This is an automated email from the ASF dual-hosted git repository. mbudiu pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 394ec336d6e89884f817e1c3b3fa1c0da211fe59 Author: suibianwanwan <[email protected]> AuthorDate: Mon Nov 11 14:53:55 2024 +0800 [CALCITE-6586] Some Rules not firing due to RelMdPredicates returning null in VolcanoPlanner --- .../org/apache/calcite/adapter/jdbc/JdbcRules.java | 2 +- .../rel/metadata/RelMdColumnUniqueness.java | 23 +------ .../calcite/rel/metadata/RelMdPredicates.java | 2 +- .../rules/AggregateProjectPullUpConstantsRule.java | 3 +- .../rel/rules/UnionPullUpConstantsRule.java | 3 +- .../org/apache/calcite/test/JdbcAdapterTest.java | 11 +++- .../java/org/apache/calcite/test/JdbcTest.java | 45 ++++++++----- .../org/apache/calcite/test/RelOptRulesTest.java | 53 +++++++++++++++ .../apache/calcite/test/ScannableTableTest.java | 7 +- .../org/apache/calcite/test/RelOptRulesTest.xml | 76 ++++++++++++++++++++++ core/src/test/resources/sql/sub-query.iq | 30 ++++----- .../org/apache/calcite/test/DruidAdapter2IT.java | 33 ++++++---- .../org/apache/calcite/test/DruidAdapterIT.java | 33 ++++++---- 13 files changed, 231 insertions(+), 90 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java index 846dc9c4e4..9a35cf7cce 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java @@ -867,7 +867,7 @@ public class JdbcRules { if (cost == null) { return null; } - return cost.multiplyBy(.1); + return cost.multiplyBy(JdbcConvention.COST_MULTIPLIER); } @Override public JdbcImplementor.Result implement(JdbcImplementor implementor) { diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java index e4e0b32822..1889e5b93e 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdColumnUniqueness.java @@ -461,7 +461,7 @@ public class RelMdColumnUniqueness || rel2 instanceof Values || rel2 instanceof Sort || rel2 instanceof TableScan - || simplyProjects(rel2, columns)) { + || rel2 instanceof Project) { try { final Boolean unique = mq.areColumnsUnique(rel2, columns, ignoreNulls); if (unique != null) { @@ -480,27 +480,6 @@ public class RelMdColumnUniqueness return false; } - private static boolean simplyProjects(RelNode rel, ImmutableBitSet columns) { - if (!(rel instanceof Project)) { - return false; - } - Project project = (Project) rel; - final List<RexNode> projects = project.getProjects(); - for (int column : columns) { - if (column >= projects.size()) { - return false; - } - if (!(projects.get(column) instanceof RexInputRef)) { - return false; - } - final RexInputRef ref = (RexInputRef) projects.get(column); - if (ref.getIndex() != column) { - return false; - } - } - return true; - } - /** Splits a column set between left and right sets. */ private static Pair<ImmutableBitSet, ImmutableBitSet> splitLeftAndRightColumns(int leftCount, final ImmutableBitSet columns) { diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java index 19335f0fff..396b3300b4 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java @@ -628,7 +628,7 @@ public class RelMdPredicates public RelOptPredicateList getPredicates(RelSubset r, RelMetadataQuery mq) { if (!Bug.CALCITE_1048_FIXED) { - return RelOptPredicateList.EMPTY; + return mq.getPulledUpPredicates(r.stripped()); } final RexBuilder rexBuilder = r.getCluster().getRexBuilder(); RelOptPredicateList list = null; diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java index b587d83a1a..231d65418c 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateProjectPullUpConstantsRule.java @@ -61,7 +61,7 @@ import java.util.TreeMap; @Value.Enclosing public class AggregateProjectPullUpConstantsRule extends RelRule<AggregateProjectPullUpConstantsRule.Config> - implements TransformationRule { + implements SubstitutionRule { /** Creates an AggregateProjectPullUpConstantsRule. */ protected AggregateProjectPullUpConstantsRule(Config config) { @@ -175,6 +175,7 @@ public class AggregateProjectPullUpConstantsRule } relBuilder.project(Pair.left(projects), Pair.right(projects)); // inverse call.transformTo(relBuilder.build()); + call.getPlanner().prune(aggregate); } diff --git a/core/src/main/java/org/apache/calcite/rel/rules/UnionPullUpConstantsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/UnionPullUpConstantsRule.java index e236844075..047a804b18 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/UnionPullUpConstantsRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/UnionPullUpConstantsRule.java @@ -49,7 +49,7 @@ import java.util.Map; @Value.Enclosing public class UnionPullUpConstantsRule extends RelRule<UnionPullUpConstantsRule.Config> - implements TransformationRule { + implements SubstitutionRule { /** Creates a UnionPullUpConstantsRule. */ protected UnionPullUpConstantsRule(Config config) { @@ -140,6 +140,7 @@ public class UnionPullUpConstantsRule relBuilder.convert(union.getRowType(), false); call.transformTo(relBuilder.build()); + call.getPlanner().prune(union); } /** Rule configuration. */ diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java index 4882c193e3..171dea060c 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java @@ -160,13 +160,18 @@ class JdbcAdapterTest { + "where \"product_id\" = 1") .runs() .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB) - .planHasSql("SELECT *\n" + .planHasSql("SELECT 1 AS \"product_id\", \"time_id\", \"customer_id\", " + + "\"promotion_id\", \"store_id\", \"store_sales\", " + + "\"store_cost\", \"unit_sales\"\n" + + "FROM (SELECT \"time_id\", \"customer_id\", \"promotion_id\", \"store_id\", " + + "\"store_sales\", \"store_cost\", \"unit_sales\"\n" + "FROM \"foodmart\".\"sales_fact_1997\"\n" + "WHERE \"product_id\" = 1\n" + "UNION ALL\n" - + "SELECT *\n" + + "SELECT \"time_id\", \"customer_id\", \"promotion_id\", \"store_id\", " + + "\"store_sales\", \"store_cost\", \"unit_sales\"\n" + "FROM \"foodmart\".\"sales_fact_1998\"\n" - + "WHERE \"product_id\" = 1"); + + "WHERE \"product_id\" = 1) AS \"t3\""); } @Test void testInPlan() { diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java index 2bbff3f6ed..7c5f6b2a18 100644 --- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java +++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java @@ -3068,32 +3068,40 @@ public class JdbcTest { final String extra; switch (format) { case "text": - expected = "EnumerableAggregate(group=[{0, 3}])\n" - + " EnumerableCalc(expr#0..1=[{inputs}], expr#2=[10], expr#3=['SameName'], expr#4=[CAST($t1):INTEGER NOT NULL], expr#5=[=($t4, $t2)], proj#0..3=[{exprs}], $condition=[$t5])\n" - + " EnumerableTableScan(table=[[SALES, EMPS]])\n\n"; + expected = "EnumerableCalc(expr#0=[{inputs}], expr#1=['SameName'], proj#0..1=[{exprs}])\n" + + " EnumerableAggregate(group=[{0}])\n" + + " EnumerableCalc(expr#0..1=[{inputs}], expr#2=[CAST($t1):INTEGER NOT NULL], expr#3=[10], expr#4=[=($t2, $t3)], proj#0..1=[{exprs}], $condition=[$t4])\n" + + " EnumerableTableScan(table=[[SALES, EMPS]])\n\n"; extra = ""; break; case "dot": expected = "PLAN=digraph {\n" + + "\"EnumerableAggregate\\n" + + "group = {0}\\n" + + "\" -> \"EnumerableCalc\\n" + + "expr#0 = {inputs}\\n" + + "expr#1 = 'SameName'\\n" + + "proj#0..1 = {exprs}\\n" + + "\" [label=\"0\"]\n" + "\"EnumerableCalc\\n" + "expr#0..1 = {inputs}\\n" - + "expr#2 = 10\\n" - + "expr#3 = 'SameName'\\n" - + "expr#4 = CAST($t1):I\\n" + + "expr#2 = CAST($t1):I\\n" + "NTEGER NOT NULL\\n" + + "expr#3 = 10\\n" + + "expr#4 = =($t2, $t3)\\n" + "...\" -> \"EnumerableAggregate\\n" - + "group = {0, 3}\\n" + + "group = {0}\\n" + "\" [label=\"0\"]\n" + "\"EnumerableTableScan\\n" + "table = [SALES, EMPS\\n]\\n" + "\" -> \"EnumerableCalc\\n" + "expr#0..1 = {inputs}\\n" - + "expr#2 = 10\\n" - + "expr#3 = 'SameName'\\n" - + "expr#4 = CAST($t1):I\\nNTEGER NOT NULL\\n" + + "expr#2 = CAST($t1):I\\n" + + "NTEGER NOT NULL\\n" + + "expr#3 = 10\\n" + + "expr#4 = =($t2, $t3)\\n" + "...\" [label=\"0\"]\n" - + "}\n" - + "\n"; + + "}\n\n"; extra = " as dot "; break; default: @@ -3191,12 +3199,13 @@ public class JdbcTest { .enable(CalciteAssert.DB != CalciteAssert.DatabaseInstance.ORACLE) .explainContains("" + "EnumerableAggregate(group=[{0}], m0=[COUNT($1)])\n" - + " EnumerableAggregate(group=[{1, 3}])\n" - + " EnumerableHashJoin(condition=[=($0, $2)], joinType=[inner])\n" - + " EnumerableCalc(expr#0..9=[{inputs}], expr#10=[CAST($t4):INTEGER], expr#11=[1997], expr#12=[=($t10, $t11)], time_id=[$t0], the_year=[$t4], $condition=[$t12])\n" - + " EnumerableTableScan(table=[[foodmart2, time_by_day]])\n" - + " EnumerableCalc(expr#0..7=[{inputs}], time_id=[$t1], unit_sales=[$t7])\n" - + " EnumerableTableScan(table=[[foodmart2, sales_fact_1997]])") + + " EnumerableCalc(expr#0=[{inputs}], expr#1=[1997:SMALLINT], expr#2=[CAST($t1):SMALLINT], c0=[$t2], unit_sales=[$t0])\n" + + " EnumerableAggregate(group=[{1}])\n" + + " EnumerableHashJoin(condition=[=($0, $2)], joinType=[semi])\n" + + " EnumerableCalc(expr#0..7=[{inputs}], time_id=[$t1], unit_sales=[$t7])\n" + + " EnumerableTableScan(table=[[foodmart2, sales_fact_1997]])\n" + + " EnumerableCalc(expr#0..9=[{inputs}], expr#10=[CAST($t4):INTEGER], expr#11=[1997], expr#12=[=($t10, $t11)], time_id=[$t0], the_year=[$t4], $condition=[$t12])\n" + + " EnumerableTableScan(table=[[foodmart2, time_by_day]])") .returns("c0=1997; m0=6\n"); } diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index 5fe12d9617..203174f39e 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -5370,6 +5370,21 @@ class RelOptRulesTest extends RelOptTestBase { basePullConstantTroughAggregate(); } + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-6586">[CALCITE-6586] + * Some Rules not firing due to RelMdPredicates returning null in VolcanoPlanner</a>. */ + @Test void testPullConstantThroughAggregatePermutedInVolcano() { + sql("${sql}") + .withVolcanoPlanner(false, p -> { + p.addRule(CoreRules.AGGREGATE_PROJECT_PULL_UP_CONSTANTS); + p.addRule(CoreRules.PROJECT_MERGE); + p.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE); + p.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE); + p.addRule(EnumerableRules.ENUMERABLE_AGGREGATE_RULE); + }) + .check(); + } + @Test void testPullConstantThroughAggregatePermutedConstFirst() { basePullConstantTroughAggregate(); } @@ -5401,6 +5416,25 @@ class RelOptRulesTest extends RelOptTestBase { .check(); } + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-6586">[CALCITE-6586] + * Some Rules not firing due to RelMdPredicates returning null in VolcanoPlanner</a>. */ + @Test void testPullConstantThroughUnionInVolcano() { + final String sql = "select 2, deptno, job from emp as e1\n" + + "union all\n" + + "select 2, deptno, job from emp as e2"; + sql(sql) + .withTrim(true) + .withVolcanoPlanner(false, p -> { + p.addRule(CoreRules.UNION_PULL_UP_CONSTANTS); + p.addRule(CoreRules.PROJECT_MERGE); + p.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE); + p.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE); + p.addRule(EnumerableRules.ENUMERABLE_UNION_RULE); + }) + .check(); + } + @Test void testPullConstantThroughUnion2() { // Negative test: constants should not be pulled up final String sql = "select 2, deptno, job from emp as e1\n" @@ -7672,6 +7706,25 @@ class RelOptRulesTest extends RelOptTestBase { .check(); } + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-6586">[CALCITE-6586] + * Some Rules not firing due to RelMdPredicates returning null in VolcanoPlanner</a>. */ + @Test void testAggregateConstantKeyRuleInVolcano() { + final String sql = "select count(*) as c\n" + + "from sales.emp\n" + + "where deptno = 10\n" + + "group by deptno, sal"; + sql(sql) + .withVolcanoPlanner(false, p -> { + p.addRule(CoreRules.AGGREGATE_ANY_PULL_UP_CONSTANTS); + p.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE); + p.addRule(EnumerableRules.ENUMERABLE_AGGREGATE_RULE); + p.addRule(EnumerableRules.ENUMERABLE_FILTER_RULE); + p.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE); + }) + .check(); + } + /** Tests {@link AggregateProjectPullUpConstantsRule} where reduction is not * possible because "deptno" is the only key. */ @Test void testAggregateConstantKeyRule2() { diff --git a/core/src/test/java/org/apache/calcite/test/ScannableTableTest.java b/core/src/test/java/org/apache/calcite/test/ScannableTableTest.java index bf1af78bd9..976f5abcd6 100644 --- a/core/src/test/java/org/apache/calcite/test/ScannableTableTest.java +++ b/core/src/test/java/org/apache/calcite/test/ScannableTableTest.java @@ -278,9 +278,10 @@ public class ScannableTableTest { final Table table = new BeatlesProjectableFilterableTable(buf, false); final String explain = "PLAN=" + "EnumerableAggregate(group=[{0}], C=[COUNT()])\n" - + " EnumerableAggregate(group=[{0, 1}])\n" - + " EnumerableInterpreter\n" - + " BindableTableScan(table=[[s, beatles]], filters=[[=($2, 1940)]], projects=[[2, 0]])"; + + " EnumerableCalc(expr#0=[{inputs}], expr#1=[1940], k=[$t1], i=[$t0])\n" + + " EnumerableAggregate(group=[{1}])\n" + + " EnumerableInterpreter\n" + + " BindableTableScan(table=[[s, beatles]], filters=[[=($2, 1940)]], projects=[[2, 0]])"; CalciteAssert.that() .with(newSchema("s", PairList.of("beatles", table))) .query(sql) diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml index eba397a3b9..da6e4936c4 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -159,6 +159,33 @@ LogicalProject(JOB=[$1]) LogicalProject(MGR=[$3]) LogicalFilter(condition=[AND(IS NULL($3), =($2, 'Clerk'))]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> + <TestCase name="testAggregateConstantKeyRuleInVolcano"> + <Resource name="sql"> + <![CDATA[select count(*) as c +from sales.emp +where deptno = 10 +group by deptno, sal]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalProject(C=[$2]) + LogicalAggregate(group=[{0, 1}], C=[COUNT()]) + LogicalProject(DEPTNO=[$7], SAL=[$5]) + LogicalFilter(condition=[=($7, 10)]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +EnumerableProject(C=[$2]) + EnumerableProject(DEPTNO=[10], SAL=[$0], C=[$1]) + EnumerableAggregate(group=[{0}], C=[COUNT()]) + EnumerableProject(SAL=[$5]) + EnumerableFilter(condition=[=($7, 10)]) + EnumerableTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> </TestCase> @@ -9040,6 +9067,29 @@ LogicalProject(DEPTNO=[$1], EXPR$1=[$2]) LogicalAggregate(group=[{0}], EXPR$1=[MAX($1)]) LogicalProject(DEPTNO=[$7], MGR=[$3]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> + <TestCase name="testPullConstantThroughAggregatePermutedInVolcano"> + <Resource name="sql"> + <![CDATA[select deptno, max(mgr) from ( + select *, 4 as four, 2+3 as two_plus_three, deptno+42 as deptno42 from emp +) group by deptno, four, two_plus_three, deptno42]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalProject(DEPTNO=[$0], EXPR$1=[$4]) + LogicalAggregate(group=[{0, 1, 2, 3}], EXPR$1=[MAX($4)]) + LogicalProject(DEPTNO=[$7], FOUR=[4], TWO_PLUS_THREE=[+(2, 3)], DEPTNO42=[+($7, 42)], MGR=[$3]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +EnumerableProject(DEPTNO=[$0], EXPR$1=[$2]) + EnumerableAggregate(group=[{0, 1}], EXPR$1=[MAX($2)]) + EnumerableProject(DEPTNO=[$7], DEPTNO42=[+($7, 42)], MGR=[$3]) + EnumerableTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> </TestCase> @@ -9152,6 +9202,32 @@ LogicalProject(EXPR$0=[2], EXPR$1=[3]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalProject(EXPR$0=[2]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> + <TestCase name="testPullConstantThroughUnionInVolcano"> + <Resource name="sql"> + <![CDATA[select 2, deptno, job from emp as e1 +union all +select 2, deptno, job from emp as e2]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalUnion(all=[true]) + LogicalProject(EXPR$0=[2], DEPTNO=[$7], JOB=[$2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) + LogicalProject(EXPR$0=[2], DEPTNO=[$7], JOB=[$2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +EnumerableProject(EXPR$0=[2], DEPTNO=[$0], JOB=[$1]) + EnumerableUnion(all=[true]) + EnumerableProject(DEPTNO=[$7], JOB=[$2]) + EnumerableTableScan(table=[[CATALOG, SALES, EMP]]) + EnumerableProject(DEPTNO=[$7], JOB=[$2]) + EnumerableTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> </TestCase> diff --git a/core/src/test/resources/sql/sub-query.iq b/core/src/test/resources/sql/sub-query.iq index f1adf623ad..7b42a78681 100644 --- a/core/src/test/resources/sql/sub-query.iq +++ b/core/src/test/resources/sql/sub-query.iq @@ -2906,8 +2906,8 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], $condi EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0]) EnumerableTableScan(table=[[scott, DEPT]]) EnumerableAggregate(group=[{0}]) - EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) - EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) + EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) + EnumerableAggregate(group=[{7}], c=[COUNT()]) EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(10, 2)], expr#9=[3000.00:DECIMAL(10, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -2932,8 +2932,8 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], U=[$t2 EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0]) EnumerableTableScan(table=[[scott, DEPT]]) EnumerableAggregate(group=[{0}]) - EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) - EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) + EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) + EnumerableAggregate(group=[{7}], c=[COUNT()]) EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(10, 2)], expr#9=[3000.00:DECIMAL(10, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -2958,8 +2958,8 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NOT NULL($t1)], DEPTNO=[$t0], U= EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0]) EnumerableTableScan(table=[[scott, DEPT]]) EnumerableAggregate(group=[{0}]) - EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[1], expr#5=[>($t2, $t4)], i=[$t3], $condition=[$t5]) - EnumerableAggregate(group=[{5, 7}], c=[COUNT()]) + EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) + EnumerableAggregate(group=[{7}], c=[COUNT()]) EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t5):DECIMAL(10, 2)], expr#9=[3000.00:DECIMAL(10, 2)], expr#10=[=($t8, $t9)], expr#11=[IS NOT NULL($t7)], expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12]) EnumerableTableScan(table=[[scott, EMP]]) !plan @@ -2984,11 +2984,10 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], $condi EnumerableNestedLoopJoin(condition=[true], joinType=[left]) EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0]) EnumerableTableScan(table=[[scott, DEPT]]) - EnumerableAggregate(group=[{0}]) - EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) - EnumerableAggregate(group=[{7}], c=[COUNT()]) - EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[35], expr#10=[=($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) - EnumerableTableScan(table=[[scott, EMP]]) + EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) + EnumerableAggregate(group=[{7}], c=[COUNT()]) + EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[35], expr#10=[=($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) + EnumerableTableScan(table=[[scott, EMP]]) !plan # Previous, as scalar sub-query. @@ -3010,11 +3009,10 @@ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[IS NULL($t1)], DEPTNO=[$t0], U=[$t2 EnumerableNestedLoopJoin(condition=[true], joinType=[left]) EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0]) EnumerableTableScan(table=[[scott, DEPT]]) - EnumerableAggregate(group=[{0}]) - EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) - EnumerableAggregate(group=[{7}], c=[COUNT()]) - EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[35], expr#10=[=($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) - EnumerableTableScan(table=[[scott, EMP]]) + EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], expr#3=[1], expr#4=[>($t1, $t3)], i=[$t2], $condition=[$t4]) + EnumerableAggregate(group=[{7}], c=[COUNT()]) + EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[35], expr#10=[=($t8, $t9)], proj#0..7=[{exprs}], $condition=[$t10]) + EnumerableTableScan(table=[[scott, EMP]]) !plan # singleton keys which a uniqueness constraint indicates that the relation is already unique. diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java index 384d98409b..17b6dba24a 100644 --- a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java +++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java @@ -1018,13 +1018,18 @@ public class DruidAdapter2IT { + "where \"product_name\" = 'High Top Dried Mushrooms'\n" + "and \"quarter\" in ('Q2', 'Q3')\n" + "and \"state_province\" = 'WA'"; - final String druidQuery1 = "{'queryType':'groupBy','dataSource':'foodmart','granularity':'all'"; - final String druidQuery2 = "'filter':{'type':'and','fields':[{'type':'selector','dimension':" - + "'product_name','value':'High Top Dried Mushrooms'},{'type':'or','fields':[{'type':'selector'," - + "'dimension':'quarter','value':'Q2'},{'type':'selector','dimension':'quarter'," - + "'value':'Q3'}]},{'type':'selector','dimension':'state_province','value':'WA'}]}," - + "'aggregations':[]," - + "'intervals':['1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z']}"; + final String druidQuery1 = "{\"queryType\":\"groupBy\"," + + "\"dataSource\":\"foodmart\",\"granularity\":\"all\""; + final String druidQuery2 = "\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":" + + "\"selector\",\"dimension\":\"product_name\",\"value\":\"High Top Dried Mushrooms\"}," + + "{\"type\":\"or\",\"fields\":[{\"type\":\"selector\",\"dimension\":" + + "\"quarter\",\"value\":\"Q2\"},{\"type\":\"selector\",\"dimension\":\"quarter\"," + + "\"value\":\"Q3\"}]},{\"type\":\"selector\",\"dimension\":" + + "\"state_province\",\"value\":\"WA\"}]},\"aggregations\":[]," + + "\"postAggregations\":[{\"type\":\"expression\"," + + "\"name\":\"state_province\",\"expression\":\"'WA'\"},{\"type\":\"expression\"," + + "\"name\":\"product_name\",\"expression\":\"'High Top Dried Mushrooms'\"}]," + + "\"intervals\":[\"1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z\"]}"; final String explain = "PLAN=EnumerableInterpreter\n" + " DruidQuery(table=[[foodmart, foodmart]], " + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], " @@ -1032,9 +1037,11 @@ public class DruidAdapter2IT { + "=($3, 'High Top Dried Mushrooms'), " + "SEARCH($87, Sarg['Q2':VARCHAR, 'Q3':VARCHAR]:VARCHAR), " + "=($30, 'WA'))], " - + "projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n"; + + "projects=[[$29]], groups=[{0}], aggs=[[]], " + + "post_projects=[[CAST('WA':VARCHAR):VARCHAR, $0, " + + "CAST('High Top Dried Mushrooms':VARCHAR):VARCHAR]])\n"; sql(sql) - .queryContains(new DruidChecker(druidQuery1, druidQuery2)) + .queryContains(new DruidChecker(false, druidQuery1, druidQuery2)) .explainContains(explain) .returnsUnordered( "state_province=WA; city=Bremerton; product_name=High Top Dried Mushrooms", @@ -1851,8 +1858,10 @@ public class DruidAdapter2IT { final String sql = "SELECT \"store_state\", \"brand_name\", sum(\"store_sales\") - " + "sum(\"store_cost\") as a from \"foodmart\" where extract (week from \"timestamp\")" + " IN (10,11) and \"brand_name\"='Bird Call' group by \"store_state\", \"brand_name\""; - final String druidQuery = "\"postAggregations\":[{\"type\":\"expression\",\"name\":\"A\"," - + "\"expression\":\"(\\\"$f2\\\" - \\\"$f3\\\")\"}]"; + final String druidQuery = "\"postAggregations\":[{\"type\":" + + "\"expression\",\"name\":\"brand_name\"," + + "\"expression\":\"'Bird Call'\"},{\"type\":\"expression\",\"name\":\"A\"," + + "\"expression\":\"(\\\"$f1\\\" - \\\"$f2\\\")\"}]"; final String plan = "PLAN=EnumerableInterpreter\n" + " DruidQuery(table=[[foodmart, foodmart]], " + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], filter=[AND(=("; @@ -1861,7 +1870,7 @@ public class DruidAdapter2IT { .returnsOrdered("store_state=CA; brand_name=Bird Call; A=34.3646", "store_state=OR; brand_name=Bird Call; A=39.1636", "store_state=WA; brand_name=Bird Call; A=53.7425") - .queryContains(new DruidChecker(druidQuery)); + .queryContains(new DruidChecker(false, druidQuery)); } @Test void testExtractFilterWorkWithPostAggregationsWithConstant() { 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 e47fe4376e..fe8419da80 100644 --- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java +++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java @@ -1293,13 +1293,18 @@ public class DruidAdapterIT { + "where \"product_name\" = 'High Top Dried Mushrooms'\n" + "and \"quarter\" in ('Q2', 'Q3')\n" + "and \"state_province\" = 'WA'"; - final String druidQuery1 = "{'queryType':'groupBy','dataSource':'foodmart','granularity':'all'"; - final String druidQuery2 = "'filter':{'type':'and','fields':[{'type':'selector','dimension':" - + "'product_name','value':'High Top Dried Mushrooms'},{'type':'or','fields':[{'type':'selector'," - + "'dimension':'quarter','value':'Q2'},{'type':'selector','dimension':'quarter'," - + "'value':'Q3'}]},{'type':'selector','dimension':'state_province','value':'WA'}]}," - + "'aggregations':[]," - + "'intervals':['1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z']}"; + final String druidQuery1 = "{\"queryType\":\"groupBy\"," + + "\"dataSource\":\"foodmart\",\"granularity\":\"all\""; + final String druidQuery2 = "\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":" + + "\"selector\",\"dimension\":\"product_name\",\"value\":\"High Top Dried Mushrooms\"}," + + "{\"type\":\"or\",\"fields\":[{\"type\":\"selector\",\"dimension\":" + + "\"quarter\",\"value\":\"Q2\"},{\"type\":\"selector\",\"dimension\":\"quarter\"," + + "\"value\":\"Q3\"}]},{\"type\":\"selector\",\"dimension\":" + + "\"state_province\",\"value\":\"WA\"}]},\"aggregations\":[]," + + "\"postAggregations\":[{\"type\":\"expression\"," + + "\"name\":\"state_province\",\"expression\":\"'WA'\"},{\"type\":\"expression\"," + + "\"name\":\"product_name\",\"expression\":\"'High Top Dried Mushrooms'\"}]," + + "\"intervals\":[\"1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z\"]}"; final String explain = "PLAN=EnumerableInterpreter\n" + " DruidQuery(table=[[foodmart, foodmart]], " + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], " @@ -1307,9 +1312,11 @@ public class DruidAdapterIT { + "=($3, 'High Top Dried Mushrooms'), " + "SEARCH($87, Sarg['Q2':VARCHAR, 'Q3':VARCHAR]:VARCHAR), " + "=($30, 'WA'))], " - + "projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n"; + + "projects=[[$29]], groups=[{0}], aggs=[[]], " + + "post_projects=[[CAST('WA':VARCHAR):VARCHAR, $0, " + + "CAST('High Top Dried Mushrooms':VARCHAR):VARCHAR]])\n"; sql(sql) - .queryContains(new DruidChecker(druidQuery1, druidQuery2)) + .queryContains(new DruidChecker(false, druidQuery1, druidQuery2)) .explainContains(explain) .returnsUnordered( "state_province=WA; city=Bremerton; product_name=High Top Dried Mushrooms", @@ -2157,8 +2164,10 @@ public class DruidAdapterIT { final String sql = "SELECT \"store_state\", \"brand_name\", sum(\"store_sales\") - " + "sum(\"store_cost\") as a from \"foodmart\" where extract (week from \"timestamp\")" + " IN (10,11) and \"brand_name\"='Bird Call' group by \"store_state\", \"brand_name\""; - final String druidQuery = "\"postAggregations\":[{\"type\":\"expression\",\"name\":\"A\"," - + "\"expression\":\"(\\\"$f2\\\" - \\\"$f3\\\")\"}]"; + final String druidQuery = "\"postAggregations\":[{\"type\":" + + "\"expression\",\"name\":\"brand_name\"," + + "\"expression\":\"'Bird Call'\"},{\"type\":\"expression\",\"name\":\"A\"," + + "\"expression\":\"(\\\"$f1\\\" - \\\"$f2\\\")\"}]"; final String plan = "PLAN=EnumerableInterpreter\n" + " DruidQuery(table=[[foodmart, foodmart]], " + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], filter=[AND(=("; @@ -2167,7 +2176,7 @@ public class DruidAdapterIT { .returnsOrdered("store_state=CA; brand_name=Bird Call; A=34.3646", "store_state=OR; brand_name=Bird Call; A=39.1636", "store_state=WA; brand_name=Bird Call; A=53.7425") - .queryContains(new DruidChecker(druidQuery)); + .queryContains(new DruidChecker(false, druidQuery)); } @Test void testExtractFilterWorkWithPostAggregationsWithConstant() {
