Skip to content

Commit 8f5fc92

Browse files
committed
Add directory property to Session
The directory is used by the `use` command (for running scripts) and the `file` value (for opening files as tables). When launched via the `morel` script the default directory is the current directory, but can be overridden using the `--directory` flag. Allow properties (`class Prop`) to be of type String or File (in addition to Integer and Boolean).
1 parent 7e4b07d commit 8f5fc92

File tree

8 files changed

+62
-13
lines changed

8 files changed

+62
-13
lines changed

morel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ fi
5252

5353
export JAVA_OPTS=-Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
5454

55-
exec java $VM_OPTS -cp "${CP}" $JAVA_OPTS net.hydromatic.morel.Shell --foreign='net.hydromatic.morel.BuiltInDataSet$Dictionary' "$@"
55+
exec java $VM_OPTS -cp "${CP}" $JAVA_OPTS net.hydromatic.morel.Shell \
56+
--foreign='net.hydromatic.morel.BuiltInDataSet$Dictionary' \
57+
--directory="$(pwd)" \
58+
"$@"
5659

5760
# End morel

src/main/java/net/hydromatic/morel/Main.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import net.hydromatic.morel.compile.Tracer;
2828
import net.hydromatic.morel.compile.Tracers;
2929
import net.hydromatic.morel.eval.Codes;
30+
import net.hydromatic.morel.eval.Prop;
3031
import net.hydromatic.morel.eval.Session;
3132
import net.hydromatic.morel.foreign.ForeignValue;
3233
import net.hydromatic.morel.parse.MorelParserImpl;
@@ -69,9 +70,8 @@ public class Main {
6970
private final boolean echo;
7071
private final Map<String, ForeignValue> valueMap;
7172
final TypeSystem typeSystem = new TypeSystem();
72-
final File directory;
7373
final boolean idempotent;
74-
final Session session = new Session();
74+
final Session session;
7575

7676
/** Command-line entry point.
7777
*
@@ -102,7 +102,9 @@ public Main(List<String> argList, Reader in, Writer out,
102102
this.out = buffer(out);
103103
this.echo = argList.contains("--echo");
104104
this.valueMap = ImmutableMap.copyOf(valueMap);
105-
this.directory = requireNonNull(directory, "directory");
105+
final Map<Prop, Object> map = new LinkedHashMap<>();
106+
Prop.DIRECTORY.set(map, requireNonNull(directory, "directory"));
107+
this.session = new Session(map);
106108
this.idempotent = idempotent;
107109
}
108110

@@ -311,7 +313,8 @@ static class SubShell extends Shell {
311313
outLines.accept("[opening " + fileName + "]");
312314
File file = new File(fileName);
313315
if (!file.isAbsolute()) {
314-
file = new File(main.directory, fileName);
316+
final File directory = Prop.DIRECTORY.fileValue(main.session.map);
317+
file = new File(directory, fileName);
315318
}
316319
if (!file.exists()) {
317320
outLines.accept("[use failed: Io: openIn failed on "

src/main/java/net/hydromatic/morel/Shell.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import net.hydromatic.morel.compile.Tracer;
2929
import net.hydromatic.morel.compile.Tracers;
3030
import net.hydromatic.morel.eval.Codes;
31+
import net.hydromatic.morel.eval.Prop;
3132
import net.hydromatic.morel.eval.Session;
3233
import net.hydromatic.morel.foreign.Calcite;
3334
import net.hydromatic.morel.foreign.DataSet;
@@ -259,8 +260,10 @@ public void run() {
259260

260261
pause();
261262
final TypeSystem typeSystem = new TypeSystem();
263+
final Map<Prop, Object> map = new LinkedHashMap<>();
264+
Prop.DIRECTORY.set(map, config.directory);
265+
final Session session = new Session(map);
262266
Environment env = Environments.env(typeSystem, config.valueMap);
263-
final Session session = new Session();
264267
final LineFn lineFn =
265268
new TerminalLineFn(minusPrompt, equalsPrompt, lineReader);
266269
final SubShell subShell =

src/main/java/net/hydromatic/morel/compile/CalciteCompiler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ Code toRel4(Environment env, Code code, Type type) {
176176

177177
@Override protected CalciteFunctions.Context createContext(
178178
Environment env) {
179-
final Session dummySession = new Session();
179+
final Session dummySession = new Session(ImmutableMap.of());
180180
return new CalciteFunctions.Context(dummySession, env, typeSystem,
181181
calcite.dataContext.getTypeFactory());
182182
}
@@ -308,7 +308,7 @@ Code toRel4(Environment env, Code code, Type type) {
308308
new RelJson(jsonBuilder).toJson(rowType));
309309
final String morelCode = apply.toString();
310310
ThreadLocals.let(CalciteFunctions.THREAD_ENV,
311-
new CalciteFunctions.Context(new Session(), cx.env,
311+
new CalciteFunctions.Context(new Session(ImmutableMap.of()), cx.env,
312312
typeSystem, cx.relBuilder.getTypeFactory()), () ->
313313
cx.relBuilder.functionScan(CalciteFunctions.TABLE_OPERATOR, 0,
314314
cx.relBuilder.literal(morelCode),

src/main/java/net/hydromatic/morel/compile/Compiler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import net.hydromatic.morel.util.ThreadLocals;
4848

4949
import com.google.common.collect.ImmutableList;
50+
import com.google.common.collect.ImmutableMap;
5051
import com.google.common.collect.ImmutableSet;
5152
import com.google.common.collect.ImmutableSortedMap;
5253
import org.apache.calcite.util.Util;
@@ -133,7 +134,7 @@ public void eval(Session session, Environment env,
133134
* not created a session yet. Lifecycle confusion.
134135
* </ul> */
135136
protected CalciteFunctions.Context createContext(Environment env) {
136-
final Session dummySession = new Session();
137+
final Session dummySession = new Session(ImmutableMap.of());
137138
return new CalciteFunctions.Context(dummySession, env, typeSystem, null);
138139
}
139140

src/main/java/net/hydromatic/morel/eval/Prop.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.common.base.CaseFormat;
2222
import com.google.common.collect.ImmutableMap;
2323

24+
import java.io.File;
2425
import java.util.LinkedHashMap;
2526
import java.util.Map;
2627

@@ -29,6 +30,15 @@
2930
* @see Session#map
3031
*/
3132
public enum Prop {
33+
/** File property "directory" is the path of the directory that the
34+
* {@code file} variable maps to in this connection.
35+
*
36+
* <p>The default value is the empty string;
37+
* many tests use the "src/test/resources" directory;
38+
* when launched via the {@code morel} shell script, the default value is the
39+
* shell's current directory. */
40+
DIRECTORY("directory", File.class, new File("")),
41+
3242
/** Boolean property "hybrid" controls whether to try to create a hybrid
3343
* execution plan that uses Apache Calcite relational algebra wherever
3444
* possible. Default is false. */
@@ -114,6 +124,10 @@ public enum Prop {
114124
assert defaultValue == null || defaultValue.getClass() == type;
115125
} else if (type == Integer.class) {
116126
assert defaultValue == null || defaultValue.getClass() == type;
127+
} else if (type == String.class) {
128+
assert defaultValue == null || defaultValue.getClass() == type;
129+
} else if (type == File.class) {
130+
assert defaultValue == null || defaultValue.getClass() == type;
117131
} else {
118132
throw new AssertionError("not a valid property type: "
119133
+ type);
@@ -149,6 +163,20 @@ public int intValue(Map<Prop, Object> map) {
149163
return this.<Integer>typeValue(o);
150164
}
151165

166+
/** Returns the value of a string property. */
167+
public String stringValue(Map<Prop, Object> map) {
168+
assert type == String.class;
169+
Object o = map.get(this);
170+
return this.typeValue(o);
171+
}
172+
173+
/** Returns the value of a file property. */
174+
public File fileValue(Map<Prop, Object> map) {
175+
assert type == File.class;
176+
Object o = map.get(this);
177+
return this.typeValue(o);
178+
}
179+
152180
@SuppressWarnings("unchecked")
153181
private <T> T typeValue(Object o) {
154182
if (o == null) {

src/main/java/net/hydromatic/morel/eval/Session.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,23 @@ public class Session {
3939
/** The output lines of the previous command. */
4040
public List<String> out;
4141
/** Property values. */
42-
public final Map<Prop, Object> map = new LinkedHashMap<>();
42+
public final Map<Prop, Object> map;
4343

4444
/** Implementation of "use". */
4545
private Shell shell = Shells.INSTANCE;
4646

47+
/** Creates a Session.
48+
*
49+
* <p>The {@code map} parameter, that becomes the property map, is used as is,
50+
* not copied. It may be immutable if the session is for a narrow, internal
51+
* use. Otherwise, it should probably be a {@link LinkedHashMap} to provide
52+
* deterministic iteration order.
53+
*
54+
* @param map Map that contains property values */
55+
public Session(Map<Prop, Object> map) {
56+
this.map = map;
57+
}
58+
4759
/** Calls some code with a new value of {@link Shell}. */
4860
public void withShell(Shell shell, Consumer<String> outLines,
4961
Consumer<Session> consumer) {

src/test/java/net/hydromatic/morel/Ml.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ Ml withPrepare(Consumer<CompiledStatement> action) {
267267
final TypeSystem typeSystem = new TypeSystem();
268268
final AstNode statement = parser.statementEof();
269269
final Environment env = Environments.empty();
270-
final Session session = new Session();
270+
final Session session = new Session(propMap);
271271
final List<CompileException> warningList = new ArrayList<>();
272272
final CompiledStatement compiled =
273273
Compiles.prepareStatement(typeSystem, session, env, statement,
@@ -428,8 +428,7 @@ Ml assertEval(Matcher<Object> resultMatcher) {
428428

429429
Ml assertEval() {
430430
return withValidate((resolved, calcite) -> {
431-
final Session session = new Session();
432-
session.map.putAll(propMap);
431+
final Session session = new Session(propMap);
433432
eval(session, resolved.env, resolved.typeMap.typeSystem, resolved.node,
434433
calcite);
435434
});

0 commit comments

Comments
 (0)