diff --git a/MatCalciteDependencies/pom.xml b/MatCalciteDependencies/pom.xml
index 68a289c..d5e80d3 100644
--- a/MatCalciteDependencies/pom.xml
+++ b/MatCalciteDependencies/pom.xml
@@ -24,6 +24,11 @@
jsr305
3.0.2
+
+ sqlline
+ sqlline
+ 1.9.0
+
diff --git a/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/Executor.java b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/Executor.java
index 99511b3..30ca101 100644
--- a/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/Executor.java
+++ b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/Executor.java
@@ -1,5 +1,6 @@
package com.github.vlsi.mat.calcite;
+import sqlline.MCPSqlLine;
import com.google.common.base.Joiner;
import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;
@@ -15,6 +16,7 @@
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
+import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -22,6 +24,8 @@
import java.util.ArrayList;
import java.util.List;
+import static org.jline.terminal.TerminalBuilder.PROP_JANSI;
+
public class Executor implements IApplication {
@Override
@@ -29,8 +33,23 @@ public Object start(IApplicationContext context) {
String[] args = (String[]) context.getArguments().get("application.args");
char delimiter = ',';
- if (args.length < 3) {
+ if (args.length == 0 || (args.length < 3 && !"sqlline".equalsIgnoreCase(args[0]))) {
System.out.println("java com.github.vlsi.mat.calcite.Executor ");
+ System.out.println("java com.github.vlsi.mat.calcite.Executor sqlline");
+ return IApplication.EXIT_OK;
+ }
+
+ if ("sqlline".equalsIgnoreCase(args[0])) {
+ try {
+ System.setProperty(PROP_JANSI, Boolean.TRUE.toString());
+ MCPSqlLine sqlLine = new MCPSqlLine();
+ String[] sqllineArgs = new String[args.length - 1];
+ System.arraycopy(args, 1, sqllineArgs, 0, args.length - 1);
+ sqlLine.begin(sqllineArgs, null, false);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return IApplication.EXIT_OK;
+ }
return IApplication.EXIT_OK;
}
@@ -57,7 +76,6 @@ public Object start(IApplicationContext context) {
return IApplication.EXIT_OK;
}
-
try (Connection con = CalciteDataSource.getConnection(openSnapshot(heapFile));
BufferedWriter w = new BufferedWriter(new FileWriter(resultsFile))) {
PreparedStatement ps = con.prepareStatement(sbQuery.toString());
diff --git a/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/DumpFileNameCompleter.java b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/DumpFileNameCompleter.java
new file mode 100644
index 0000000..1397301
--- /dev/null
+++ b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/DumpFileNameCompleter.java
@@ -0,0 +1,19 @@
+package com.github.vlsi.mat.calcite.cli;
+
+import org.jline.builtins.Completers;
+
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+
+public class DumpFileNameCompleter extends Completers.FileNameCompleter {
+ private static final PathMatcher DUMP_FILE_MATCHER =
+ FileSystems.getDefault().getPathMatcher("glob:**.{bin,hprof}");
+
+ @Override
+ protected boolean accept(Path path) {
+ return super.accept(path)
+ && (Files.isDirectory(path) || DUMP_FILE_MATCHER.matches(path));
+ }
+}
diff --git a/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/MCPApplication.java b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/MCPApplication.java
new file mode 100644
index 0000000..3762782
--- /dev/null
+++ b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/MCPApplication.java
@@ -0,0 +1,48 @@
+package com.github.vlsi.mat.calcite.cli;
+
+import sqlline.Application;
+import sqlline.CommandHandler;
+import sqlline.MCPSqlLine;
+import sqlline.SqlLine;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public class MCPApplication extends Application {
+ private static final Set ALLOWED_SQLLINE_COMMANDS = new HashSet() {{
+ add("quit");
+ add("history");
+ add("verbose");
+ add("run");
+ add("list");
+ add("all");
+ add("go");
+ add("script");
+ add("record");
+ add("brief");
+ add("close");
+ add("closeall");
+ add("outputformat");
+ add("set");
+ add("help");
+ add("reset");
+ add("save");
+ add("rerun");
+ add("prompthandler");
+ }};
+
+ @Override
+ public Collection getCommandHandlers(SqlLine sqlLine) {
+ Collection handlers = new ArrayList<>();
+ for (CommandHandler commandHandler : super.getCommandHandlers(sqlLine)) {
+ if (ALLOWED_SQLLINE_COMMANDS.contains(commandHandler.getName())) {
+ handlers.add(commandHandler);
+ }
+ }
+ handlers.add(new OpenDumpCommandHandler((MCPSqlLine) sqlLine, new DumpFileNameCompleter(), "Open heap dump",
+ "open_dump"));
+ return handlers;
+ }
+}
diff --git a/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/OpenDumpCommandHandler.java b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/OpenDumpCommandHandler.java
new file mode 100644
index 0000000..19e0a44
--- /dev/null
+++ b/MatCalcitePlugin/src/com/github/vlsi/mat/calcite/cli/OpenDumpCommandHandler.java
@@ -0,0 +1,68 @@
+package com.github.vlsi.mat.calcite.cli;
+
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.SnapshotFactory;
+import org.eclipse.mat.util.VoidProgressListener;
+import org.jline.reader.Completer;
+import sqlline.AbstractCommandHandler;
+import sqlline.Commands;
+import sqlline.DispatchCallback;
+import sqlline.MCPDatabaseConnection;
+import sqlline.MCPSqlLine;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+public class OpenDumpCommandHandler extends AbstractCommandHandler {
+ public OpenDumpCommandHandler(MCPSqlLine sqlLine, List completers,
+ String helpText, String... cmds) {
+ super(sqlLine, cmds, helpText, completers);
+ }
+
+ public OpenDumpCommandHandler(MCPSqlLine sqlLine, Completer completer,
+ String helpText, String... cmds) {
+ this(sqlLine, Collections.singletonList(completer), helpText, cmds);
+ }
+
+ public void execute(String line, DispatchCallback callback) {
+ final String[] parts = sqlLine.split(line, " ", 0);
+ if (parts.length != 2) {
+ sqlLine.error("Usage: open_dump ");
+ callback.setToFailure();
+ return;
+ }
+ // replace ~/ with user directory
+ final String filename = Commands.expand(parts[1]);
+ if (!new File(filename).isFile()) {
+ sqlLine.error("Dump file " + filename + " does not exists!");
+ callback.setToFailure();
+ return;
+ }
+
+ final MCPSqlLine mcpSqlLine = (MCPSqlLine) sqlLine;
+ final MCPDatabaseConnection mcpDatabaseConnection;
+ try {
+ mcpDatabaseConnection = new MCPDatabaseConnection(mcpSqlLine, filename, openSnapshot(new File(filename)));
+ } catch (SnapshotException e) {
+ callback.setToFailure();
+ mcpSqlLine.error(e);
+ return;
+ }
+ try {
+ mcpSqlLine.setUpConnection(mcpDatabaseConnection);
+ callback.setToSuccess();
+ } catch (Exception e) {
+ mcpDatabaseConnection.close();
+ mcpSqlLine.removeConnection(mcpDatabaseConnection);
+ callback.setToFailure();
+ mcpSqlLine.error(e);
+ }
+ }
+
+ private static ISnapshot openSnapshot(File heapDump) throws SnapshotException {
+ System.out.println("exists = " + heapDump.exists() + ", file = " + heapDump.getAbsolutePath());
+ return SnapshotFactory.openSnapshot(heapDump, new VoidProgressListener());
+ }
+}
diff --git a/MatCalcitePlugin/src/sqlline/MCPDatabaseConnection.java b/MatCalcitePlugin/src/sqlline/MCPDatabaseConnection.java
new file mode 100644
index 0000000..28cc2ba
--- /dev/null
+++ b/MatCalcitePlugin/src/sqlline/MCPDatabaseConnection.java
@@ -0,0 +1,22 @@
+package sqlline;
+
+import com.github.vlsi.mat.calcite.CalciteDataSource;
+
+import org.eclipse.mat.snapshot.ISnapshot;
+
+import java.sql.SQLException;
+
+public class MCPDatabaseConnection extends DatabaseConnection {
+ private final ISnapshot snapshot;
+
+ public MCPDatabaseConnection(MCPSqlLine sqlLine, String filename, ISnapshot snapshot) {
+ super(sqlLine, null, filename, "username", "password", null);
+ this.snapshot = snapshot;
+ }
+
+ @Override
+ boolean connect() throws SQLException {
+ connection = CalciteDataSource.getConnection(snapshot);
+ return true;
+ }
+}
diff --git a/MatCalcitePlugin/src/sqlline/MCPSqlLine.java b/MatCalcitePlugin/src/sqlline/MCPSqlLine.java
new file mode 100644
index 0000000..bb45866
--- /dev/null
+++ b/MatCalcitePlugin/src/sqlline/MCPSqlLine.java
@@ -0,0 +1,27 @@
+package sqlline;
+
+import com.github.vlsi.mat.calcite.cli.MCPApplication;
+
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+public class MCPSqlLine extends SqlLine {
+ void setAppConfig(Application application) {
+ super.setAppConfig(new MCPApplication());
+ }
+
+ public void setUpConnection(final MCPDatabaseConnection mcpDatabaseConnection) throws SQLException {
+ getDatabaseConnections().setConnection(mcpDatabaseConnection);
+ Connection connection = getDatabaseConnection().getConnection();
+ mcpDatabaseConnection.meta = (DatabaseMetaData) Proxy.newProxyInstance(
+ DatabaseMetaData.class.getClassLoader(),
+ new Class[]{DatabaseMetaData.class},
+ new DatabaseMetaDataHandler(connection.getMetaData()));
+ }
+
+ public void removeConnection(final MCPDatabaseConnection mcpDatabaseConnection) {
+ getDatabaseConnections().removeConnection(mcpDatabaseConnection);
+ }
+}