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() {

Reply via email to