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 <francesco.g...@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>. */