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

SqlLine integration #17

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions MatCalciteDependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>sqlline</groupId>
<artifactId>sqlline</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>

<build>
Expand Down
22 changes: 20 additions & 2 deletions MatCalcitePlugin/src/com/github/vlsi/mat/calcite/Executor.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -15,22 +16,40 @@
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;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

import static org.jline.terminal.TerminalBuilder.PROP_JANSI;

public class Executor implements IApplication {

@Override
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 <heap-dump> <query> <result>");
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;
}

Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
@@ -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<String> ALLOWED_SQLLINE_COMMANDS = new HashSet<String>() {{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snuyanzin , I might be late here :) Do you remember by chance why do you limit the set of commands?

Copy link
Author

@snuyanzin snuyanzin Oct 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I remember there are database specific commands e.g. !isolation, !drop and etc.
The idea was to limit to set of commands which makes sense for mat-calcite-plugin.

Agree that the list of commands itself is the subject for discussion.

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<CommandHandler> getCommandHandlers(SqlLine sqlLine) {
Collection<CommandHandler> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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<Completer> 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 <path to file>");
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());
}
}
22 changes: 22 additions & 0 deletions MatCalcitePlugin/src/sqlline/MCPDatabaseConnection.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
27 changes: 27 additions & 0 deletions MatCalcitePlugin/src/sqlline/MCPSqlLine.java
Original file line number Diff line number Diff line change
@@ -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);
}
}