This is an automated email from the ASF dual-hosted git repository.
xiong 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 fc2fd2dd7 [CALCITE-5021] Double JOIN is created for NOT IN when
IN-list that the values all non-nullable is converted to Values
fc2fd2dd7 is described below
commit fc2fd2dd7efe237905f53ed754a2af2dd0a669ff
Author: NobiGo <[email protected]>
AuthorDate: Fri Feb 25 10:35:13 2022 +0800
[CALCITE-5021] Double JOIN is created for NOT IN when IN-list that the
values all non-nullable is converted to Values
---
.../org/apache/calcite/sql/type/SqlTypeUtil.java | 28 ++++++++++++++++++
.../apache/calcite/sql2rel/SqlToRelConverter.java | 23 ++++++---------
.../apache/calcite/test/SqlToRelConverterTest.xml | 8 +++---
core/src/test/resources/sql/sub-query.iq | 33 +++++++++++++++++++++-
4 files changed, 73 insertions(+), 19 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
index 0fcff9c33..3f5a8ec96 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
@@ -294,6 +294,34 @@ public abstract class SqlTypeUtil {
return false;
}
+ /**
+ * Creates a RelDataType having the same type of the sourceRelDataType,
+ * and the same nullability as the targetRelDataType.
+ */
+ public static RelDataType keepSourceTypeAndTargetNullability(RelDataType
sourceRelDataType,
+ RelDataType targetRelDataType,
+ RelDataTypeFactory typeFactory) {
+ if (!targetRelDataType.isStruct()) {
+ return typeFactory.createTypeWithNullability(
+ sourceRelDataType, targetRelDataType.isNullable());
+ }
+ List<RelDataTypeField> targetFields = targetRelDataType.getFieldList();
+ List<RelDataTypeField> sourceFields = sourceRelDataType.getFieldList();
+ ImmutableList.Builder<RelDataTypeField> newTargetField =
ImmutableList.builder();
+ for (int i = 0; i < targetRelDataType.getFieldCount(); i++) {
+ RelDataTypeField targetField = targetFields.get(i);
+ RelDataTypeField sourceField = sourceFields.get(i);
+ newTargetField.add(
+ new RelDataTypeFieldImpl(
+ sourceField.getName(),
+ sourceField.getIndex(),
+ keepSourceTypeAndTargetNullability(
+ sourceField.getType(), targetField.getType(),
typeFactory)));
+ }
+ RelDataType relDataType =
typeFactory.createStructType(newTargetField.build());
+ return typeFactory.createTypeWithNullability(relDataType,
targetRelDataType.isNullable());
+ }
+
/**
* Returns typeName.equals(type.getSqlTypeName()). If
* typeName.equals(SqlTypeName.Any) true is always returned.
diff --git
a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index c85c70148..c22ecc5a2 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -1397,15 +1397,16 @@ public class SqlToRelConverter {
//
// The first two lists contain the same number of fields.
final int k = (fieldCount - 1) / 2;
+ ImmutableList.Builder<RexNode> rexNodeBuilder = ImmutableList.builder();
+ rexNodeBuilder.add(rexNode);
for (int i = 0; i < k; i++) {
- rexNode =
+ rexNodeBuilder.add(
rexBuilder.makeCall(
- SqlStdOperatorTable.AND,
- rexNode,
- rexBuilder.makeCall(
- SqlStdOperatorTable.IS_NOT_NULL,
- rexBuilder.makeFieldAccess(rex, i)));
+ SqlStdOperatorTable.IS_NOT_NULL,
+ rexBuilder.makeFieldAccess(rex, i)));
}
+ rexNode = rexBuilder.makeCall(rexNode.getType(), SqlStdOperatorTable.AND,
+ RexUtil.flatten(rexNodeBuilder.build(),
SqlStdOperatorTable.AND));
return rexNode;
case TRUE_FALSE_UNKNOWN:
@@ -1717,15 +1718,9 @@ public class SqlToRelConverter {
final RelDataType rowType;
if (targetRowType != null) {
rowType =
- typeFactory.createTypeWithNullability(
- targetRowType,
- SqlTypeUtil.containsNullable(listType));
+ SqlTypeUtil.keepSourceTypeAndTargetNullability(targetRowType,
listType, typeFactory);
} else {
- rowType =
- SqlTypeUtil.promoteToRowType(
- typeFactory,
- listType,
- null);
+ rowType = SqlTypeUtil.promoteToRowType(typeFactory, listType, null);
}
final List<RelNode> unionInputs = new ArrayList<>();
diff --git
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 6684c5cbd..407f03ab4 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2713,7 +2713,7 @@ LogicalTableModify(table=[[CATALOG, SALES, EMPDEFAULTS]],
operation=[INSERT], fl
<![CDATA[
LogicalTableModify(table=[[SALES, EMPDEFAULTS]], operation=[INSERT],
flattened=[true])
LogicalFilter(condition=[=($7, 20)])
- LogicalProject(EMPNO=[$2], ENAME=[$0], JOB=[null:VARCHAR(10)],
MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)], SAL=[$4],
COMM=[null:INTEGER], DEPTNO=[$1], SLACKER=[null:BOOLEAN], EXTRA=[null:BOOLEAN],
UPDATED=[$3])
+ LogicalProject(EMPNO=[$2], ENAME=[$0], JOB=[null:VARCHAR(10)],
MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)], SAL=[CAST($4):INTEGER],
COMM=[null:INTEGER], DEPTNO=[CAST($1):INTEGER], SLACKER=[null:BOOLEAN],
EXTRA=[null:BOOLEAN], UPDATED=[CAST($3):TIMESTAMP(0)])
LogicalValues(tuples=[[{ 'Fred', 20, 44, 2017-03-12 13:03:05, 999999 }]])
]]>
</Resource>
@@ -2725,7 +2725,7 @@ LogicalTableModify(table=[[SALES, EMPDEFAULTS]],
operation=[INSERT], flattened=[
<Resource name="plan">
<![CDATA[
LogicalTableModify(table=[[SALES, EMPDEFAULTS]], operation=[INSERT],
flattened=[true])
- LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[null:INTEGER],
HIREDATE=[null:TIMESTAMP(0)], SAL=[555], COMM=[null:INTEGER], DEPTNO=[20],
SLACKER=[null:BOOLEAN])
+ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[CAST($2):VARCHAR(10)],
MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)], SAL=[555],
COMM=[null:INTEGER], DEPTNO=[20], SLACKER=[null:BOOLEAN])
LogicalValues(tuples=[[{ 34625, 'nom', 'accountant' }]])
]]>
</Resource>
@@ -2764,7 +2764,7 @@ values (10, 'Fred')]]>
<![CDATA[
LogicalTableModify(table=[[CATALOG, SALES, EMPNULLABLES]], operation=[INSERT],
flattened=[true])
LogicalFilter(condition=[>($5, 1000)])
- LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[null:VARCHAR(10)],
MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)], SAL=[null:INTEGER],
COMM=[null:INTEGER], DEPTNO=[20], SLACKER=[null:BOOLEAN])
+ LogicalProject(EMPNO=[$0], ENAME=[CAST($1):VARCHAR(20)],
JOB=[null:VARCHAR(10)], MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)],
SAL=[null:INTEGER], COMM=[null:INTEGER], DEPTNO=[20], SLACKER=[null:BOOLEAN])
LogicalValues(tuples=[[{ 10, 'Fred' }]])
]]>
</Resource>
@@ -2790,7 +2790,7 @@ values (150, 'Fred')]]>
<![CDATA[
LogicalTableModify(table=[[CATALOG, SALES, EMPNULLABLES]], operation=[INSERT],
flattened=[true])
LogicalFilter(condition=[>($5, 1000)])
- LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[null:VARCHAR(10)],
MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)], SAL=[null:INTEGER],
COMM=[null:INTEGER], DEPTNO=[20], SLACKER=[null:BOOLEAN])
+ LogicalProject(EMPNO=[$0], ENAME=[CAST($1):VARCHAR(20)],
JOB=[null:VARCHAR(10)], MGR=[null:INTEGER], HIREDATE=[null:TIMESTAMP(0)],
SAL=[null:INTEGER], COMM=[null:INTEGER], DEPTNO=[20], SLACKER=[null:BOOLEAN])
LogicalValues(tuples=[[{ 150, 'Fred' }]])
]]>
</Resource>
diff --git a/core/src/test/resources/sql/sub-query.iq
b/core/src/test/resources/sql/sub-query.iq
index cbdc992b7..bbad2b6f2 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -3345,11 +3345,42 @@ EnumerableCalc(expr#0..14=[{inputs}],
expr#15=[0:BIGINT], expr#16=[=($t8, $t15)]
EnumerableCalc(expr#0..9=[{inputs}], proj#0..9=[{exprs}], EMPNO0=[$t0],
DEPTNO0=[$t7])
EnumerableNestedLoopJoin(condition=[true], joinType=[inner])
EnumerableTableScan(table=[[scott, EMP]])
- EnumerableAggregate(group=[{}], agg#0=[COUNT()], agg#1=[COUNT($0,
$1)])
+ EnumerableAggregate(group=[{}], agg#0=[COUNT()], agg#1=[COUNT($1)])
EnumerableValues(tuples=[[{ 1, 2 }, { 3, null }]])
EnumerableSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC])
EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], proj#0..2=[{exprs}])
EnumerableValues(tuples=[[{ 1, 2 }, { 3, null }]])
!plan
+select * from "scott".emp where (empno, deptno) not in ((7369, 20), (7499,
30));
++-------+--------+-----------+------+------------+---------+---------+--------+
+| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
++-------+--------+-----------+------+------------+---------+---------+--------+
+| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
+| 7566 | JONES | MANAGER | 7839 | 1981-02-04 | 2975.00 | | 20 |
+| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
+| 7698 | BLAKE | MANAGER | 7839 | 1981-01-05 | 2850.00 | | 30 |
+| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | | 10 |
+| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | | 20 |
+| 7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
+| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
+| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 |
+| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | | 30 |
+| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
+| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | | 10 |
++-------+--------+-----------+------+------------+---------+---------+--------+
+(12 rows)
+
+!ok
+
+EnumerableCalc(expr#0..12=[{inputs}], expr#13=[IS NOT TRUE($t12)], expr#14=[IS
NULL($t9)], expr#15=[OR($t13, $t14)], proj#0..7=[{exprs}], $condition=[$t15])
+ EnumerableMergeJoin(condition=[AND(=($8, $10), =($9, $11))], joinType=[left])
+ EnumerableSort(sort0=[$8], sort1=[$9], dir0=[ASC], dir1=[ASC])
+ EnumerableCalc(expr#0..7=[{inputs}], proj#0..7=[{exprs}], EMPNO0=[$t0],
DEPTNO0=[$t7])
+ EnumerableTableScan(table=[[scott, EMP]])
+ EnumerableSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC])
+ EnumerableCalc(expr#0..1=[{inputs}], expr#2=[true], proj#0..2=[{exprs}])
+ EnumerableValues(tuples=[[{ 7369, 20 }, { 7499, 30 }]])
+!plan
+
# End sub-query.iq