[CALCITE-1772] Add a hook to allow RelNode expressions to be executed by JDBC driver
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/9c10c3da Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/9c10c3da Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/9c10c3da Branch: refs/heads/master Commit: 9c10c3da15ee65190cca4767d9a52406ba9ba1b0 Parents: bb74e5a Author: Julian Hyde <[email protected]> Authored: Mon May 1 20:22:35 2017 -0700 Committer: Julian Hyde <[email protected]> Committed: Mon May 1 20:26:02 2017 -0700 ---------------------------------------------------------------------- .../apache/calcite/jdbc/CalciteMetaImpl.java | 24 ++++++++++++++++++-- .../java/org/apache/calcite/runtime/Hook.java | 6 +++++ .../org/apache/calcite/test/CalciteAssert.java | 19 ++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/9c10c3da/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java index 1cd88e4..95bca51 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java @@ -43,6 +43,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactoryImpl; import org.apache.calcite.rel.type.RelDataTypeField; import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.runtime.FlatLists; +import org.apache.calcite.runtime.Hook; import org.apache.calcite.schema.Schema; import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.schema.Table; @@ -51,6 +52,10 @@ import org.apache.calcite.server.CalciteServerStatement; import org.apache.calcite.sql.SqlJdbcFunctionCall; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.tools.FrameworkConfig; +import org.apache.calcite.tools.Frameworks; +import org.apache.calcite.util.Holder; +import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; import com.google.common.annotations.VisibleForTesting; @@ -569,7 +574,7 @@ public class CalciteMetaImpl extends MetaImpl { throw new AssertionError("missing statement", e); } h.signature = - calciteConnection.parseQuery(CalcitePrepare.Query.of(sql), + calciteConnection.parseQuery(toQuery(statement, sql), statement.createPrepareContext(), maxRowCount); statement.setSignature(h.signature); return h; @@ -592,7 +597,7 @@ public class CalciteMetaImpl extends MetaImpl { final CalciteConnectionImpl calciteConnection = getConnection(); CalciteServerStatement statement = calciteConnection.server.getStatement(h); - signature = calciteConnection.parseQuery(CalcitePrepare.Query.of(sql), + signature = calciteConnection.parseQuery(toQuery(statement, sql), statement.createPrepareContext(), maxRowCount); statement.setSignature(signature); callback.assign(signature, null, -1); @@ -607,6 +612,21 @@ public class CalciteMetaImpl extends MetaImpl { // TODO: share code with prepare and createIterable } + /** Wraps the SQL string in a + * {@link org.apache.calcite.jdbc.CalcitePrepare.Query} object, giving the + * {@link Hook#STRING_TO_QUERY} hook chance to override. */ + private CalcitePrepare.Query<Object> toQuery( + CalciteServerStatement statement, String sql) { + final Holder<CalcitePrepare.Query<Object>> queryHolder = + Holder.of(CalcitePrepare.Query.of(sql)); + final FrameworkConfig config = Frameworks.newConfigBuilder() + .parserConfig(SqlParser.Config.DEFAULT) + .defaultSchema(statement.createPrepareContext().getRootSchema().plus()) + .build(); + Hook.STRING_TO_QUERY.run(Pair.of(config, queryHolder)); + return queryHolder.get(); + } + @Override public Frame fetch(StatementHandle h, long offset, int fetchMaxRowCount) throws NoSuchStatementException { final CalciteConnectionImpl calciteConnection = getConnection(); http://git-wip-us.apache.org/repos/asf/calcite/blob/9c10c3da/core/src/main/java/org/apache/calcite/runtime/Hook.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/runtime/Hook.java b/core/src/main/java/org/apache/calcite/runtime/Hook.java index 301ac94..2936bcc 100644 --- a/core/src/main/java/org/apache/calcite/runtime/Hook.java +++ b/core/src/main/java/org/apache/calcite/runtime/Hook.java @@ -47,6 +47,12 @@ public enum Hook { /** Called with the SQL string and parse tree, in an array. */ PARSE_TREE, + /** Converts a SQL string to a + * {@link org.apache.calcite.jdbc.CalcitePrepare.Query} object. This hook is + * an opportunity to execute a {@link org.apache.calcite.rel.RelNode} query + * plan in the JDBC driver rather than the usual SQL string. */ + STRING_TO_QUERY, + /** Called with the generated Java plan, just before it is compiled by * Janino. */ JAVA_PLAN, http://git-wip-us.apache.org/repos/asf/calcite/blob/9c10c3da/core/src/test/java/org/apache/calcite/test/CalciteAssert.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java index 1267546..fcec8e5 100644 --- a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java +++ b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java @@ -25,6 +25,7 @@ import org.apache.calcite.config.CalciteConnectionProperty; import org.apache.calcite.config.Lex; import org.apache.calcite.jdbc.CalciteConnection; import org.apache.calcite.jdbc.CalciteMetaImpl; +import org.apache.calcite.jdbc.CalcitePrepare; import org.apache.calcite.jdbc.CalciteSchema; import org.apache.calcite.materialize.Lattice; import org.apache.calcite.plan.RelOptUtil; @@ -35,7 +36,10 @@ import org.apache.calcite.schema.Schema; import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.schema.impl.AbstractSchema; import org.apache.calcite.schema.impl.ViewTable; +import org.apache.calcite.tools.FrameworkConfig; +import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.util.Closer; +import org.apache.calcite.util.Holder; import org.apache.calcite.util.JsonBuilder; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; @@ -1471,6 +1475,21 @@ public class CalciteAssert { public <V> AssertQuery withProperty(Hook hook, V value) { return withHook(hook, Hook.property(value)); } + + /** Adds a factory to create a {@link RelNode} query. This {@code RelNode} + * will be used instead of the SQL string. */ + public AssertQuery withRel(final Function<RelBuilder, RelNode> relFn) { + return withHook(Hook.STRING_TO_QUERY, + new Function< + Pair<FrameworkConfig, Holder<CalcitePrepare.Query>>, Void>() { + public Void apply( + Pair<FrameworkConfig, Holder<CalcitePrepare.Query>> pair) { + final RelBuilder b = RelBuilder.create(pair.left); + pair.right.set(CalcitePrepare.Query.of(relFn.apply(b))); + return null; + } + }); + } } /** Fluent interface for building a metadata query to be tested. */
