Skip to content

Commit

Permalink
Add directory property to Session
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
julianhyde committed Jan 4, 2024
1 parent 7e4b07d commit 8f5fc92
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 13 deletions.
5 changes: 4 additions & 1 deletion morel
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ fi

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

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

# End morel
11 changes: 7 additions & 4 deletions src/main/java/net/hydromatic/morel/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import net.hydromatic.morel.compile.Tracer;
import net.hydromatic.morel.compile.Tracers;
import net.hydromatic.morel.eval.Codes;
import net.hydromatic.morel.eval.Prop;
import net.hydromatic.morel.eval.Session;
import net.hydromatic.morel.foreign.ForeignValue;
import net.hydromatic.morel.parse.MorelParserImpl;
Expand Down Expand Up @@ -69,9 +70,8 @@ public class Main {
private final boolean echo;
private final Map<String, ForeignValue> valueMap;
final TypeSystem typeSystem = new TypeSystem();
final File directory;
final boolean idempotent;
final Session session = new Session();
final Session session;

/** Command-line entry point.
*
Expand Down Expand Up @@ -102,7 +102,9 @@ public Main(List<String> argList, Reader in, Writer out,
this.out = buffer(out);
this.echo = argList.contains("--echo");
this.valueMap = ImmutableMap.copyOf(valueMap);
this.directory = requireNonNull(directory, "directory");
final Map<Prop, Object> map = new LinkedHashMap<>();
Prop.DIRECTORY.set(map, requireNonNull(directory, "directory"));
this.session = new Session(map);
this.idempotent = idempotent;
}

Expand Down Expand Up @@ -311,7 +313,8 @@ static class SubShell extends Shell {
outLines.accept("[opening " + fileName + "]");
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(main.directory, fileName);
final File directory = Prop.DIRECTORY.fileValue(main.session.map);
file = new File(directory, fileName);
}
if (!file.exists()) {
outLines.accept("[use failed: Io: openIn failed on "
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/net/hydromatic/morel/Shell.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import net.hydromatic.morel.compile.Tracer;
import net.hydromatic.morel.compile.Tracers;
import net.hydromatic.morel.eval.Codes;
import net.hydromatic.morel.eval.Prop;
import net.hydromatic.morel.eval.Session;
import net.hydromatic.morel.foreign.Calcite;
import net.hydromatic.morel.foreign.DataSet;
Expand Down Expand Up @@ -259,8 +260,10 @@ public void run() {

pause();
final TypeSystem typeSystem = new TypeSystem();
final Map<Prop, Object> map = new LinkedHashMap<>();
Prop.DIRECTORY.set(map, config.directory);
final Session session = new Session(map);
Environment env = Environments.env(typeSystem, config.valueMap);
final Session session = new Session();
final LineFn lineFn =
new TerminalLineFn(minusPrompt, equalsPrompt, lineReader);
final SubShell subShell =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ Code toRel4(Environment env, Code code, Type type) {

@Override protected CalciteFunctions.Context createContext(
Environment env) {
final Session dummySession = new Session();
final Session dummySession = new Session(ImmutableMap.of());
return new CalciteFunctions.Context(dummySession, env, typeSystem,
calcite.dataContext.getTypeFactory());
}
Expand Down Expand Up @@ -308,7 +308,7 @@ Code toRel4(Environment env, Code code, Type type) {
new RelJson(jsonBuilder).toJson(rowType));
final String morelCode = apply.toString();
ThreadLocals.let(CalciteFunctions.THREAD_ENV,
new CalciteFunctions.Context(new Session(), cx.env,
new CalciteFunctions.Context(new Session(ImmutableMap.of()), cx.env,
typeSystem, cx.relBuilder.getTypeFactory()), () ->
cx.relBuilder.functionScan(CalciteFunctions.TABLE_OPERATOR, 0,
cx.relBuilder.literal(morelCode),
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/hydromatic/morel/compile/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import net.hydromatic.morel.util.ThreadLocals;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import org.apache.calcite.util.Util;
Expand Down Expand Up @@ -133,7 +134,7 @@ public void eval(Session session, Environment env,
* not created a session yet. Lifecycle confusion.
* </ul> */
protected CalciteFunctions.Context createContext(Environment env) {
final Session dummySession = new Session();
final Session dummySession = new Session(ImmutableMap.of());
return new CalciteFunctions.Context(dummySession, env, typeSystem, null);
}

Expand Down
28 changes: 28 additions & 0 deletions src/main/java/net/hydromatic/morel/eval/Prop.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableMap;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;

Expand All @@ -29,6 +30,15 @@
* @see Session#map
*/
public enum Prop {
/** File property "directory" is the path of the directory that the
* {@code file} variable maps to in this connection.
*
* <p>The default value is the empty string;
* many tests use the "src/test/resources" directory;
* when launched via the {@code morel} shell script, the default value is the
* shell's current directory. */
DIRECTORY("directory", File.class, new File("")),

/** Boolean property "hybrid" controls whether to try to create a hybrid
* execution plan that uses Apache Calcite relational algebra wherever
* possible. Default is false. */
Expand Down Expand Up @@ -114,6 +124,10 @@ public enum Prop {
assert defaultValue == null || defaultValue.getClass() == type;
} else if (type == Integer.class) {
assert defaultValue == null || defaultValue.getClass() == type;
} else if (type == String.class) {
assert defaultValue == null || defaultValue.getClass() == type;
} else if (type == File.class) {
assert defaultValue == null || defaultValue.getClass() == type;
} else {
throw new AssertionError("not a valid property type: "
+ type);
Expand Down Expand Up @@ -149,6 +163,20 @@ public int intValue(Map<Prop, Object> map) {
return this.<Integer>typeValue(o);
}

/** Returns the value of a string property. */
public String stringValue(Map<Prop, Object> map) {
assert type == String.class;
Object o = map.get(this);
return this.typeValue(o);
}

/** Returns the value of a file property. */
public File fileValue(Map<Prop, Object> map) {
assert type == File.class;
Object o = map.get(this);
return this.typeValue(o);
}

@SuppressWarnings("unchecked")
private <T> T typeValue(Object o) {
if (o == null) {
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/net/hydromatic/morel/eval/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,23 @@ public class Session {
/** The output lines of the previous command. */
public List<String> out;
/** Property values. */
public final Map<Prop, Object> map = new LinkedHashMap<>();
public final Map<Prop, Object> map;

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

/** Creates a Session.
*
* <p>The {@code map} parameter, that becomes the property map, is used as is,
* not copied. It may be immutable if the session is for a narrow, internal
* use. Otherwise, it should probably be a {@link LinkedHashMap} to provide
* deterministic iteration order.
*
* @param map Map that contains property values */
public Session(Map<Prop, Object> map) {
this.map = map;
}

/** Calls some code with a new value of {@link Shell}. */
public void withShell(Shell shell, Consumer<String> outLines,
Consumer<Session> consumer) {
Expand Down
5 changes: 2 additions & 3 deletions src/test/java/net/hydromatic/morel/Ml.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ Ml withPrepare(Consumer<CompiledStatement> action) {
final TypeSystem typeSystem = new TypeSystem();
final AstNode statement = parser.statementEof();
final Environment env = Environments.empty();
final Session session = new Session();
final Session session = new Session(propMap);
final List<CompileException> warningList = new ArrayList<>();
final CompiledStatement compiled =
Compiles.prepareStatement(typeSystem, session, env, statement,
Expand Down Expand Up @@ -428,8 +428,7 @@ Ml assertEval(Matcher<Object> resultMatcher) {

Ml assertEval() {
return withValidate((resolved, calcite) -> {
final Session session = new Session();
session.map.putAll(propMap);
final Session session = new Session(propMap);
eval(session, resolved.env, resolved.typeMap.typeSystem, resolved.node,
calcite);
});
Expand Down

0 comments on commit 8f5fc92

Please sign in to comment.