You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by za...@apache.org on 2022/06/07 15:22:01 UTC

[calcite] branch main updated: [CALCITE-4907] JDBC adapter cannot push down join ON TRUE (cartesian product)

This is an automated email from the ASF dual-hosted git repository.

zabetak pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new a9aea934d [CALCITE-4907] JDBC adapter cannot push down join ON TRUE (cartesian product)
a9aea934d is described below

commit a9aea934dc29395ca8ee81df5dcf0d50ac823023
Author: Francesco Gini <fr...@gmail.com>
AuthorDate: Sun Nov 28 18:37:05 2021 +0000

    [CALCITE-4907] JDBC adapter cannot push down join ON TRUE (cartesian product)
    
    Close apache/calcite#2620
---
 .../org/apache/calcite/adapter/jdbc/JdbcRules.java |  3 ++
 .../org/apache/calcite/test/JdbcAdapterTest.java   | 43 ++++++++++++++++------
 2 files changed, 34 insertions(+), 12 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 37fb747a8..6c9b545e6 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
@@ -331,6 +331,9 @@ public class JdbcRules {
     private static boolean canJoinOnCondition(RexNode node) {
       final List<RexNode> operands;
       switch (node.getKind()) {
+      case LITERAL:
+        // literal on a join condition would be TRUE or FALSE
+        return true;
       case AND:
       case OR:
         operands = ((RexCall) node).getOperands();
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 d4bd9dc9c..2b0a5aaa2 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -50,23 +50,25 @@ class JdbcAdapterTest {
    * same time. */
   private static final ReentrantLock LOCK = new ReentrantLock();
 
-  /** VALUES is not pushed down, currently. */
+  /** VALUES is pushed down. */
   @Test void testValuesPlan() {
     final String sql = "select * from \"days\", (values 1, 2) as t(c)";
-    final String explain = "PLAN="
-        + "EnumerableNestedLoopJoin(condition=[true], joinType=[inner])\n"
-        + "  JdbcToEnumerableConverter\n"
+    final String explain = "PLAN=JdbcToEnumerableConverter\n"
+        + "  JdbcJoin(condition=[true], joinType=[inner])\n"
         + "    JdbcTableScan(table=[[foodmart, days]])\n"
-        + "  EnumerableValues(tuples=[[{ 1 }, { 2 }]])";
+        + "    JdbcValues(tuples=[[{ 1 }, { 2 }]])";
     final String jdbcSql = "SELECT *\n"
-        + "FROM \"foodmart\".\"days\"";
+        + "FROM \"foodmart\".\"days\",\n"
+        + "(VALUES (1),\n"
+        + "(2)) AS \"t\" (\"C\")";
     CalciteAssert.model(FoodmartSchema.FOODMART_MODEL)
         .query(sql)
         .explainContains(explain)
         .runs()
         .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB
             || CalciteAssert.DB == DatabaseInstance.POSTGRESQL)
-        .planHasSql(jdbcSql);
+        .planHasSql(jdbcSql)
+        .returnsCount(14);
   }
 
   @Test void testUnionPlan() {
@@ -360,17 +362,14 @@ class JdbcAdapterTest {
             + "FROM \"SCOTT\".\"DEPT\") AS \"t0\" ON \"t\".\"DEPTNO\" = \"t0\".\"DEPTNO\"");
   }
 
-  // JdbcJoin not used for this
   @Test void testCartesianJoinWithoutKeyPlan() {
     CalciteAssert.model(JdbcTest.SCOTT_MODEL)
         .query("select empno, ename, d.deptno, dname\n"
             + "from scott.emp e,scott.dept d")
-        .explainContains("PLAN=EnumerableNestedLoopJoin(condition=[true], "
-            + "joinType=[inner])\n"
-            + "  JdbcToEnumerableConverter\n"
+        .explainContains("PLAN=JdbcToEnumerableConverter\n"
+            + "  JdbcJoin(condition=[true], joinType=[inner])\n"
             + "    JdbcProject(EMPNO=[$0], ENAME=[$1])\n"
             + "      JdbcTableScan(table=[[SCOTT, EMP]])\n"
-            + "  JdbcToEnumerableConverter\n"
             + "    JdbcProject(DEPTNO=[$0], DNAME=[$1])\n"
             + "      JdbcTableScan(table=[[SCOTT, DEPT]])")
         .runs()
@@ -402,6 +401,26 @@ class JdbcAdapterTest {
             + "FROM \"SCOTT\".\"DEPT\") AS \"t1\" ON \"t0\".\"DEPTNO\" = \"t1\".\"DEPTNO\"");
   }
 
+  @Test void testJoinConditionAlwaysTruePushDown() {
+    CalciteAssert.model(JdbcTest.SCOTT_MODEL)
+        .query("select empno, ename, d.deptno, dname\n"
+                + "from scott.emp e,scott.dept d\n"
+                + "where true")
+        .explainContains("PLAN=JdbcToEnumerableConverter\n"
+                + "  JdbcJoin(condition=[true], joinType=[inner])\n"
+                + "    JdbcProject(EMPNO=[$0], ENAME=[$1])\n"
+                + "      JdbcTableScan(table=[[SCOTT, EMP]])\n"
+                + "    JdbcProject(DEPTNO=[$0], DNAME=[$1])\n"
+                + "      JdbcTableScan(table=[[SCOTT, DEPT]])")
+        .runs()
+        .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
+        .planHasSql("SELECT *\n"
+                + "FROM (SELECT \"EMPNO\", \"ENAME\"\n"
+                + "FROM \"SCOTT\".\"EMP\") AS \"t\",\n"
+                + "(SELECT \"DEPTNO\", \"DNAME\"\n"
+                + "FROM \"SCOTT\".\"DEPT\") AS \"t0\"");
+  }
+
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-893">[CALCITE-893]
    * Theta join in JdbcAdapter</a>. */