You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2023/01/06 06:08:11 UTC
[doris] branch master updated: [fix](nereids) Convert to datetime when binary expr's left is date and right is int type (#15615)
This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7f84db310a [fix](nereids) Convert to datetime when binary expr's left is date and right is int type (#15615)
7f84db310a is described below
commit 7f84db310a5f8310b5e308606efd6351a854bb9f
Author: AKIRA <33...@users.noreply.github.com>
AuthorDate: Fri Jan 6 14:08:05 2023 +0800
[fix](nereids) Convert to datetime when binary expr's left is date and right is int type (#15615)
In the below case, expression ` date > 20200101` should implicit cast date both side to datetime instead of bigint
```sql
CREATE TABLE `part_by_date`
(
`date` date NOT NULL COMMENT '',
`id` int(11) NOT NULL COMMENT ''
) ENGINE=OLAP
UNIQUE KEY(`date`, `id`)
PARTITION BY RANGE(`date`)
(PARTITION p201912 VALUES [('0000-01-01'), ('2020-01-01')),
PARTITION p202001 VALUES [('2020-01-01'), ('2020-02-01')))
DISTRIBUTED BY HASH(`id`) BUCKETS 3
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
INSERT INTO part_by_date VALUES('0001-02-01', 1),('2020-01-15', 2);
SELECT
id
FROM
part_by_date
WHERE date > 20200101;
```
---
.../expression/rewrite/rules/TypeCoercion.java | 14 +++---
.../trees/expressions/BinaryArithmetic.java | 3 +-
.../trees/plans/logical/LogicalSetOperation.java | 2 +-
.../doris/nereids/util/TypeCoercionUtils.java | 29 ++++++++++---
.../org/apache/doris/planner/OriginalPlanner.java | 2 -
.../doris/nereids/util/TypeCoercionUtilsTest.java | 3 +-
.../data/nereids_syntax_p0/test_convert.out | 4 ++
.../suites/nereids_syntax_p0/test_convert.groovy | 50 ++++++++++++++++++++++
8 files changed, 90 insertions(+), 17 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
index a81aefc986..e1bb596a00 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/TypeCoercion.java
@@ -77,23 +77,23 @@ public class TypeCoercion extends AbstractExpressionRewriteRule {
// TODO: add other expression visitor function to do type coercion if necessary.
@Override
- public Expression visitBinaryOperator(BinaryOperator binaryOperator, ExpressionRewriteContext context) {
- Expression left = rewrite(binaryOperator.left(), context);
- Expression right = rewrite(binaryOperator.right(), context);
+ public Expression visitBinaryOperator(BinaryOperator op, ExpressionRewriteContext context) {
+ Expression left = rewrite(op.left(), context);
+ Expression right = rewrite(op.right(), context);
return Optional.of(TypeCoercionUtils.canHandleTypeCoercion(left.getDataType(), right.getDataType()))
.filter(Boolean::booleanValue)
- .map(b -> TypeCoercionUtils.findTightestCommonType(left.getDataType(), right.getDataType()))
+ .map(b -> TypeCoercionUtils.findTightestCommonType(op, left.getDataType(), right.getDataType()))
.filter(Optional::isPresent)
.map(Optional::get)
- .filter(ct -> binaryOperator.inputType().acceptsType(ct))
+ .filter(ct -> op.inputType().acceptsType(ct))
.filter(ct -> !left.getDataType().equals(ct) || !right.getDataType().equals(ct))
.map(commonType -> {
Expression newLeft = TypeCoercionUtils.castIfNotSameType(left, commonType);
Expression newRight = TypeCoercionUtils.castIfNotSameType(right, commonType);
- return binaryOperator.withChildren(newLeft, newRight);
+ return op.withChildren(newLeft, newRight);
})
- .orElse(binaryOperator.withChildren(left, right));
+ .orElse(op.withChildren(left, right));
}
@Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BinaryArithmetic.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BinaryArithmetic.java
index ec45b4f707..942252ccaf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BinaryArithmetic.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/BinaryArithmetic.java
@@ -48,7 +48,8 @@ public abstract class BinaryArithmetic extends BinaryOperator implements Propaga
try {
return TypeCoercionUtils.findCommonNumericsType(left().getDataType(), right().getDataType());
} catch (Exception e) {
- return TypeCoercionUtils.findTightestCommonType(left().getDataType(), right().getDataType())
+ return TypeCoercionUtils.findTightestCommonType(this,
+ left().getDataType(), right().getDataType())
.orElseGet(() -> left().getDataType());
}
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java
index 10c5eb275c..1e69cda49c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java
@@ -134,7 +134,7 @@ public abstract class LogicalSetOperation extends AbstractLogicalPlan implements
Slot right = child(1).getOutput().get(i);
if (TypeCoercionUtils.canHandleTypeCoercion(left.getDataType(), right.getDataType())) {
Optional<DataType> tightestCommonType =
- TypeCoercionUtils.findTightestCommonType(left.getDataType(), right.getDataType());
+ TypeCoercionUtils.findTightestCommonType(null, left.getDataType(), right.getDataType());
if (tightestCommonType.isPresent()) {
Expression newLeft = TypeCoercionUtils.castIfNotSameType(left, tightestCommonType.get());
Expression newRight = TypeCoercionUtils.castIfNotSameType(right, tightestCommonType.get());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
index ccb0796ae6..bc357e4fef 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java
@@ -19,6 +19,8 @@ package org.apache.doris.nereids.util;
import org.apache.doris.nereids.annotation.Developing;
import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.trees.expressions.BinaryArithmetic;
+import org.apache.doris.nereids.trees.expressions.BinaryOperator;
import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.literal.Literal;
@@ -186,7 +188,8 @@ public class TypeCoercionUtils {
* find the tightest common type for two type
*/
@Developing
- public static Optional<DataType> findTightestCommonType(DataType left, DataType right) {
+ public static Optional<DataType> findTightestCommonType(BinaryOperator binaryOperator,
+ DataType left, DataType right) {
// TODO: compatible with origin planner and BE
// TODO: when add new type, add it to here
DataType tightestCommonType = null;
@@ -234,9 +237,12 @@ public class TypeCoercionUtils {
} else if (left instanceof DateV2Type || right instanceof DateV2Type) {
tightestCommonType = DateV2Type.INSTANCE;
}
- } else if ((left instanceof DateLikeType && right instanceof IntegralType)
- || (right instanceof DateLikeType && left instanceof IntegralType)) {
- tightestCommonType = BigIntType.INSTANCE;
+ } else if (canCompareDate(left, right)) {
+ if (binaryOperator instanceof BinaryArithmetic) {
+ tightestCommonType = IntegerType.INSTANCE;
+ } else {
+ tightestCommonType = DateTimeType.INSTANCE;
+ }
}
return tightestCommonType == null ? Optional.of(DoubleType.INSTANCE) : Optional.of(tightestCommonType);
}
@@ -302,7 +308,7 @@ public class TypeCoercionUtils {
// TODO: need to rethink how to handle char and varchar to return char or varchar as much as possible.
return Stream
.<Supplier<Optional<DataType>>>of(
- () -> findTightestCommonType(left, right),
+ () -> findTightestCommonType(null, left, right),
() -> findWiderTypeForDecimal(left, right),
() -> characterPromotion(left, right),
() -> findTypeForComplex(left, right))
@@ -381,4 +387,17 @@ public class TypeCoercionUtils {
return new Cast(input, dataType);
}
}
+
+ private static boolean canCompareDate(DataType left, DataType right) {
+ if (left instanceof DateLikeType) {
+ return right.isDateType() || right.isStringType() || right instanceof TinyIntType
+ || right instanceof SmallIntType || right instanceof IntegerType
+ || right instanceof BigIntType;
+ } else if (right instanceof DateLikeType) {
+ return left.isStringType() || left instanceof TinyIntType
+ || left instanceof SmallIntType || left instanceof IntegerType
+ || left instanceof BigIntType;
+ }
+ return false;
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java
index d882c65119..c2c15c5c31 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java
@@ -91,8 +91,6 @@ public class OriginalPlanner extends Planner {
return analyzer.getAssignedRuntimeFilter();
}
- /**
- */
private void setResultExprScale(Analyzer analyzer, ArrayList<Expr> outputExprs) {
for (TupleDescriptor tupleDesc : analyzer.getDescTbl().getTupleDescs()) {
for (SlotDescriptor slotDesc : tupleDesc.getSlots()) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java
index bbd75d48c2..16ac52b8ec 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/TypeCoercionUtilsTest.java
@@ -155,7 +155,8 @@ public class TypeCoercionUtilsTest {
}
private void testFindTightestCommonType(DataType commonType, DataType left, DataType right) {
- Assertions.assertEquals(Optional.ofNullable(commonType), TypeCoercionUtils.findTightestCommonType(left, right));
+ Assertions.assertEquals(Optional.ofNullable(commonType), TypeCoercionUtils.findTightestCommonType(null,
+ left, right));
}
@Test
diff --git a/regression-test/data/nereids_syntax_p0/test_convert.out b/regression-test/data/nereids_syntax_p0/test_convert.out
new file mode 100644
index 0000000000..4ee136aef2
--- /dev/null
+++ b/regression-test/data/nereids_syntax_p0/test_convert.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !sql --
+2
+
diff --git a/regression-test/suites/nereids_syntax_p0/test_convert.groovy b/regression-test/suites/nereids_syntax_p0/test_convert.groovy
new file mode 100644
index 0000000000..9f402c4a7e
--- /dev/null
+++ b/regression-test/suites/nereids_syntax_p0/test_convert.groovy
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_implicit_convert") {
+
+ sql """
+ DROP TABLE IF EXISTS part_by_date
+ """
+ sql """
+ CREATE TABLE `part_by_date`
+ (
+ `date` date NOT NULL COMMENT '',
+ `id` int(11) NOT NULL COMMENT ''
+ ) ENGINE=OLAP
+ UNIQUE KEY(`date`, `id`)
+ PARTITION BY RANGE(`date`)
+ (PARTITION p201912 VALUES [('0000-01-01'), ('2020-01-01')),
+ PARTITION p202001 VALUES [('2020-01-01'), ('2020-02-01')))
+ DISTRIBUTED BY HASH(`id`) BUCKETS 3
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ """
+
+ sql """
+ INSERT INTO part_by_date VALUES('0001-02-01', 1),('2020-01-15', 2);
+ """
+
+ qt_sql """
+ SELECT
+ id
+ FROM
+ part_by_date
+ WHERE date > 20200101;
+ """
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org