package com.github.vlsi.mat.calcite; import com.github.vlsi.mat.calcite.neo.PackageSchema; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import org.apache.calcite.jdbc.CalciteConnection; import org.apache.calcite.schema.Schema; import org.apache.calcite.schema.SchemaPlus; import org.codehaus.commons.compiler.CompilerFactoryFactory; import org.eclipse.mat.snapshot.ISnapshot; import java.sql.*; import java.util.Properties; import java.util.concurrent.ExecutionException; public class CalciteDataSource { private static LoadingCache<ISnapshot, Schema> SCHEMA_CACHE = CacheBuilder .newBuilder() .weakKeys().build(new CacheLoader<ISnapshot, Schema>() { @Override public Schema load(ISnapshot key) throws Exception { // return new HeapSchema(key); return PackageSchema.resolveSchema(key); } }); private static boolean initCompilerDone; public static Connection getConnection(ISnapshot snapshot) throws SQLException { initJanino(); try { Class.forName("org.apache.calcite.jdbc.Driver"); } catch (ClassNotFoundException e) { throw new SQLException( "Unable to load Calcite JDBC driver", e); } Properties info = new Properties(); info.put("lex", "JAVA"); info.put("quoting", "DOUBLE_QUOTE"); info.put("conformance", "LENIENT"); // enable cross apply, etc Connection connection = DriverManager.getConnection( "jdbc:calcite:", info); CalciteConnection con = connection .unwrap(CalciteConnection.class); if (snapshot == null) return connection; if ("HEAP".equals(con.getSchema())) return connection; SchemaPlus root = con.getRootSchema(); Schema heapSchema; try { heapSchema = SCHEMA_CACHE.get(snapshot); } catch (ExecutionException e) { throw new SQLException("Unable to create heap schema", e); } root.add("HEAP", heapSchema); con.setSchema("HEAP"); return connection; } private static void initJanino() throws SQLException { // For unknown reason, threadContextClassLoader.getResource("org.codehaus.commons.compiler.properties") // returns null when accessed via BundleClassLoader // We make a shortcut // Some OSGi WA might probably exist if (initCompilerDone) { return; } initCompilerDone = true; Thread currentThread = Thread.currentThread(); ClassLoader cl = currentThread.getContextClassLoader(); try{ currentThread.setContextClassLoader(CompilerFactoryFactory.class.getClassLoader()); if (CompilerFactoryFactory.getDefaultCompilerFactory() == null) { throw new SQLException("Janino compiler is not initialized: CompilerFactoryFactory.getDefaultCompilerFactory() == null"); }; } catch (Exception e) { throw new SQLException("Unable to load Janino compiler", e); } finally { currentThread.setContextClassLoader(cl); } } public static void close(ResultSet rs, Statement st, Connection con) { if (rs != null) try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } if (st != null) try { st.close(); } catch (SQLException e) { e.printStackTrace(); } if (con != null) try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } }