Repository: calcite Updated Branches: refs/heads/master 32cca802e -> 868d64140
Add test case for [CALCITE-1769] Push filter involving cast to numeric down to Druid The test case specifies a query as a RelNode tree rather than the usual SQL. A work around for [CALCITE-1774] was necessary to make it work. It turns out that [CALCITE-1769] was fixed in 1.12, probably [CALCITE-1695]. Fix log4j.properties; now tracing goes to the console, not a file. Close apache/calcite#440 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/868d6414 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/868d6414 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/868d6414 Branch: refs/heads/master Commit: 868d64140d446cdb33652c0c76c4038b1ca26a14 Parents: 7c7e932 Author: Julian Hyde <[email protected]> Authored: Mon May 1 20:24:39 2017 -0700 Committer: Julian Hyde <[email protected]> Committed: Sun May 14 09:54:36 2017 -0700 ---------------------------------------------------------------------- .../org/apache/calcite/prepare/Prepare.java | 24 ++++++++ .../org/apache/calcite/test/DruidAdapterIT.java | 59 ++++++++++++++++++++ druid/src/test/resources/log4j.properties | 8 +-- 3 files changed, 87 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/868d6414/core/src/main/java/org/apache/calcite/prepare/Prepare.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/prepare/Prepare.java b/core/src/main/java/org/apache/calcite/prepare/Prepare.java index 054801d..cc6a81b 100644 --- a/core/src/main/java/org/apache/calcite/prepare/Prepare.java +++ b/core/src/main/java/org/apache/calcite/prepare/Prepare.java @@ -23,6 +23,7 @@ import org.apache.calcite.jdbc.CalcitePrepare; import org.apache.calcite.jdbc.CalciteSchema; import org.apache.calcite.jdbc.CalciteSchema.LatticeEntry; import org.apache.calcite.plan.Convention; +import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelOptLattice; import org.apache.calcite.plan.RelOptMaterialization; import org.apache.calcite.plan.RelOptPlanner; @@ -33,6 +34,8 @@ import org.apache.calcite.plan.RelTraitSet; import org.apache.calcite.rel.RelCollation; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelRoot; +import org.apache.calcite.rel.RelVisitor; +import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.logical.LogicalTableModify; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeField; @@ -158,6 +161,27 @@ public abstract class Prepare { } final RelTraitSet desiredTraits = getDesiredRootTraitSet(root); + + // Work around + // [CALCITE-1774] Allow rules to be registered during planning process + // by briefly creating each kind of physical table to let it register its + // rules. The problem occurs when plans are created via RelBuilder, not + // the usual process (SQL and SqlToRelConverter.Config.isConvertTableAccess + // = true). + final RelVisitor visitor = new RelVisitor() { + @Override public void visit(RelNode node, int ordinal, RelNode parent) { + if (node instanceof TableScan) { + final RelOptCluster cluster = node.getCluster(); + final RelOptTable.ToRelContext context = + RelOptUtil.getContext(cluster); + final RelNode r = node.getTable().toRel(context); + planner.registerClass(r); + } + super.visit(node, ordinal, parent); + } + }; + visitor.go(root.rel); + final Program program = getProgram(); final RelNode rootRel4 = program.run( planner, root.rel, desiredTraits, materializationList, latticeList); http://git-wip-us.apache.org/repos/asf/calcite/blob/868d6414/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java ---------------------------------------------------------------------- diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java index 2b639c8..5f043a2 100644 --- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java +++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java @@ -19,10 +19,17 @@ package org.apache.calcite.test; import org.apache.calcite.adapter.druid.DruidQuery; import org.apache.calcite.config.CalciteConnectionConfig; import org.apache.calcite.config.CalciteConnectionProperty; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.calcite.tools.RelBuilder; import org.apache.calcite.util.Util; import com.google.common.base.Function; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; @@ -2115,6 +2122,58 @@ public class DruidAdapterIT { + "\"product_id\" = 1558 and (true or false)"; sql(sql).returnsUnordered("C=60").queryContains(druidChecker("'queryType':'timeseries'")); } + + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-1769">[CALCITE-1769] + * Druid adapter: Push down filters involving numeric cast of literals</a>. */ + @Test public void testPushCastNumeric() { + String druidQuery = "'filter':{'type':'bound','dimension':'product_id'," + + "'upper':'10','upperStrict':true,'ordering':'numeric'}"; + sql("?") + .withRel(new Function<RelBuilder, RelNode>() { + public RelNode apply(RelBuilder b) { + // select product_id + // from foodmart.foodmart + // where product_id < cast(10 as varchar) + final RelDataType intType = + b.getTypeFactory().createSqlType(SqlTypeName.INTEGER); + return b.scan("foodmart", "foodmart") + .filter( + b.call(SqlStdOperatorTable.LESS_THAN, + b.getRexBuilder().makeCall(intType, + SqlStdOperatorTable.CAST, + ImmutableList.<RexNode>of(b.field("product_id"))), + b.getRexBuilder().makeCall(intType, + SqlStdOperatorTable.CAST, + ImmutableList.of(b.literal("10"))))) + .project(b.field("product_id")) + .build(); + } + }) + .queryContains(druidChecker(druidQuery)); + } + + @Test public void testPushFieldEqualsLiteral() { + sql("?") + .withRel(new Function<RelBuilder, RelNode>() { + public RelNode apply(RelBuilder b) { + // select count(*) as c + // from foodmart.foodmart + // where product_id = 'id' + return b.scan("foodmart", "foodmart") + .filter( + b.call(SqlStdOperatorTable.EQUALS, b.field("product_id"), + b.literal("id"))) + .aggregate(b.groupKey(), b.countStar("c")) + .build(); + } + }) + // Should return one row, "c=0"; logged + // [CALCITE-1775] "GROUP BY ()" on empty relation should return 1 row + .returnsUnordered() + .queryContains(druidChecker("'queryType':'timeseries'")); + } + } // End DruidAdapterIT.java http://git-wip-us.apache.org/repos/asf/calcite/blob/868d6414/druid/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/druid/src/test/resources/log4j.properties b/druid/src/test/resources/log4j.properties index 65a3982..ddf2f06 100644 --- a/druid/src/test/resources/log4j.properties +++ b/druid/src/test/resources/log4j.properties @@ -17,11 +17,11 @@ log4j.rootLogger=INFO, A1 # A1 goes to the console -#log4j.appender.A1=org.apache.log4j.ConsoleAppender - -log4j.appender.A1=org.apache.log4j.RollingFileAppender -log4j.appender.A1.File=/tmp/trace.log +log4j.appender.A1=org.apache.log4j.ConsoleAppender +# Uncomment to send output to a file. +#log4j.appender.A1=org.apache.log4j.RollingFileAppender +#log4j.appender.A1.File=/tmp/trace.log # Set the pattern for each log message log4j.appender.A1.layout=org.apache.log4j.PatternLayout
