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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]