Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CLI !config command #43

Merged
merged 1 commit into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ public interface Environment {
default Environment orElse(Environment other) {
return (k, f) -> getOrDefault(k, () -> other.getOrDefault(k, f));
}

default Environment orIgnore() {
return orElse(new DummyEnvironment());
}
}

/** Basic Environment implementation */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.linkedin.hoptimator;

import org.apache.calcite.rel.RelNode;
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
import sqlline.SqlLine;
import sqlline.CommandHandler;
import sqlline.DispatchCallback;
import org.jline.reader.Completer;

import org.apache.calcite.rel.RelNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.linkedin.hoptimator.catalog.AvroConverter;
import com.linkedin.hoptimator.catalog.Resource;
Expand All @@ -15,9 +16,6 @@
import com.linkedin.hoptimator.planner.Pipeline;
import com.linkedin.hoptimator.planner.PipelineRel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -28,16 +26,21 @@

public class HoptimatorCliApp {
private final Logger logger = LoggerFactory.getLogger(HoptimatorCliApp.class);
private final Properties properties;

private SqlLine sqlline;

public HoptimatorCliApp(Properties properties) {
this.properties = properties;
}

public static void main(String[] args) throws Exception {
HoptimatorCliApp app = new HoptimatorCliApp();
HoptimatorCliApp app = new HoptimatorCliApp(new Properties());
int result = app.run(args);
System.exit(result);
}

protected int run(String[] args) throws IOException {
public int run(String[] args) throws IOException {
this.sqlline = new SqlLine();
Scanner scanner = new Scanner(Thread.currentThread().getContextClassLoader().getResourceAsStream("welcome.txt"));
while (scanner.hasNext()) {
Expand All @@ -52,6 +55,7 @@ protected int run(String[] args) throws IOException {
commandHandlers.add(new InsertCommandHandler());
commandHandlers.add(new CheckCommandHandler());
commandHandlers.add(new MermaidCommandHandler());
commandHandlers.add(new ConfigCommandHandler());
sqlline.updateCommandHandlers(commandHandlers);
return sqlline.begin(args, null, true).ordinal();
}
Expand Down Expand Up @@ -133,7 +137,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {

String connectionUrl = sqlline.getConnectionMetadata().getUrl();
try {
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
RelNode plan = planner.logical(sql);
String avroSchema = AvroConverter.avro("OutputNamespace", "OutputName", plan.getRowType()).toString(true);
sqlline.output(avroSchema);
Expand Down Expand Up @@ -201,14 +205,15 @@ public void execute(String line, DispatchCallback dispatchCallback) {
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
try {
InsertInto insertInto = parseInsertInto(sql);
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
PipelineRel plan = planner.pipeline(insertInto.query);
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
HopTable sink = planner.database(insertInto.database)
.makeTable(insertInto.table, impl.rowType());
Pipeline pipeline = impl.pipeline(sink);
// TODO provide generated avro schema to environment
Resource.TemplateFactory templateFactory = new Resource.SimpleTemplateFactory(new Resource.DummyEnvironment());
Resource.TemplateFactory templateFactory = new Resource.SimpleTemplateFactory(
new Resource.SimpleEnvironment(properties).orIgnore());
sqlline.output(pipeline.render(templateFactory));
dispatchCallback.setToSuccess();
} catch (Exception e) {
Expand Down Expand Up @@ -275,7 +280,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
try {
InsertInto insertInto = parseInsertInto(sql);
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
PipelineRel plan = planner.pipeline(insertInto.query);
sqlline.output("PLAN:");
sqlline.output(plan.explain());
Expand Down Expand Up @@ -378,7 +383,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
throw new IllegalArgumentException("Expected one of 'not', 'empty', or 'value'");
}

HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
PipelineRel plan = planner.pipeline(query);
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
String pipelineSql = impl.query().sql(MysqlSqlDialect.DEFAULT);
Expand Down Expand Up @@ -470,8 +475,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
try {
InsertInto insertInto = parseInsertInto(sql);
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl,
new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
PipelineRel plan = planner.pipeline(insertInto.query);
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
HopTable sink = planner.database(insertInto.database)
Expand Down Expand Up @@ -603,7 +607,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
String connectionUrl = sqlline.getConnectionMetadata().getUrl();
try {
InsertInto insertInto = parseInsertInto(sql);
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, new Properties());
HoptimatorPlanner planner = HoptimatorPlanner.fromModelFile(connectionUrl, properties);
PipelineRel plan = planner.pipeline(insertInto.query);
PipelineRel.Implementor impl = new PipelineRel.Implementor(plan);
HopTable sink = planner.database(insertInto.database)
Expand All @@ -628,6 +632,79 @@ public boolean echoToFile() {
}
}

private class ConfigCommandHandler implements CommandHandler {

@Override
public String getName() {
return "config";
}

@Override
public List<String> getNames() {
return Collections.singletonList(getName());
}

@Override
public String getHelpText() {
return "Export a Hoptimator variable to templates, operators, etc";
}

@Override
public String matches(String line) {
String cmd = line;
if (startsWith(cmd, SqlLine.COMMAND_PREFIX)) {
cmd = cmd.substring(1);
}

if (startsWith(cmd, "config ")) {
cmd = cmd.substring("config ".length());
return cmd;
} else if (startsWith(cmd, "config")) {
cmd = cmd.substring("config".length());
return cmd;
}

return null;
}

@Override
public void execute(String line, DispatchCallback dispatchCallback) {
String cmd = line;
if (startsWith(cmd, SqlLine.COMMAND_PREFIX)) {
cmd = cmd.substring(1);
}

if (startsWith(cmd, "config ")) {
cmd = cmd.substring("config ".length());
} else if (startsWith(cmd, "config")) {
cmd = cmd.substring("config".length());
}

String []split = cmd.split("[\\s=]+", 2);

if (split.length != 2) {
sqlline.output("Currently defined configs:");
properties.forEach((k, v) -> sqlline.output(k.toString() + "=" + v.toString()));
} else {
String k = split[0];
String v = split[1];
sqlline.output("Setting config " + k + " = " + v);
properties.setProperty(k, v);
}
dispatchCallback.setToSuccess();
}

@Override
public List<Completer> getParameterCompleters() {
return Collections.emptyList();
}

@Override
public boolean echoToFile() {
return false;
}
}

// case-insensitive prefix match
static boolean startsWith(String s, String prefix) {
return s.matches("(?i)" + prefix + ".*");
Expand Down