calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject [01/10] incubator-calcite git commit: [CALCITE-868] Add API to execute queries expressed as RelNode
Date Fri, 04 Sep 2015 07:34:59 GMT
Repository: incubator-calcite
Updated Branches:
  refs/heads/master 3e4d2b5c7 -> ba789deb4


[CALCITE-868] Add API to execute queries expressed as RelNode


Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/2a215df3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/2a215df3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/2a215df3

Branch: refs/heads/master
Commit: 2a215df30d26f4363e6a7fe2d27be0ee7db9357f
Parents: 3e4d2b5
Author: Julian Hyde <jhyde@apache.org>
Authored: Mon Aug 31 17:19:27 2015 -0700
Committer: Julian Hyde <jhyde@apache.org>
Committed: Tue Sep 1 23:25:59 2015 -0700

----------------------------------------------------------------------
 .../calcite/jdbc/CalciteConnectionImpl.java     | 45 +++++++++--
 .../apache/calcite/jdbc/CalciteMetaImpl.java    |  6 +-
 .../org/apache/calcite/jdbc/CalcitePrepare.java | 34 ++++++++-
 .../apache/calcite/jdbc/CalciteStatement.java   |  3 +-
 .../calcite/prepare/CalcitePrepareImpl.java     | 79 +++++++++++++-------
 .../java/org/apache/calcite/schema/Schemas.java |  3 +-
 .../org/apache/calcite/tools/RelRunner.java     | 35 +++++++++
 .../org/apache/calcite/tools/RelRunners.java    | 43 +++++++++++
 .../org/apache/calcite/test/RelBuilderTest.java | 44 +++++++++++
 9 files changed, 252 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
index d69971d..f563174 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
@@ -41,6 +41,7 @@ import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.materialize.Lattice;
 import org.apache.calcite.materialize.MaterializationService;
 import org.apache.calcite.prepare.CalciteCatalogReader;
+import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.schema.SchemaPlus;
@@ -53,16 +54,20 @@ import org.apache.calcite.sql.advise.SqlAdvisorValidator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.validate.SqlConformance;
 import org.apache.calcite.sql.validate.SqlValidatorWithHints;
+import org.apache.calcite.tools.RelRunner;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Holder;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 
 import java.io.Serializable;
 import java.lang.reflect.Type;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Iterator;
 import java.util.List;
@@ -143,6 +148,24 @@ abstract class CalciteConnectionImpl
     }
   }
 
+  @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+    if (iface == RelRunner.class) {
+      return iface.cast(
+          new RelRunner() {
+            public PreparedStatement prepare(RelNode rel) {
+              try {
+                return prepareStatement_(CalcitePrepare.Query.of(rel),
+                    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+                    getHoldability());
+              } catch (SQLException e) {
+                throw Throwables.propagate(e);
+              }
+            }
+          });
+    }
+    return super.unwrap(iface);
+  }
+
   @Override public CalciteStatement createStatement(int resultSetType,
       int resultSetConcurrency, int resultSetHoldability) throws SQLException {
     return (CalciteStatement) super.createStatement(resultSetType,
@@ -154,23 +177,34 @@ abstract class CalciteConnectionImpl
       int resultSetType,
       int resultSetConcurrency,
       int resultSetHoldability) throws SQLException {
+    final CalcitePrepare.Query<Object> query = CalcitePrepare.Query.of(sql);
+    return prepareStatement_(query, resultSetType, resultSetConcurrency,
+        resultSetHoldability);
+  }
+
+  private CalcitePreparedStatement prepareStatement_(
+      CalcitePrepare.Query<?> query,
+      int resultSetType,
+      int resultSetConcurrency,
+      int resultSetHoldability) throws SQLException {
     try {
-      Meta.Signature signature =
-          parseQuery(sql, new ContextImpl(this), -1);
+      final Meta.Signature signature =
+          parseQuery(query, new ContextImpl(this), -1);
       return (CalcitePreparedStatement) factory.newPreparedStatement(this, null,
           signature, resultSetType, resultSetConcurrency, resultSetHoldability);
     } catch (Exception e) {
       throw Helper.INSTANCE.createException(
-          "Error while preparing statement [" + sql + "]", e);
+          "Error while preparing statement [" + query.sql + "]", e);
     }
   }
 
