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 b53c42636e [Fix](Nereids) fold constant result is wrong on functions relative to timezone (#19863) b53c42636e is described below commit b53c42636ecb1522c64066ddd293e986df0f395e Author: mch_ucchi <41606806+sohardforan...@users.noreply.github.com> AuthorDate: Wed May 31 15:52:40 2023 +0800 [Fix](Nereids) fold constant result is wrong on functions relative to timezone (#19863) --- .../expression/rules/FoldConstantRuleOnFE.java | 4 -- .../nereids/trees/expressions/Expression.java | 5 +++ .../trees/expressions/ExpressionEvaluator.java | 2 +- .../doris/nereids/trees/expressions/Foldable.java | 24 +++++++++++ .../functions/executable/DateTimeAcquire.java | 39 ++++++++++++------ .../executable/DateTimeExtractAndTransform.java | 25 ++---------- .../expressions/functions/scalar/CurrentDate.java | 3 +- .../expressions/functions/scalar/CurrentTime.java | 3 +- .../org/apache/doris/nereids/util/DateUtils.java | 9 +++++ .../nereids_p0/datatype/test_date_acquire.groovy | 46 ++++++++++++++++++++++ 10 files changed, 121 insertions(+), 39 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java index 2451b72be5..7c60c8df79 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java @@ -328,10 +328,6 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule { @Override public Expression visitBoundFunction(BoundFunction boundFunction, ExpressionRewriteContext context) { boundFunction = rewriteChildren(boundFunction, context); - //functions, like current_date, do not have arg - if (boundFunction.getArguments().isEmpty()) { - return boundFunction; - } Optional<Expression> checkedExpr = preProcess(boundFunction); if (checkedExpr.isPresent()) { return checkedExpr.get(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java index 0d2772d768..e58795e112 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java @@ -20,6 +20,7 @@ package org.apache.doris.nereids.trees.expressions; import org.apache.doris.nereids.analyzer.Unbound; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.AbstractTreeNode; +import org.apache.doris.nereids.trees.expressions.functions.BoundFunction; import org.apache.doris.nereids.trees.expressions.functions.ExpressionTrait; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; @@ -139,6 +140,10 @@ public abstract class Expression extends AbstractTreeNode<Expression> implements */ public boolean isConstant() { if (this instanceof LeafExpression) { + if (this instanceof BoundFunction) { + BoundFunction function = ((BoundFunction) this); + return function instanceof Foldable; + } return this instanceof Literal; } else { return children().stream().allMatch(Expression::isConstant); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java index 80eb82f3a0..b6b2441c99 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ExpressionEvaluator.java @@ -137,11 +137,11 @@ public enum ExpressionEvaluator { ImmutableMultimap.Builder<String, FunctionInvoker> mapBuilder = new ImmutableMultimap.Builder<String, FunctionInvoker>(); List<Class> classes = ImmutableList.of( + DateTimeAcquire.class, DateTimeExtractAndTransform.class, ExecutableFunctions.class, DateLiteral.class, DateTimeArithmetic.class, - DateTimeAcquire.class, NumericArithmetic.class ); for (Class cls : classes) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Foldable.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Foldable.java new file mode 100644 index 0000000000..fae923dd86 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Foldable.java @@ -0,0 +1,24 @@ +// 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; + +/** + * specifically for bound function can be folded to constant. + */ +public interface Foldable { +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeAcquire.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeAcquire.java index 8670ea1858..e5dca783fd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeAcquire.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeAcquire.java @@ -23,9 +23,10 @@ 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.IntegerLiteral; +import org.apache.doris.nereids.util.DateUtils; import java.time.LocalDateTime; -import java.util.TimeZone; +import java.time.ZoneId; /** * executable functions: @@ -37,12 +38,12 @@ public class DateTimeAcquire { */ @ExecFunction(name = "now", argTypes = {}, returnType = "DATETIME") public static Expression now() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now()); + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } @ExecFunction(name = "now", argTypes = {"INT"}, returnType = "DATETIMEV2") public static Expression now(IntegerLiteral precision) { - return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(), + return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()), precision.getValue()); } @@ -51,12 +52,12 @@ public class DateTimeAcquire { */ @ExecFunction(name = "current_timestamp", argTypes = {}, returnType = "DATETIME") public static Expression currentTimestamp() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now()); + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } @ExecFunction(name = "current_timestamp", argTypes = {"INT"}, returnType = "DATETIMEV2") public static Expression currentTimestamp(IntegerLiteral precision) { - return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(), precision.getValue()); + return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()), precision.getValue()); } /** @@ -64,12 +65,12 @@ public class DateTimeAcquire { */ @ExecFunction(name = "localtime", argTypes = {}, returnType = "DATETIME") public static Expression localTime() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(TimeZone.getDefault().toZoneId())); + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } @ExecFunction(name = "localtimestamp", argTypes = {}, returnType = "DATETIME") public static Expression localTimestamp() { - return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(TimeZone.getDefault().toZoneId())); + return DateTimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } /** @@ -77,12 +78,12 @@ public class DateTimeAcquire { */ @ExecFunction(name = "curdate", argTypes = {}, returnType = "DATE") public static Expression curDate() { - return DateLiteral.fromJavaDateType(LocalDateTime.now()); + return DateLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } @ExecFunction(name = "current_date", argTypes = {}, returnType = "DATE") public static Expression currentDate() { - return DateLiteral.fromJavaDateType(LocalDateTime.now()); + return DateLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } /** @@ -90,11 +91,27 @@ public class DateTimeAcquire { */ @ExecFunction(name = "curtime", argTypes = {}, returnType = "DATETIME") public static Expression curTime() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now()); + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); } @ExecFunction(name = "current_time", argTypes = {}, returnType = "DATETIME") public static Expression currentTime() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now()); + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone())); + } + + /** + * date transformation function: unix_timestamp + */ + @ExecFunction(name = "unix_timestamp", argTypes = {}, returnType = "INT") + public static Expression unixTimestamp() { + return new IntegerLiteral((int) (System.currentTimeMillis() / 1000L)); + } + + /** + * date transformation function: utc_timestamp + */ + @ExecFunction(name = "utc_timestamp", argTypes = {}, returnType = "INT") + public static Expression utcTimestamp() { + return DateTimeLiteral.fromJavaDateType(LocalDateTime.now(ZoneId.of("UTC+0"))); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java index 66dd20d6c3..b0a61832b6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java @@ -448,20 +448,12 @@ public class DateTimeExtractAndTransform { .plusSeconds(second.getValue()) .atZone(ZoneId.of("UTC+0")) .toOffsetDateTime() - .atZoneSameInstant(ZoneId.systemDefault()); + .atZoneSameInstant(DateUtils.getTimeZone()); return dateFormat(new DateTimeLiteral(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(), dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond()), format); } - /** - * date transformation function: unix_timestamp - */ - @ExecFunction(name = "unix_timestamp", argTypes = {}, returnType = "INT") - public static Expression unixTimestamp() { - return new IntegerLiteral(getTimestamp(LocalDateTime.now())); - } - /** * date transformation function: unix_timestamp */ @@ -509,18 +501,9 @@ public class DateTimeExtractAndTransform { } return ((int) Duration.between( specialLowerBound, - dateTime - .atZone(ZoneId.systemDefault()) - .toOffsetDateTime().atZoneSameInstant(ZoneId.of("UTC+0")) - .toLocalDateTime()).getSeconds()); - } - - /** - * date transformation function: utc_timestamp - */ - @ExecFunction(name = "utc_timestamp", argTypes = {}, returnType = "INT") - public static Expression utcTimestamp() { - return DateTimeLiteral.fromJavaDateType(LocalDateTime.now()); + dateTime.atZone(DateUtils.getTimeZone()) + .toOffsetDateTime().atZoneSameInstant(ZoneId.of("UTC+0")) + .toLocalDateTime()).getSeconds()); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentDate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentDate.java index bca7ffd05c..d4bcfbee77 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentDate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentDate.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids.trees.expressions.functions.scalar; import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Foldable; import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable; import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; import org.apache.doris.nereids.trees.expressions.functions.Nondeterministic; @@ -33,7 +34,7 @@ import java.util.List; * ScalarFunction 'current_date'. This class is generated by GenerateFunction. */ public class CurrentDate extends ScalarFunction - implements LeafExpression, ExplicitlyCastableSignature, Nondeterministic, AlwaysNotNullable { + implements LeafExpression, ExplicitlyCastableSignature, Nondeterministic, AlwaysNotNullable, Foldable { public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( FunctionSignature.ret(DateType.INSTANCE).args() diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentTime.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentTime.java index 2e09c36d85..9bf190879b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentTime.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/CurrentTime.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids.trees.expressions.functions.scalar; import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Foldable; import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable; import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; import org.apache.doris.nereids.trees.expressions.functions.Nondeterministic; @@ -33,7 +34,7 @@ import java.util.List; * ScalarFunction 'current_time'. This class is generated by GenerateFunction. */ public class CurrentTime extends ScalarFunction - implements LeafExpression, ExplicitlyCastableSignature, Nondeterministic, AlwaysNotNullable { + implements LeafExpression, ExplicitlyCastableSignature, Nondeterministic, AlwaysNotNullable, Foldable { public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( FunctionSignature.ret(TimeType.INSTANCE).args() diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java index 8014bbd199..cb65a9bca6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/DateUtils.java @@ -18,8 +18,10 @@ package org.apache.doris.nereids.util; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.qe.ConnectContext; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; @@ -163,4 +165,11 @@ public class DateUtils { public static int getOrDefault(final TemporalAccessor accessor, final ChronoField field) { return accessor.isSupported(field) ? accessor.get(field) : /*default value*/ 0; } + + public static ZoneId getTimeZone() { + if (ConnectContext.get() == null || ConnectContext.get().getSessionVariable() == null) { + return ZoneId.systemDefault(); + } + return ZoneId.of(ConnectContext.get().getSessionVariable().getTimeZone()); + } } diff --git a/regression-test/suites/nereids_p0/datatype/test_date_acquire.groovy b/regression-test/suites/nereids_p0/datatype/test_date_acquire.groovy new file mode 100644 index 0000000000..f78752a33f --- /dev/null +++ b/regression-test/suites/nereids_p0/datatype/test_date_acquire.groovy @@ -0,0 +1,46 @@ +// 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_date_acquire") { + sql 'set enable_nereids_planner=true' + sql 'set enable_fallback_to_original_planner=false' + + String res = sql 'explain select now(), now(3), curdate(), current_date(), curtime(), current_time(), current_timestamp(), current_timestamp(3)' + res = res.split('VUNION')[1] + assertFalse(res.contains("()") || res.contains("(3)")) + + sql "set enable_fold_constant_by_be=true" + + test { + sql "select from_unixtime(1553152255), unix_timestamp('2007-11-30 10:30%3A19', '%Y-%m-%d %H:%i%%3A%s')" + result([['2019-03-21 15:10:55', 1196389819]]) + } + + sql "set time_zone='+00:00'" + + test { + sql "select from_unixtime(1553152255), unix_timestamp('2007-11-30 10:30%3A19', '%Y-%m-%d %H:%i%%3A%s')" + result([['2019-03-21 07:10:55', 1196418619]]) + } + + sql "set time_zone='+04:00'" + + test { + sql "select from_unixtime(1553152255), unix_timestamp('2007-11-30 10:30%3A19', '%Y-%m-%d %H:%i%%3A%s')" + result([['2019-03-21 11:10:55', 1196404219]]) + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org