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 47a6373e0a [feature](Nereids) support datev2 and datetimev2 type (#14263) 47a6373e0a is described below commit 47a6373e0a56046d55fc97296680c8b616d2221b Author: morrySnow <101034200+morrys...@users.noreply.github.com> AuthorDate: Wed Nov 16 15:51:48 2022 +0800 [feature](Nereids) support datev2 and datetimev2 type (#14263) 1. split DateLiteral and DateTimeLiteral into V1 and V2 2. add a type coercion about DateLikeType: DateTimeV2Type > DateTimeType > DateV2Type > DateType 3. add a rule to remove unnecessary CAST on DateLikeType in ComparisonPredicate --- .../expression/rewrite/ExpressionOptimization.java | 4 +- .../rewrite/rules/SimplifyComparisonPredicate.java | 140 +++++++++++++++++++++ .../trees/expressions/literal/DateLiteral.java | 45 ++++--- .../trees/expressions/literal/DateTimeLiteral.java | 68 ++++++---- .../expressions/literal/DateTimeV2Literal.java | 89 +++++++++++++ .../trees/expressions/literal/DateV2Literal.java | 49 ++++++++ .../apache/doris/nereids/types/DateTimeType.java | 4 +- .../apache/doris/nereids/types/DateTimeV2Type.java | 4 +- .../org/apache/doris/nereids/types/DateType.java | 4 +- .../org/apache/doris/nereids/types/DateV2Type.java | 4 +- .../{DateType.java => coercion/DateLikeType.java} | 27 +--- .../doris/nereids/util/TypeCoercionUtils.java | 19 +++ .../expression/rewrite/ExpressionRewriteTest.java | 76 +++++++++++ 13 files changed, 457 insertions(+), 76 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java index be0e7f0763..973af7ab72 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOptimization.java @@ -19,6 +19,7 @@ package org.apache.doris.nereids.rules.expression.rewrite; import org.apache.doris.nereids.rules.expression.rewrite.rules.DistinctPredicatesRule; import org.apache.doris.nereids.rules.expression.rewrite.rules.ExtractCommonFactorRule; +import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyComparisonPredicate; import com.google.common.collect.ImmutableList; @@ -30,7 +31,8 @@ import java.util.List; public class ExpressionOptimization extends ExpressionRewrite { public static final List<ExpressionRewriteRule> OPTIMIZE_REWRITE_RULES = ImmutableList.of( ExtractCommonFactorRule.INSTANCE, - DistinctPredicatesRule.INSTANCE); + DistinctPredicatesRule.INSTANCE, + SimplifyComparisonPredicate.INSTANCE); private static final ExpressionRuleExecutor EXECUTOR = new ExpressionRuleExecutor(OPTIMIZE_REWRITE_RULES); public ExpressionOptimization() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java new file mode 100644 index 0000000000..c96b924e2c --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyComparisonPredicate.java @@ -0,0 +1,140 @@ +// 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. + +package org.apache.doris.nereids.rules.expression.rewrite.rules; + +import org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule; +import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext; +import org.apache.doris.nereids.trees.expressions.Cast; +import org.apache.doris.nereids.trees.expressions.ComparisonPredicate; +import org.apache.doris.nereids.trees.expressions.EqualTo; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.GreaterThan; +import org.apache.doris.nereids.trees.expressions.GreaterThanEqual; +import org.apache.doris.nereids.trees.expressions.LessThan; +import org.apache.doris.nereids.trees.expressions.LessThanEqual; +import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.types.DateTimeType; +import org.apache.doris.nereids.types.DateType; +import org.apache.doris.nereids.types.DateV2Type; +import org.apache.doris.nereids.types.coercion.DateLikeType; + +/** + * simplify comparison + * such as: cast(c1 as DateV2) >= DateV2Literal --> c1 >= DateLiteral + */ +public class SimplifyComparisonPredicate extends AbstractExpressionRewriteRule { + + public static SimplifyComparisonPredicate INSTANCE = new SimplifyComparisonPredicate(); + + enum AdjustType { + LOWER, + UPPER, + NONE + } + + @Override + public Expression visitComparisonPredicate(ComparisonPredicate cp, ExpressionRewriteContext context) { + Expression left = rewrite(cp.left(), context); + Expression right = rewrite(cp.right(), context); + + // date like type + if (left.getDataType() instanceof DateLikeType && right.getDataType() instanceof DateLikeType) { + return processDateLikeTypeCoercion(cp, left, right); + } + + if (left != cp.left() || right != cp.right()) { + return cp.withChildren(left, right); + } else { + return cp; + } + } + + private Expression processDateLikeTypeCoercion(ComparisonPredicate cp, Expression left, Expression right) { + if (left instanceof DateLiteral) { + cp = cp.commute(); + Expression temp = left; + left = right; + right = temp; + } + + if (left instanceof Cast && right instanceof DateLiteral) { + Cast cast = (Cast) left; + if (cast.child().getDataType() instanceof DateTimeType) { + if (right instanceof DateTimeV2Literal) { + left = cast.child(); + right = migrateToDateTime((DateTimeV2Literal) right); + } + } + // datetime to datev2 + if (cast.child().getDataType() instanceof DateType || cast.child().getDataType() instanceof DateV2Type) { + if (right instanceof DateTimeLiteral) { + if (cannotAdjust((DateTimeLiteral) right, cp)) { + return cp; + } + AdjustType type = AdjustType.NONE; + if (cp instanceof GreaterThanEqual || cp instanceof LessThan) { + type = AdjustType.UPPER; + } else if (cp instanceof GreaterThan || cp instanceof LessThanEqual) { + type = AdjustType.LOWER; + } + right = migrateToDateV2((DateTimeLiteral) right, type); + if (cast.child().getDataType() instanceof DateV2Type) { + left = cast.child(); + } + } + } + + // datev2 to date + if (cast.child().getDataType() instanceof DateType) { + if (right instanceof DateV2Literal) { + left = cast.child(); + right = migrateToDate((DateV2Literal) right); + } + } + } + + if (left != cp.left() || right != cp.right()) { + return cp.withChildren(left, right); + } else { + return cp; + } + } + + private Expression migrateToDateTime(DateTimeV2Literal l) { + return new DateTimeLiteral(l.getYear(), l.getMonth(), l.getDay(), l.getHour(), l.getMinute(), l.getSecond()); + } + + private boolean cannotAdjust(DateTimeLiteral l, ComparisonPredicate cp) { + return cp instanceof EqualTo && (l.getHour() != 0 || l.getMinute() != 0 || l.getSecond() != 0); + } + + private Expression migrateToDateV2(DateTimeLiteral l, AdjustType type) { + DateV2Literal d = new DateV2Literal(l.getYear(), l.getMonth(), l.getDay()); + if (type == AdjustType.UPPER) { + d = d.plusDays(1); + } + return d; + } + + private Expression migrateToDate(DateV2Literal l) { + return new DateLiteral(l.getYear(), l.getMonth(), l.getDay()); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java index e3093c2a09..9a83db217a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java @@ -18,11 +18,12 @@ package org.apache.doris.nereids.trees.expressions.literal; import org.apache.doris.analysis.LiteralExpr; -import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateType; +import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.util.DateUtils; import org.apache.logging.log4j.LogManager; @@ -35,14 +36,13 @@ import org.joda.time.format.DateTimeFormatter; */ public class DateLiteral extends Literal { - private static final Logger LOG = LogManager.getLogger(DateLiteral.class); + protected static DateTimeFormatter DATE_FORMATTER = null; + protected static DateTimeFormatter DATE_FORMATTER_TWO_DIGIT = null; + protected static DateTimeFormatter DATEKEY_FORMATTER = null; + private static final Logger LOG = LogManager.getLogger(DateLiteral.class); private static final int DATEKEY_LENGTH = 8; - private static DateTimeFormatter DATE_FORMATTER = null; - private static DateTimeFormatter DATE_FORMATTER_TWO_DIGIT = null; - private static DateTimeFormatter DATEKEY_FORMATTER = null; - protected long year; protected long month; protected long day; @@ -59,7 +59,11 @@ public class DateLiteral extends Literal { } public DateLiteral(String s) throws AnalysisException { - super(DataType.fromCatalogType(ScalarType.createDateType())); + this(DateType.INSTANCE, s); + } + + protected DateLiteral(DateLikeType dataType, String s) throws AnalysisException { + super(dataType); init(s); } @@ -71,7 +75,14 @@ public class DateLiteral extends Literal { * C'tor for date type. */ public DateLiteral(long year, long month, long day) { - super(DateType.INSTANCE); + this(DateType.INSTANCE, year, month, day); + } + + /** + * C'tor for date type. + */ + public DateLiteral(DateLikeType dataType, long year, long month, long day) { + super(dataType); this.year = year; this.month = month; this.day = day; @@ -87,7 +98,7 @@ public class DateLiteral extends Literal { this.day = other.day; } - private void init(String s) throws AnalysisException { + protected void init(String s) throws AnalysisException { try { LocalDateTime dateTime; if (s.split("-")[0].length() == 2) { @@ -106,13 +117,13 @@ public class DateLiteral extends Literal { } @Override - public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { - return visitor.visitDateLiteral(this, context); + public Long getValue() { + return (year * 10000 + month * 100 + day) * 1000000L; } @Override - public Long getValue() { - return (year * 10000 + month * 100 + day) * 1000000L; + public String getStringValue() { + return String.format("%04d-%02d-%02d", year, month, day); } @Override @@ -121,18 +132,18 @@ public class DateLiteral extends Literal { } @Override - public String toString() { - return String.format("%04d-%02d-%02d", year, month, day); + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitDateLiteral(this, context); } @Override - public String getStringValue() { + public String toString() { return String.format("%04d-%02d-%02d", year, month, day); } @Override public LiteralExpr toLegacyLiteral() { - return new org.apache.doris.analysis.DateLiteral(year, month, day); + return new org.apache.doris.analysis.DateLiteral(year, month, day, Type.DATE); } public long getYear() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java index 5b62296057..a2211d5c8f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeLiteral.java @@ -18,9 +18,11 @@ package org.apache.doris.nereids.trees.expressions.literal; import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DateTimeType; +import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.util.DateUtils; import org.apache.logging.log4j.LogManager; @@ -34,20 +36,21 @@ import java.util.Objects; * date time literal. */ public class DateTimeLiteral extends DateLiteral { - private static final Logger LOG = LogManager.getLogger(DateTimeLiteral.class); - private static final int DATETIME_TO_MINUTE_STRING_LENGTH = 16; - private static final int DATETIME_TO_HOUR_STRING_LENGTH = 13; - private static final int DATETIME_DEFAULT_STRING_LENGTH = 10; - private static DateTimeFormatter DATE_TIME_DEFAULT_FORMATTER = null; - private static DateTimeFormatter DATE_TIME_FORMATTER = null; - private static DateTimeFormatter DATE_TIME_FORMATTER_TO_HOUR = null; - private static DateTimeFormatter DATE_TIME_FORMATTER_TO_MINUTE = null; - private static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null; + protected static final int DATETIME_TO_MINUTE_STRING_LENGTH = 16; + protected static final int DATETIME_TO_HOUR_STRING_LENGTH = 13; + protected static final int DATETIME_DEFAULT_STRING_LENGTH = 10; + protected static DateTimeFormatter DATE_TIME_DEFAULT_FORMATTER = null; + protected static DateTimeFormatter DATE_TIME_FORMATTER = null; + protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_HOUR = null; + protected static DateTimeFormatter DATE_TIME_FORMATTER_TO_MINUTE = null; + protected static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null; + + private static final Logger LOG = LogManager.getLogger(DateTimeLiteral.class); - private long hour; - private long minute; - private long second; + protected long hour; + protected long minute; + protected long second; static { try { @@ -63,7 +66,11 @@ public class DateTimeLiteral extends DateLiteral { } public DateTimeLiteral(String s) { - super(DateTimeType.INSTANCE); + this(DateTimeType.INSTANCE, s); + } + + protected DateTimeLiteral(DateLikeType dataType, String s) { + super(dataType); init(s); } @@ -71,7 +78,15 @@ public class DateTimeLiteral extends DateLiteral { * C'tor data time literal. */ public DateTimeLiteral(long year, long month, long day, long hour, long minute, long second) { - super(DateTimeType.INSTANCE); + this(DateTimeType.INSTANCE, year, month, day, hour, minute, second); + } + + /** + * C'tor data time literal. + */ + public DateTimeLiteral(DateLikeType dataType, long year, long month, long day, + long hour, long minute, long second) { + super(dataType); this.hour = hour; this.minute = minute; this.second = second; @@ -80,7 +95,8 @@ public class DateTimeLiteral extends DateLiteral { this.day = day; } - private void init(String s) throws AnalysisException { + @Override + protected void init(String s) throws AnalysisException { try { LocalDateTime dateTime; if (s.split("-")[0].length() == 2) { @@ -132,20 +148,25 @@ public class DateTimeLiteral extends DateLiteral { return String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); } - public DateTimeLiteral plusYears(int years) { - LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusYears(years); + @Override + public LiteralExpr toLegacyLiteral() { + return new org.apache.doris.analysis.DateLiteral(year, month, day, hour, minute, second, Type.DATETIME); + } + + public DateTimeLiteral plusDays(int days) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusDays(days); return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); } - public DateTimeLiteral plusMonths(int months) { - LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusMonths(months); + public DateTimeLiteral plusYears(int years) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusYears(years); return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); } - public DateTimeLiteral plusDays(int days) { - LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusDays(days); + public DateTimeLiteral plusMonths(int months) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusMonths(months); return new DateTimeLiteral(d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); } @@ -168,11 +189,6 @@ public class DateTimeLiteral extends DateLiteral { d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); } - @Override - public LiteralExpr toLegacyLiteral() { - return new org.apache.doris.analysis.DateLiteral(year, month, day, hour, minute, second); - } - public long getHour() { return hour; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java new file mode 100644 index 0000000000..4706c87a0e --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateTimeV2Literal.java @@ -0,0 +1,89 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.literal; + +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.types.DateTimeV2Type; + +import org.joda.time.LocalDateTime; + +/** + * date time v2 literal for nereids + */ +public class DateTimeV2Literal extends DateTimeLiteral { + + public DateTimeV2Literal(String s) { + super(DateTimeV2Type.INSTANCE, s); + } + + public DateTimeV2Literal(long year, long month, long day, long hour, long minute, long second) { + super(DateTimeV2Type.INSTANCE, year, month, day, hour, minute, second); + } + + public DateTimeV2Literal(DateTimeV2Type dataType, + long year, long month, long day, long hour, long minute, long second) { + super(dataType, year, month, day, hour, minute, second); + } + + @Override + public DateTimeV2Type getDataType() throws UnboundException { + return (DateTimeV2Type) super.getDataType(); + } + + @Override + public DateTimeV2Literal plusYears(int years) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusYears(years); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } + + @Override + public DateTimeV2Literal plusMonths(int months) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusMonths(months); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } + + @Override + public DateTimeLiteral plusDays(int days) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusDays(days); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } + + @Override + public DateTimeV2Literal plusHours(int hours) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusHours(hours); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } + + @Override + public DateTimeV2Literal plusMinutes(int minutes) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusMinutes(minutes); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } + + @Override + public DateTimeV2Literal plusSeconds(int seconds) { + LocalDateTime d = LocalDateTime.parse(getStringValue(), DATE_TIME_FORMATTER).plusSeconds(seconds); + return new DateTimeV2Literal(this.getDataType(), d.getYear(), d.getMonthOfYear(), d.getDayOfMonth(), + d.getHourOfDay(), d.getMinuteOfHour(), d.getSecondOfMinute()); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java new file mode 100644 index 0000000000..18fe8e9ca6 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java @@ -0,0 +1,49 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.literal; + +import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.catalog.Type; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.types.DateV2Type; + +import org.joda.time.LocalDateTime; + +/** + * date v2 literal for nereids + */ +public class DateV2Literal extends DateLiteral { + + public DateV2Literal(String s) throws AnalysisException { + super(DateV2Type.INSTANCE, s); + } + + public DateV2Literal(long year, long month, long day) { + super(DateV2Type.INSTANCE, year, month, day); + } + + @Override + public LiteralExpr toLegacyLiteral() { + return new org.apache.doris.analysis.DateLiteral(year, month, day, Type.DATEV2); + } + + public DateV2Literal plusDays(int days) { + LocalDateTime dateTime = LocalDateTime.parse(getStringValue(), DATE_FORMATTER).plusDays(days); + return new DateV2Literal(dateTime.getYear(), dateTime.getMonthOfYear(), dateTime.getDayOfMonth()); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java index 48a1b1a59c..b59e47d3eb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java @@ -18,12 +18,12 @@ package org.apache.doris.nereids.types; import org.apache.doris.catalog.Type; -import org.apache.doris.nereids.types.coercion.PrimitiveType; +import org.apache.doris.nereids.types.coercion.DateLikeType; /** * Datetime type in Nereids. */ -public class DateTimeType extends PrimitiveType { +public class DateTimeType extends DateLikeType { public static final DateTimeType INSTANCE = new DateTimeType(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java index d21649142b..c6737a1618 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java @@ -19,7 +19,7 @@ package org.apache.doris.nereids.types; import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; -import org.apache.doris.nereids.types.coercion.PrimitiveType; +import org.apache.doris.nereids.types.coercion.DateLikeType; import com.google.common.base.Preconditions; @@ -28,7 +28,7 @@ import java.util.Objects; /** * Datetime type in Nereids. */ -public class DateTimeV2Type extends PrimitiveType { +public class DateTimeV2Type extends DateLikeType { public static final int MAX_SCALE = 6; public static final DateTimeV2Type INSTANCE = new DateTimeV2Type(0); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java index 04bf92920c..a33fec9d1c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java @@ -18,12 +18,12 @@ package org.apache.doris.nereids.types; import org.apache.doris.catalog.Type; -import org.apache.doris.nereids.types.coercion.PrimitiveType; +import org.apache.doris.nereids.types.coercion.DateLikeType; /** * Date type in Nereids. */ -public class DateType extends PrimitiveType { +public class DateType extends DateLikeType { public static final DateType INSTANCE = new DateType(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateV2Type.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateV2Type.java index 4f5b808b84..9cf5efdbb6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateV2Type.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateV2Type.java @@ -18,12 +18,12 @@ package org.apache.doris.nereids.types; import org.apache.doris.catalog.Type; -import org.apache.doris.nereids.types.coercion.PrimitiveType; +import org.apache.doris.nereids.types.coercion.DateLikeType; /** * Date type in Nereids. */ -public class DateV2Type extends PrimitiveType { +public class DateV2Type extends DateLikeType { public static final DateV2Type INSTANCE = new DateV2Type(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java similarity index 61% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java index 04bf92920c..ee491fa18d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/DateLikeType.java @@ -15,31 +15,10 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.types; - -import org.apache.doris.catalog.Type; -import org.apache.doris.nereids.types.coercion.PrimitiveType; +package org.apache.doris.nereids.types.coercion; /** - * Date type in Nereids. + * date like type. */ -public class DateType extends PrimitiveType { - - public static final DateType INSTANCE = new DateType(); - - private static final int WIDTH = 16; - - private DateType() { - } - - @Override - public Type toCatalogDataType() { - return Type.DATE; - } - - @Override - public int width() { - return WIDTH; - } +public abstract class DateLikeType extends PrimitiveType { } - 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 7c9cc60ee2..d1cc520bbf 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 @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.BigIntType; import org.apache.doris.nereids.types.BooleanType; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeType; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.DecimalV2Type; import org.apache.doris.nereids.types.DoubleType; import org.apache.doris.nereids.types.FloatType; @@ -37,6 +39,7 @@ import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.coercion.AbstractDataType; import org.apache.doris.nereids.types.coercion.CharacterType; +import org.apache.doris.nereids.types.coercion.DateLikeType; import org.apache.doris.nereids.types.coercion.FractionalType; import org.apache.doris.nereids.types.coercion.IntegralType; import org.apache.doris.nereids.types.coercion.NumericType; @@ -207,6 +210,22 @@ public class TypeCoercionUtils { tightestCommonType = DecimalV2Type.widerDecimalV2Type((DecimalV2Type) left, DecimalV2Type.forType(right)); } else if (left instanceof IntegralType && right instanceof DecimalV2Type) { tightestCommonType = DecimalV2Type.widerDecimalV2Type((DecimalV2Type) right, DecimalV2Type.forType(left)); + } else if (left instanceof DateLikeType && right instanceof DateLikeType) { + if (left instanceof DateTimeV2Type && right instanceof DateTimeV2Type) { + if (((DateTimeV2Type) left).getScale() > ((DateTimeV2Type) right).getScale()) { + tightestCommonType = left; + } else { + tightestCommonType = right; + } + } else if (left instanceof DateTimeV2Type) { + tightestCommonType = left; + } else if (right instanceof DateTimeV2Type) { + tightestCommonType = right; + } else if (left instanceof DateTimeType || right instanceof DateTimeType) { + tightestCommonType = DateTimeType.INSTANCE; + } else if (left instanceof DateV2Type || right instanceof DateV2Type) { + tightestCommonType = DateV2Type.INSTANCE; + } } return Optional.ofNullable(tightestCommonType); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java index a77ab645e4..92810237fb 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java @@ -23,16 +23,26 @@ import org.apache.doris.nereids.rules.expression.rewrite.rules.ExtractCommonFact import org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateToEqualToRule; import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule; import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyCastRule; +import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyComparisonPredicate; import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule; import org.apache.doris.nereids.trees.expressions.Cast; +import org.apache.doris.nereids.trees.expressions.EqualTo; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.GreaterThan; +import org.apache.doris.nereids.trees.expressions.LessThan; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.CharLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; +import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DecimalV2Type; import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.VarcharType; @@ -212,4 +222,70 @@ public class ExpressionRewriteTest extends ExpressionRewriteTestHelper { assertRewrite(new Cast(new BigIntLiteral(1L), DecimalV2Type.createDecimalV2Type(15, 9)), new DecimalLiteral(new BigDecimal(1))); } + + @Test + public void testSimplifyComparisonPredicateRule() { + executor = new ExpressionRuleExecutor(ImmutableList.of(SimplifyComparisonPredicate.INSTANCE)); + + Expression dtv2 = new DateTimeV2Literal(1, 1, 1, 1, 1, 1); + Expression dt = new DateTimeLiteral(1, 1, 1, 1, 1, 1); + Expression dv2 = new DateV2Literal(1, 1, 1); + Expression dv2PlusOne = new DateV2Literal(1, 1, 2); + Expression d = new DateLiteral(1, 1, 1); + Expression dPlusOne = new DateLiteral(1, 1, 2); + + // DateTimeV2 -> DateTime + assertRewrite( + new GreaterThan(new Cast(dt, DateTimeV2Type.INSTANCE), dtv2), + new GreaterThan(dt, dt)); + + // DateTimeV2 -> DateV2 + assertRewrite( + new GreaterThan(new Cast(dv2, DateTimeV2Type.INSTANCE), dtv2), + new GreaterThan(dv2, dv2)); + assertRewrite( + new LessThan(new Cast(dv2, DateTimeV2Type.INSTANCE), dtv2), + new LessThan(dv2, dv2PlusOne)); + assertRewrite( + new EqualTo(new Cast(dv2, DateTimeV2Type.INSTANCE), dtv2), + new EqualTo(new Cast(dv2, DateTimeV2Type.INSTANCE), dtv2)); + + // DateTime -> DateV2 + assertRewrite( + new GreaterThan(new Cast(dv2, DateTimeV2Type.INSTANCE), dt), + new GreaterThan(dv2, dv2)); + assertRewrite( + new LessThan(new Cast(dv2, DateTimeV2Type.INSTANCE), dt), + new LessThan(dv2, dv2PlusOne)); + assertRewrite( + new EqualTo(new Cast(dv2, DateTimeV2Type.INSTANCE), dt), + new EqualTo(new Cast(dv2, DateTimeV2Type.INSTANCE), dt)); + + // DateTimeV2 -> Date + assertRewrite( + new GreaterThan(new Cast(d, DateTimeV2Type.INSTANCE), dtv2), + new GreaterThan(d, d)); + assertRewrite( + new LessThan(new Cast(d, DateTimeV2Type.INSTANCE), dtv2), + new LessThan(d, dPlusOne)); + assertRewrite( + new EqualTo(new Cast(d, DateTimeV2Type.INSTANCE), dtv2), + new EqualTo(new Cast(d, DateTimeV2Type.INSTANCE), dtv2)); + + // DateTime -> Date + assertRewrite( + new GreaterThan(new Cast(d, DateTimeV2Type.INSTANCE), dt), + new GreaterThan(d, d)); + assertRewrite( + new LessThan(new Cast(d, DateTimeV2Type.INSTANCE), dt), + new LessThan(d, dPlusOne)); + assertRewrite( + new EqualTo(new Cast(d, DateTimeV2Type.INSTANCE), dt), + new EqualTo(new Cast(d, DateTimeV2Type.INSTANCE), dt)); + + // DateV2 -> Date + assertRewrite( + new GreaterThan(new Cast(d, DateTimeV2Type.INSTANCE), dv2), + new GreaterThan(d, d)); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org