-  <T> CalcitePrepare.CalciteSignature<T> parseQuery(String sql,
+  <T> CalcitePrepare.CalciteSignature<T>
+  parseQuery(CalcitePrepare.Query<T> query,
       CalcitePrepare.Context prepareContext, long maxRowCount) {
     CalcitePrepare.Dummy.push(prepareContext);
     try {
       final CalcitePrepare prepare = prepareFactory.apply();
-      return prepare.prepareSql(prepareContext, sql, null, Object[].class,
+      return prepare.prepareSql(prepareContext, query, Object[].class,
           maxRowCount);
     } finally {
       CalcitePrepare.Dummy.pop(prepareContext);
@@ -468,6 +502,7 @@ abstract class CalciteConnectionImpl
       this.iterator = iterator;
     }
   }
+
 }
 
 // End CalciteConnectionImpl.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/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 fabaf26..49a65d7 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
@@ -545,8 +545,8 @@ public class CalciteMetaImpl extends MetaImpl {
 
     CalciteServerStatement statement = calciteConnection.server.getStatement(h);
     h.signature =
-        calciteConnection.parseQuery(sql, statement.createPrepareContext(),
-            maxRowCount);
+        calciteConnection.parseQuery(CalcitePrepare.Query.of(sql),
+            statement.createPrepareContext(), maxRowCount);
     statement.setSignature(h.signature);
     return h;
   }
@@ -560,7 +560,7 @@ public class CalciteMetaImpl extends MetaImpl {
         final CalciteConnectionImpl calciteConnection = getConnection();
         CalciteServerStatement statement =
             calciteConnection.server.getStatement(h);
-        signature = calciteConnection.parseQuery(sql,
+        signature = calciteConnection.parseQuery(CalcitePrepare.Query.of(sql),
             statement.createPrepareContext(), maxRowCount);
         statement.setSignature(signature);
         callback.assign(signature, null, -1);

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
index b2c1821..197deb4 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
@@ -95,8 +95,7 @@ public interface CalcitePrepare {
 
   <T> CalciteSignature<T> prepareSql(
       Context context,
-      String sql,
-      Queryable<T> expression,
+      Query<T> query,
       Type elementType,
       long maxRowCount);
 
@@ -319,6 +318,37 @@ public interface CalcitePrepare {
       return collationList;
     }
   }
+
+  /** A union type of the three possible ways of expressing a query: as a SQL
+   * string, a {@link Queryable} or a {@link RelNode}. Exactly one must be
+   * provided. */
+  class Query<T> {
+    public final String sql;
+    public final Queryable<T> queryable;
+    public final RelNode rel;
+
+    private Query(String sql, Queryable<T> queryable, RelNode rel) {
+      this.sql = sql;
+      this.queryable = queryable;
+      this.rel = rel;
+
+      assert (sql == null ? 0 : 1)
+          + (queryable == null ? 0 : 1)
+          + (rel == null ? 0 : 1) == 1;
+    }
+
+    public static <T> Query<T> of(String sql) {
+      return new Query<>(sql, null, null);
+    }
+
+    public static <T> Query<T> of(Queryable<T> queryable) {
+      return new Query<>(null, queryable, null);
+    }
+
+    public static <T> Query<T> of(RelNode rel) {
+      return new Query<>(null, null, rel);
+    }
+  }
 }
 
 // End CalcitePrepare.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
index fa875e4..298b56c 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
@@ -48,8 +48,7 @@ public abstract class CalciteStatement extends AvaticaStatement {
 
   @Override public <T> T unwrap(Class<T> iface) throws SQLException {
     if (iface == CalciteServerStatement.class) {
-      //noinspection unchecked
-      return (T) getConnection().server.getStatement(handle);
+      return iface.cast(getConnection().server.getStatement(handle));
     }
     return super.unwrap(iface);
   }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
index b787a0f..87bd09f 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -70,6 +70,7 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelRoot;
 import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
 import org.apache.calcite.rel.rules.AggregateReduceFunctionsRule;
@@ -124,6 +125,7 @@ import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -540,26 +542,25 @@ public class CalcitePrepareImpl implements CalcitePrepare {
   public <T> CalciteSignature<T> prepareQueryable(
       Context context,
       Queryable<T> queryable) {
-    return prepare_(context, null, queryable, queryable.getElementType(), -1);
+    return prepare_(context, Query.of(queryable), queryable.getElementType(),
+        -1);
   }
 
   public <T> CalciteSignature<T> prepareSql(
       Context context,
-      String sql,
-      Queryable<T> expression,
+      Query<T> query,
       Type elementType,
       long maxRowCount) {
-    return prepare_(context, sql, expression, elementType, maxRowCount);
+    return prepare_(context, query, elementType, maxRowCount);
   }
 
   <T> CalciteSignature<T> prepare_(
       Context context,
-      String sql,
-      Queryable<T> queryable,
+      Query<T> query,
       Type elementType,
       long maxRowCount) {
-    if (SIMPLE_SQLS.contains(sql)) {
-      return simplePrepare(context, sql);
+    if (SIMPLE_SQLS.contains(query.sql)) {
+      return simplePrepare(context, query.sql);
     }
     final JavaTypeFactory typeFactory = context.getTypeFactory();
     CalciteCatalogReader catalogReader =
@@ -580,7 +581,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
         throw new AssertionError("factory returned null planner");
       }
       try {
-        return prepare2_(context, sql, queryable, elementType, maxRowCount,
+        return prepare2_(context, query, elementType, maxRowCount,
             catalogReader, planner);
       } catch (RelOptPlanner.CannotPlanException e) {
         exception = e;
@@ -623,8 +624,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
 
   <T> CalciteSignature<T> prepare2_(
       Context context,
-      String sql,
-      Queryable<T> queryable,
+      Query<T> query,
       Type elementType,
       long maxRowCount,
       CalciteCatalogReader catalogReader,
@@ -645,10 +645,9 @@ public class CalcitePrepareImpl implements CalcitePrepare {
 
     final RelDataType x;
     final Prepare.PreparedResult preparedResult;
-    if (sql != null) {
-      assert queryable == null;
+    if (query.sql != null) {
       final CalciteConnectionConfig config = context.config();
-      SqlParser parser = createParser(sql,
+      SqlParser parser = createParser(query.sql,
           createParserConfig()
               .setQuotedCasing(config.quotedCasing())
               .setUnquotedCasing(config.unquotedCasing())
@@ -661,7 +660,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
             "parse failed: " + e.getMessage(), e);
       }
 
-      Hook.PARSE_TREE.run(new Object[] {sql, sqlNode});
+      Hook.PARSE_TREE.run(new Object[] {query.sql, sqlNode});
 
       if (sqlNode.getKind().belongsTo(SqlKind.DDL)) {
         executeDdl(context, sqlNode);
@@ -672,7 +671,8 @@ public class CalcitePrepareImpl implements CalcitePrepare {
             return Linq4j.emptyEnumerable();
           }
         };
-        return new CalciteSignature<>(sql, ImmutableList.<AvaticaParameter>of(),
+        return new CalciteSignature<>(query.sql,
+            ImmutableList.<AvaticaParameter>of(),
             ImmutableMap.<String, Object>of(), null,
             ImmutableList.<ColumnMetaData>of(), Meta.CursorFactory.OBJECT,
             ImmutableList.<RelCollation>of(), -1, bindable);
@@ -706,11 +706,14 @@ public class CalcitePrepareImpl implements CalcitePrepare {
       default:
         x = validator.getValidatedNodeType(sqlNode);
       }
-    } else {
-      assert queryable != null;
+    } else if (query.queryable != null) {
       x = context.getTypeFactory().createType(elementType);
       preparedResult =
-          preparingStmt.prepareQueryable(queryable, x);
+          preparingStmt.prepareQueryable(query.queryable, x);
+    } else {
+      assert query.rel != null;
+      x = query.rel.getRowType();
+      preparedResult = preparingStmt.prepareRel(query.rel);
     }
 
     final List<AvaticaParameter> parameters = new ArrayList<>();
@@ -739,7 +742,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
     //noinspection unchecked
     final Bindable<T> bindable = preparedResult.getBindable();
     return new CalciteSignature<>(
-        sql,
+        query.sql,
         parameters,
         preparingStmt.internalParameters,
         jdbcType,
@@ -948,23 +951,45 @@ public class CalcitePrepareImpl implements CalcitePrepare {
     }
 
     public PreparedResult prepareQueryable(
-        Queryable queryable,
+        final Queryable queryable,
+        RelDataType resultType) {
+      return prepare_(
+          new Supplier<RelNode>() {
+            public RelNode get() {
+              final RelOptCluster cluster =
+                  prepare.createCluster(planner, rexBuilder);
+              return new LixToRelTranslator(cluster, CalcitePreparingStmt.this)
+                  .translate(queryable);
+            }
+          }, resultType);
+    }
+
+    public PreparedResult prepareRel(final RelNode rel) {
+      return prepare_(
+          new Supplier<RelNode>() {
+            public RelNode get() {
+              return rel;
+            }
+          }, rel.getRowType());
+    }
+
+    private PreparedResult prepare_(Supplier<RelNode> fn,
         RelDataType resultType) {
       queryString = null;
       Class runtimeContextClass = Object.class;
       init(runtimeContextClass);
 
-      final RelOptCluster cluster = prepare.createCluster(planner, rexBuilder);
-
-      final RelNode rel =
-          new LixToRelTranslator(cluster, CalcitePreparingStmt.this)
-              .translate(queryable);
+      final RelNode rel = fn.get();
       final RelDataType rowType = rel.getRowType();
       final List<Pair<Integer, String>> fields =
           Pair.zip(ImmutableIntList.identity(rowType.getFieldCount()),
               rowType.getFieldNames());
+      final RelCollation collation =
+          rel instanceof Sort
+              ? ((Sort) rel).collation
+              : RelCollations.EMPTY;
       RelRoot root = new RelRoot(rel, resultType, SqlKind.SELECT, fields,
-          RelCollations.EMPTY);
+          collation);
 
       if (timingTracer != null) {
         timingTracer.traceTime("end sql2rel");

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/schema/Schemas.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/schema/Schemas.java b/core/src/main/java/org/apache/calcite/schema/Schemas.java
index aa53419..639e852 100644
--- a/core/src/main/java/org/apache/calcite/schema/Schemas.java
+++ b/core/src/main/java/org/apache/calcite/schema/Schemas.java
@@ -343,7 +343,8 @@ public final class Schemas {
         makeContext(connection, schema, schemaPath, map);
     CalcitePrepare.Dummy.push(context);
     try {
-      return prepare.prepareSql(context, sql, null, Object[].class, -1);
+      return prepare.prepareSql(context, CalcitePrepare.Query.of(sql),
+          Object[].class, -1);
     } finally {
       CalcitePrepare.Dummy.pop(context);
     }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/tools/RelRunner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelRunner.java b/core/src/main/java/org/apache/calcite/tools/RelRunner.java
new file mode 100644
index 0000000..d29db9c
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/tools/RelRunner.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.tools;
+
+import org.apache.calcite.rel.RelNode;
+
+import java.sql.PreparedStatement;
+
+/**
+ * Runs a relational expression.
+ *
+ * <p>Experimental.
+ *
+ * @see RelRunners
+ */
+public interface RelRunner {
+  /** Runs a relational expression. */
+  PreparedStatement prepare(RelNode rel);
+}
+
+// End RelRunner.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/main/java/org/apache/calcite/tools/RelRunners.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelRunners.java b/core/src/main/java/org/apache/calcite/tools/RelRunners.java
new file mode 100644
index 0000000..9db8e7c
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/tools/RelRunners.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.tools;
+
+import org.apache.calcite.rel.RelNode;
+
+import com.google.common.base.Throwables;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/** Implementations of {@link RelRunner}. */
+public class RelRunners {
+  private RelRunners() {}
+
+  /** Runs a relational expression by creating a JDBC connection. */
+  public static PreparedStatement run(RelNode rel) {
+    try (Connection connection = DriverManager.getConnection("jdbc:calcite:")) {
+      final RelRunner runner = connection.unwrap(RelRunner.class);
+      return runner.prepare(rel);
+    } catch (SQLException e) {
+      throw Throwables.propagate(e);
+    }
+  }
+}
+
+// End RelRunners.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/2a215df3/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index cafd61e..2aa0d50 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -37,10 +37,12 @@ import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.tools.Frameworks;
 import org.apache.calcite.tools.Programs;
 import org.apache.calcite.tools.RelBuilder;
+import org.apache.calcite.tools.RelRunners;
 import org.apache.calcite.util.Util;
 
 import org.junit.Test;
 
+import java.sql.PreparedStatement;
 import java.util.List;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -738,6 +740,48 @@ public class RelBuilderTest {
             .build();
     assertThat(str(root2), is(expected));
   }
+
+  /** Tests {@link org.apache.calcite.tools.RelRunner} for a VALUES query. */
+  @Test public void testRunValues() throws Exception {
+    // Equivalent SQL:
+    //   VALUES (true, 1), (false, -50) AS t(a, b)
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelNode root =
+        builder.values(new String[]{"a", "b"}, true, 1, false, -50)
+            .build();
+    try (final PreparedStatement preparedStatement = RelRunners.run(root)) {
+      String s = CalciteAssert.toString(preparedStatement.executeQuery());
+      final String result = "a=true; b=1\n"
+          + "a=false; b=-50\n";
+      assertThat(s, is(result));
+    }
+  }
+
+  /** Tests {@link org.apache.calcite.tools.RelRunner} for a table scan + filter
+   * query. */
+  @Test public void testRun() throws Exception {
+    // Equivalent SQL:
+    //   SELECT * FROM EMP WHERE DEPTNO = 20
+    final RelBuilder builder = RelBuilder.create(config().build());
+    RelNode root =
+        builder.scan("EMP")
+            .filter(
+                builder.equals(builder.field("DEPTNO"), builder.literal(20)))
+            .build();
+
+    // Note that because the table has been resolved in the RelNode tree
+    // we do not need to supply a "schema" as context to the runner.
+    try (final PreparedStatement preparedStatement = RelRunners.run(root)) {
+      String s = CalciteAssert.toString(preparedStatement.executeQuery());
+      final String result = ""
+          + "EMPNO=7369; ENAME=SMITH; JOB=CLERK; MGR=7902; HIREDATE=1980-12-17; SAL=800.00;
COMM=null; DEPTNO=20\n"
+          + "EMPNO=7566; ENAME=JONES; JOB=MANAGER; MGR=7839; HIREDATE=1981-02-04; SAL=2975.00;
COMM=null; DEPTNO=20\n"
+          + "EMPNO=7788; ENAME=SCOTT; JOB=ANALYST; MGR=7566; HIREDATE=1987-04-19; SAL=3000.00;
COMM=null; DEPTNO=20\n"
+          + "EMPNO=7876; ENAME=ADAMS; JOB=CLERK; MGR=7788; HIREDATE=1987-05-23; SAL=1100.00;
COMM=null; DEPTNO=20\n"
+          + "EMPNO=7902; ENAME=FORD; JOB=ANALYST; MGR=7566; HIREDATE=1981-12-03; SAL=3000.00;
COMM=null; DEPTNO=20\n";
+      assertThat(s, is(result));
+    }
+  }
 }
 
 // End RelBuilderTest.java


Mime
View raw message