From 34dd67f804c50e5e5bf5491eb43192d4068d2b7a Mon Sep 17 00:00:00 2001 From: minghong Date: Sat, 3 Sep 2022 12:04:51 +0800 Subject: [PATCH] [feature](nereids) add weekOfYear to support ssb-flat benchmark (#12207) support function WeekOfYear In current implementation, WeekOfYear can be used in where clause, but not in select clause. --- .../doris/analysis/FunctionCallExpr.java | 3 +- .../nereids/rules/analysis/BindFunction.java | 7 ++ .../expressions/functions/WeekOfYear.java | 68 +++++++++++++++++++ .../doris/nereids/util/TypeCoercionUtils.java | 25 ++++--- .../data/datatype_p0/date/test_weekofyear.out | 4 ++ .../datatype_p0/date/test_weekofyear.groovy | 37 ++++++++++ 6 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/WeekOfYear.java create mode 100644 regression-test/data/datatype_p0/date/test_weekofyear.out create mode 100644 regression-test/suites/datatype_p0/date/test_weekofyear.groovy diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java index 1f2af19394..8d4db06794 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java @@ -1445,7 +1445,8 @@ public class FunctionCallExpr extends Expr { } else if (fnName.getFunction().equalsIgnoreCase("year") || fnName.getFunction().equalsIgnoreCase("max") || fnName.getFunction().equalsIgnoreCase("min") - || fnName.getFunction().equalsIgnoreCase("avg")) { + || fnName.getFunction().equalsIgnoreCase("avg") + || fnName.getFunction().equalsIgnoreCase("weekOfYear")) { Type childType = getChild(0).type; fn = getBuiltinFunction(fnName.getFunction(), new Type[]{childType}, Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java index df2174caf3..9c24d0b1ec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java @@ -30,6 +30,7 @@ import org.apache.doris.nereids.trees.expressions.functions.Max; import org.apache.doris.nereids.trees.expressions.functions.Min; import org.apache.doris.nereids.trees.expressions.functions.Substring; import org.apache.doris.nereids.trees.expressions.functions.Sum; +import org.apache.doris.nereids.trees.expressions.functions.WeekOfYear; import org.apache.doris.nereids.trees.expressions.functions.Year; import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import org.apache.doris.nereids.trees.plans.logical.LogicalFilter; @@ -138,6 +139,12 @@ public class BindFunction implements AnalysisRuleFactory { return unboundFunction; } return new Year(unboundFunction.getArguments().get(0)); + } else if (name.equalsIgnoreCase("WeekOfYear")) { + List arguments = unboundFunction.getArguments(); + if (arguments.size() != 1) { + return unboundFunction; + } + return new WeekOfYear(unboundFunction.getArguments().get(0)); } return unboundFunction; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/WeekOfYear.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/WeekOfYear.java new file mode 100644 index 0000000000..6f4dc44548 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/WeekOfYear.java @@ -0,0 +1,68 @@ +// 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.functions; + +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.typecoercion.ImplicitCastInputTypes; +import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.DateTimeType; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.coercion.AbstractDataType; +import org.apache.doris.nereids.types.coercion.TypeCollection; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * weekOfYear function + */ +public class WeekOfYear extends BoundFunction implements UnaryExpression, ImplicitCastInputTypes { + + private static final List EXPECTED_INPUT_TYPES = ImmutableList.of( + new TypeCollection(DateTimeType.INSTANCE) + ); + + public WeekOfYear(Expression child) { + super("weekofyear", child); + } + + @Override + public DataType getDataType() { + return IntegerType.INSTANCE; + } + + @Override + public boolean nullable() { + return child().nullable(); + } + + @Override + public WeekOfYear withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new WeekOfYear(children.get(0)); + } + + @Override + public List expectedInputTypes() { + return EXPECTED_INPUT_TYPES; + } + +} 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 e372e6c3b3..5c776b00ac 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 @@ -23,6 +23,7 @@ import org.apache.doris.nereids.trees.expressions.Expression; 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.DecimalType; import org.apache.doris.nereids.types.DoubleType; import org.apache.doris.nereids.types.FloatType; @@ -102,20 +103,28 @@ public class TypeCoercionUtils { if (input instanceof NullType) { // Cast null type (usually from null literals) into target types returnType = expected.defaultConcreteType(); - } else if (input instanceof NumericType && expected instanceof DecimalType) { - // If input is a numeric type but not decimal, and we expect a decimal type, - // cast the input to decimal. - returnType = DecimalType.forType(input); - } else if (input instanceof NumericType && expected instanceof NumericType) { - // For any other numeric types, implicitly cast to each other, e.g. bigint -> int, int -> bigint - returnType = expected.defaultConcreteType(); + } else if (input instanceof NumericType) { + if (expected instanceof DecimalType) { + // If input is a numeric type but not decimal, and we expect a decimal type, + // cast the input to decimal. + returnType = DecimalType.forType(input); + } else if (expected instanceof DateTimeType) { + returnType = DateTimeType.INSTANCE; + } else if (expected instanceof NumericType) { + // For any other numeric types, implicitly cast to each other, e.g. bigint -> int, int -> bigint + returnType = expected.defaultConcreteType(); + } } else if (input instanceof CharacterType) { if (expected instanceof DecimalType) { returnType = DecimalType.SYSTEM_DEFAULT; } else if (expected instanceof NumericType) { returnType = expected.defaultConcreteType(); + } else if (expected instanceof DateTimeType) { + returnType = DateTimeType.INSTANCE; } - } else if (input instanceof PrimitiveType + } + + if (returnType == null && input instanceof PrimitiveType && expected instanceof CharacterType) { returnType = StringType.INSTANCE; } diff --git a/regression-test/data/datatype_p0/date/test_weekofyear.out b/regression-test/data/datatype_p0/date/test_weekofyear.out new file mode 100644 index 0000000000..619d323de0 --- /dev/null +++ b/regression-test/data/datatype_p0/date/test_weekofyear.out @@ -0,0 +1,4 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !weekOfYear -- +20000101 2000-01-01 + diff --git a/regression-test/suites/datatype_p0/date/test_weekofyear.groovy b/regression-test/suites/datatype_p0/date/test_weekofyear.groovy new file mode 100644 index 0000000000..8f45396561 --- /dev/null +++ b/regression-test/suites/datatype_p0/date/test_weekofyear.groovy @@ -0,0 +1,37 @@ + +// 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_weekofyear") { + sql "DROP TABLE IF EXISTS woy" + + sql """ + CREATE TABLE IF NOT EXISTS woy ( + c0 int, + c1 varchar(10) + ) + DUPLICATE KEY(c0) + DISTRIBUTED BY HASH(c0) BUCKETS 1 properties("replication_num" = "1") + """ + sql "insert into woy values(20000101, '2000-01-01')" + sql "insert into woy values(20000110, '2000-01-10')" + + + sql "set enable_nereids_planner=true" + sql "set enable_vectorized_engine=true" + qt_weekOfYear "select * from woy where weekofyear(c0)=52 and weekofyear(c1)=52" +}