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 2021/06/11 12:26:58 UTC
[calcite] branch master updated: [CALCITE-4619] `Full join` plan
cannot be executed in MySQL (Jiasen Sheng)
This is an automated email from the ASF dual-hosted git repository.
zabetak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new e5477e7 [CALCITE-4619] `Full join` plan cannot be executed in MySQL (Jiasen Sheng)
e5477e7 is described below
commit e5477e7cda4ed9747d970b830d1fe9c53c49f2f3
Author: shengjiasen <an...@gmail.com>
AuthorDate: Wed Jun 9 19:07:24 2021 +0800
[CALCITE-4619] `Full join` plan cannot be executed in MySQL (Jiasen Sheng)
Close apache/calcite#2430
---
.../org/apache/calcite/adapter/jdbc/JdbcRules.java | 7 +++++++
.../java/org/apache/calcite/sql/SqlDialect.java | 8 ++++++++
.../apache/calcite/sql/dialect/H2SqlDialect.java | 5 +++++
.../calcite/sql/dialect/MysqlSqlDialect.java | 5 +++++
.../org/apache/calcite/test/JdbcAdapterTest.java | 23 ++++++++++++++++++++++
5 files changed, 48 insertions(+)
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 d173472..c6adeb6 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
@@ -24,6 +24,7 @@ import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelRule;
import org.apache.calcite.plan.RelTraitSet;
@@ -361,6 +362,12 @@ public class JdbcRules {
return false;
}
}
+
+ @Override public boolean matches(RelOptRuleCall call) {
+ Join join = call.rel(0);
+ JoinRelType joinType = join.getJoinType();
+ return ((JdbcConvention) getOutConvention()).dialect.supportsJoinType(joinType);
+ }
}
/** Join operator implemented in JDBC convention. */
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
index 3bbdb90..fdb69fd 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
@@ -22,6 +22,7 @@ import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.config.NullCollation;
import org.apache.calcite.linq4j.function.Experimental;
import org.apache.calcite.rel.RelFieldCollation;
+import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
@@ -1004,6 +1005,13 @@ public class SqlDialect {
return false;
}
+ /**
+ * Returns whether this dialect support the specified type of join.
+ */
+ public boolean supportsJoinType(JoinRelType joinType) {
+ return true;
+ }
+
/** Returns how NULL values are sorted if an ORDER BY item does not contain
* NULLS ASCENDING or NULLS DESCENDING. */
public NullCollation getNullCollation() {
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java
index 18c086d..1721971 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java
@@ -16,6 +16,7 @@
*/
package org.apache.calcite.sql.dialect;
+import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.sql.SqlDialect;
/**
@@ -40,4 +41,8 @@ public class H2SqlDialect extends SqlDialect {
@Override public boolean supportsWindowFunctions() {
return false;
}
+
+ @Override public boolean supportsJoinType(JoinRelType joinType) {
+ return joinType != JoinRelType.FULL;
+ }
}
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
index 8667f1a..be1c8ef 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.util.Casing;
import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.avatica.util.TimeUnitRange;
import org.apache.calcite.config.NullCollation;
+import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
@@ -322,6 +323,10 @@ public class MysqlSqlDialect extends SqlDialect {
}
}
+ @Override public boolean supportsJoinType(JoinRelType joinType) {
+ return joinType != JoinRelType.FULL;
+ }
+
private static TimeUnit validate(TimeUnit timeUnit) {
switch (timeUnit) {
case MICROSECOND:
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 ebc2ee0..4607667 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -1045,6 +1045,29 @@ class JdbcAdapterTest {
.planHasSql("SELECT \"EMPNO\", \"ENAME\"\nFROM \"SCOTT\".\"EMP\"\nWHERE \"EMPNO\" = ?");
}
+ /**
+ * Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-4619">[CALCITE-4619]
+ * "Full join" generates an incorrect execution plan under mysql</a>. */
+ @Test void testFullJoinNonSupportedDialect() {
+ CalciteAssert.model(JdbcTest.SCOTT_MODEL)
+ .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.H2
+ || CalciteAssert.DB == CalciteAssert.DatabaseInstance.MYSQL)
+ .query("select empno, ename, e.deptno, dname\n"
+ + "from scott.emp e full join scott.dept d\n"
+ + "on e.deptno = d.deptno")
+ .explainContains("PLAN=EnumerableCalc(expr#0..4=[{inputs}], proj#0..2=[{exprs}],"
+ + " DNAME=[$t4])\n"
+ + " EnumerableHashJoin(condition=[=($2, $3)], joinType=[full])\n"
+ + " JdbcToEnumerableConverter\n"
+ + " JdbcProject(EMPNO=[$0], ENAME=[$1], DEPTNO=[$7])\n"
+ + " JdbcTableScan(table=[[SCOTT, EMP]])\n"
+ + " JdbcToEnumerableConverter\n"
+ + " JdbcProject(DEPTNO=[$0], DNAME=[$1])\n"
+ + " JdbcTableScan(table=[[SCOTT, DEPT]])")
+ .runs();
+ }
+
/** Acquires a lock, and releases it when closed. */
static class LockWrapper implements AutoCloseable {
private final Lock lock;