Skip to content

Commit b7c6a9d

Browse files
authored
Add CLI !config command (#43)
1 parent 3b46997 commit b7c6a9d

File tree

2 files changed

+96
-15
lines changed

2 files changed

+96
-15
lines changed

hoptimator-catalog/src/main/java/com/linkedin/hoptimator/catalog/Resource.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ public interface Environment {
157157
default Environment orElse(Environment other) {
158158
return (k, f) -> getOrDefault(k, () -> other.getOrDefault(k, f));
159159
}
160+
161+
default Environment orIgnore() {
162+
return orElse(new DummyEnvironment());
163+
}
160164
}
161165

162166
/** Basic Environment implementation */

hoptimator-cli/src/main/java/com/linkedin/hoptimator/HoptimatorCliApp.java

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.linkedin.hoptimator;
22

3+
import org.apache.calcite.rel.RelNode;
34
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
45
import sqlline.SqlLine;
56
import sqlline.CommandHandler;
67
import sqlline.DispatchCallback;
78
import org.jline.reader.Completer;
8-
9-
import org.apache.calcite.rel.RelNode;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
1011

1112
import com.linkedin.hoptimator.catalog.AvroConverter;
1213
import com.linkedin.hoptimator.catalog.Resource;
@@ -15,9 +16,6 @@
1516
import com.linkedin.hoptimator.planner.Pipeline;
1617
import com.linkedin.hoptimator.planner.PipelineRel;
1718

18-
import org.slf4j.Logger;
19-
import org.slf4j.LoggerFactory;
20-
2119
import java.util.ArrayList;
2220
import java.util.Collections;
2321
import java.util.List;
@@ -28,16 +26,21 @@
2826

2927
public class HoptimatorCliApp {
3028
private final Logger logger = LoggerFactory.getLogger(HoptimatorCliApp.class);
29+
private final Properties properties;
3130

3231
private SqlLine sqlline;
3332

33+
public HoptimatorCliApp(Properties properties) {
34+
this.properties = properties;
35+
}
36+
3437
public static void main(String[] args) throws Exception {
35-
HoptimatorCliApp app = new HoptimatorCliApp();
38+
HoptimatorCliApp app = new HoptimatorCliApp(new Properties());
3639
int result = app.run(args);
3740
System.exit(result);
3841
}
3942

40-
protected int run(String[] args) throws IOException {
43+
public int run(String[] args) throws IOException {
4144
this.sqlline = new SqlLine();
4245
Scanner scanner = new Scanner(Thread.currentThread().getContextClassLoader().getResourceAsStream("welcome.txt"));
4346
while (scanner.hasNext()) {
@@ -52,6 +55,7 @@ protected int run(String[] args) throws IOException {
5255
commandHandlers.add(new InsertCommandHandler());
5356
commandHandlers.add(new CheckCommandHandler());
5457
commandHandlers.add(new MermaidCommandHandler());
58+
commandHandlers.add(new ConfigCommandHandler());
5559
sqlline.updateCommandHandlers(commandHandlers);
5660
return sqlline.begin(args, null, true).ordinal();
5761
}
@@ -133,7 +137,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
133137

134138
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
135139
try {
136-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
140+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
137141
RelNode plan = planner.logical(sql);
138142
String avroSchema = AvroConverter.avro("OutputNamespace", "OutputName", plan.getRowType()).toString(true);
139143
sqlline.output(avroSchema);
@@ -201,14 +205,15 @@ public void execute(String line, DispatchCallback dispatchCallback) {
201205
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
202206
try {
203207
InsertInto insertInto = parseInsertInto(sql);
204-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
208+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
205209
PipelineRel plan = planner.pipeline(insertInto.query);
206210
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
207211
HopTable sink = planner.database(insertInto.database)
208212
.makeTable(insertInto.table, impl.rowType());
209213
Pipeline pipeline = impl.pipeline(sink);
210214
// TODO provide generated avro schema to environment
211-
Resource.TemplateFactory templateFactory = new Resource.SimpleTemplateFactory(new Resource.DummyEnvironment());
215+
Resource.TemplateFactory templateFactory = new Resource.SimpleTemplateFactory(
216+
new Resource.SimpleEnvironment(properties).orIgnore());
212217
sqlline.output(pipeline.render(templateFactory));
213218
dispatchCallback.setToSuccess();
214219
} catch (Exception e) {
@@ -275,7 +280,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
275280
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
276281
try {
277282
InsertInto insertInto = parseInsertInto(sql);
278-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
283+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
279284
PipelineRel plan = planner.pipeline(insertInto.query);
280285
sqlline.output("PLAN:");
281286
sqlline.output(plan.explain());
@@ -378,7 +383,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
378383
throw new IllegalArgumentException("Expected one of 'not', 'empty', or 'value'");
379384
}
380385

381-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
386+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
382387
PipelineRel plan = planner.pipeline(query);
383388
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
384389
String pipelineSql = impl.query().sql(MysqlSqlDialect.DEFAULT);
@@ -470,8 +475,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
470475
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
471476
try {
472477
InsertInto insertInto = parseInsertInto(sql);
473-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl,
474-
new Properties());
478+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
475479
PipelineRel plan = planner.pipeline(insertInto.query);
476480
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
477481
HopTable sink = planner.database(insertInto.database)
@@ -603,7 +607,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
603607
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
604608
try {
605609
InsertInto insertInto = parseInsertInto(sql);
606-
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
610+
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
607611
PipelineRel plan = planner.pipeline(insertInto.query);
608612
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
609613
HopTable sink = planner.database(insertInto.database)
@@ -628,6 +632,79 @@ public boolean echoToFile() {
628632
}
629633
}
630634

635+
private class ConfigCommandHandler implements CommandHandler {
636+
637+
@Override
638+
public String getName() {
639+
return "config";
640+
}
641+
642+
@Override
643+
public List<String> getNames() {
644+
return Collections.singletonList(getName());
645+
}
646+
647+
@Override
648+
public String getHelpText() {
649+
return "Export a Hoptimator variable to templates, operators, etc";
650+
}
651+
652+
@Override
653+
public String matches(String line) {
654+
String cmd = line;
655+
if (startsWith(cmd, SqlLine.COMMAND_PREFIX)) {
656+
cmd = cmd.substring(1);
657+
}
658+
659+
if (startsWith(cmd, "config ")) {
660+
cmd = cmd.substring("config ".length());
661+
return cmd;
662+
} else if (startsWith(cmd, "config")) {
663+
cmd = cmd.substring("config".length());
664+
return cmd;
665+
}
666+
667+
return null;
668+
}
669+
670+
@Override
671+
public void execute(String line, DispatchCallback dispatchCallback) {
672+
String cmd = line;
673+
if (startsWith(cmd, SqlLine.COMMAND_PREFIX)) {
674+
cmd = cmd.substring(1);
675+
}
676+
677+
if (startsWith(cmd, "config ")) {
678+
cmd = cmd.substring("config ".length());
679+
} else if (startsWith(cmd, "config")) {
680+
cmd = cmd.substring("config".length());
681+
}
682+
683+
String []split = cmd.split("[\\s=]+", 2);
684+
685+
if (split.length != 2) {
686+
sqlline.output("Currently defined configs:");
687+
properties.forEach((k, v) -> sqlline.output(k.toString() + "=" + v.toString()));
688+
} else {
689+
String k = split[0];
690+
String v = split[1];
691+
sqlline.output("Setting config " + k + " = " + v);
692+
properties.setProperty(k, v);
693+
}
694+
dispatchCallback.setToSuccess();
695+
}
696+
697+
@Override
698+
public List<Completer> getParameterCompleters() {
699+
return Collections.emptyList();
700+
}
701+
702+
@Override
703+
public boolean echoToFile() {
704+
return false;
705+
}
706+
}
707+
631708
// case-insensitive prefix match
632709
static boolean startsWith(String s, String prefix) {
633710
return s.matches("(?i)" + prefix + ".*");

0 commit comments

Comments
 (0)