This is an automated email from the ASF dual-hosted git repository. lihaopeng 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 d487355903c [feature](pred) Support xor function (#33634) d487355903c is described below commit d487355903c05fad0941573591d79b733d14063f Author: Mryange <59914473+mrya...@users.noreply.github.com> AuthorDate: Sun May 5 18:44:37 2024 +0800 [feature](pred) Support xor function (#33634) --- be/src/vec/functions/functions_logical.cpp | 11 +++- be/src/vec/functions/functions_logical.h | 15 +++++ .../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 1 + .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 1 + .../doris/catalog/BuiltinScalarFunctions.java | 5 +- .../doris/nereids/parser/LogicalPlanBuilder.java | 3 + .../trees/expressions/functions/scalar/Xor.java | 66 ++++++++++++++++++++++ .../expressions/visitor/ScalarFunctionVisitor.java | 5 ++ .../data/correctness_p0/test_xor_pred.out | 15 +++++ .../suites/correctness_p0/test_xor_pred.groovy | 49 ++++++++++++++++ 10 files changed, 167 insertions(+), 4 deletions(-) diff --git a/be/src/vec/functions/functions_logical.cpp b/be/src/vec/functions/functions_logical.cpp index c0b8d62ec25..b3082b73fa0 100644 --- a/be/src/vec/functions/functions_logical.cpp +++ b/be/src/vec/functions/functions_logical.cpp @@ -20,6 +20,7 @@ #include "vec/functions/functions_logical.h" +#include <bits/ranges_algo.h> #include <glog/logging.h> #include <utility> @@ -208,9 +209,14 @@ Status FunctionAnyArityLogical<Impl, Name>::execute_impl(FunctionContext* contex args_in.push_back(block.get_by_position(arg_index).column.get()); auto& result_info = block.get_by_position(result_index); - if (result_info.type->is_nullable()) { - null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count); + if constexpr (Impl::special_implementation_for_nulls()) { + if (result_info.type->is_nullable()) { + null_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count); + } else { + basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count); + } } else { + DCHECK(std::ranges::all_of(args_in, [](const auto& arg) { return !arg->is_nullable(); })); basic_execute_impl<Impl>(std::move(args_in), result_info, input_rows_count); } return Status::OK(); @@ -272,6 +278,7 @@ void register_function_logical(SimpleFunctionFactory& instance) { instance.register_function<FunctionAnd>(); instance.register_function<FunctionOr>(); instance.register_function<FunctionNot>(); + instance.register_function<FunctionXor>(); } } // namespace doris::vectorized diff --git a/be/src/vec/functions/functions_logical.h b/be/src/vec/functions/functions_logical.h index 0c1cf54a08e..e371fa3bf8f 100644 --- a/be/src/vec/functions/functions_logical.h +++ b/be/src/vec/functions/functions_logical.h @@ -94,6 +94,14 @@ struct OrImpl { static inline constexpr bool special_implementation_for_nulls() { return true; } }; +struct XorImpl { + using ResultType = UInt8; + + static inline constexpr ResultType apply(UInt8 a, UInt8 b) { return a ^ b; } + // select null xor true , null xor false , false xor null , true xor null ; + static inline constexpr bool special_implementation_for_nulls() { return false; } +}; + template <typename A> struct NotImpl { using ResultType = UInt8; @@ -151,10 +159,17 @@ struct NameNot { static constexpr auto name = "not"; }; +struct NameXor { + static constexpr auto name = "xor"; +}; + using FunctionAnd = FunctionsLogicalDetail::FunctionAnyArityLogical<FunctionsLogicalDetail::AndImpl, NameAnd>; using FunctionOr = FunctionsLogicalDetail::FunctionAnyArityLogical<FunctionsLogicalDetail::OrImpl, NameOr>; using FunctionNot = FunctionsLogicalDetail::FunctionUnaryLogical<FunctionsLogicalDetail::NotImpl, NameNot>; + +using FunctionXor = + FunctionsLogicalDetail::FunctionAnyArityLogical<FunctionsLogicalDetail::XorImpl, NameXor>; } // namespace doris::vectorized diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 index b70d19b7e0a..74a4caf5520 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 @@ -105,6 +105,7 @@ ALTER: 'ALTER'; ANALYZE: 'ANALYZE'; ANALYZED: 'ANALYZED'; AND: 'AND'; +XOR: 'XOR'; ANTI: 'ANTI'; APPEND: 'APPEND'; ARRAY: 'ARRAY'; diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index f3f712742ed..395cdc16665 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -676,6 +676,7 @@ booleanExpression | IS_NOT_NULL_PRED LEFT_PAREN valueExpression RIGHT_PAREN #is_not_null_pred | valueExpression predicate? #predicated | left=booleanExpression operator=(AND | LOGICALAND) right=booleanExpression #logicalBinary + | left=booleanExpression operator=XOR right=booleanExpression #logicalBinary | left=booleanExpression operator=OR right=booleanExpression #logicalBinary | left=booleanExpression operator=DOUBLEPIPES right=booleanExpression #doublePipes ; diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index eb7a2c6050c..f234403739c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -433,6 +433,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.WidthBucket; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Xor; import org.apache.doris.nereids.trees.expressions.functions.scalar.XxHash32; import org.apache.doris.nereids.trees.expressions.functions.scalar.XxHash64; import org.apache.doris.nereids.trees.expressions.functions.scalar.Year; @@ -894,14 +895,14 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(WidthBucket.class, "width_bucket"), scalar(XxHash32.class, "xxhash_32"), scalar(XxHash64.class, "xxhash_64"), + scalar(Xor.class, "xor"), scalar(Year.class, "year"), scalar(YearCeil.class, "year_ceil"), scalar(YearFloor.class, "year_floor"), scalar(YearWeek.class, "yearweek"), scalar(YearsAdd.class, "years_add"), scalar(YearsDiff.class, "years_diff"), - scalar(YearsSub.class, "years_sub") - ); + scalar(YearsSub.class, "years_sub")); public static final BuiltinScalarFunctions INSTANCE = new BuiltinScalarFunctions(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 604cdde889b..ec295724f4f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -321,6 +321,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.WeekFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Xor; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsAdd; @@ -1561,6 +1562,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return new And(left, right); case DorisParser.OR: return new Or(left, right); + case DorisParser.XOR: + return new Xor(left, right); default: throw new ParseException("Unsupported logical binary type: " + ctx.operator.getText(), ctx); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Xor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Xor.java new file mode 100644 index 00000000000..8452c2269e8 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Xor.java @@ -0,0 +1,66 @@ +// 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.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.NullOrIdenticalSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.BooleanType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * Xor predicate expression. + */ +public class Xor extends ScalarFunction + implements BinaryExpression, NullOrIdenticalSignature, PropagateNullable { + public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BooleanType.INSTANCE).args(BooleanType.INSTANCE, BooleanType.INSTANCE)); + + /** + * constructor with 2 argument. + */ + public Xor(Expression arg0, Expression arg1) { + super("xor", arg0, arg1); + } + + /** + * withChildren. + */ + @Override + public Xor withChildren(List<Expression> children) { + Preconditions.checkArgument(children.size() == 2); + return new Xor(children.get(0), children.get(1)); + } + + @Override + public List<FunctionSignature> getSignatures() { + return SIGNATURES; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitXor(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java index b8d2ccfbf4f..f908691ecb4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java @@ -430,6 +430,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.WidthBucket; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Xor; import org.apache.doris.nereids.trees.expressions.functions.scalar.XxHash32; import org.apache.doris.nereids.trees.expressions.functions.scalar.XxHash64; import org.apache.doris.nereids.trees.expressions.functions.scalar.Year; @@ -2129,6 +2130,10 @@ public interface ScalarFunctionVisitor<R, C> { return visitScalarFunction(mapValues, context); } + default R visitXor(Xor xor, C context) { + return visitScalarFunction(xor, context); + } + // struct function default R visitCreateStruct(CreateStruct createStruct, C context) { diff --git a/regression-test/data/correctness_p0/test_xor_pred.out b/regression-test/data/correctness_p0/test_xor_pred.out new file mode 100644 index 00000000000..2f507eb5d28 --- /dev/null +++ b/regression-test/data/correctness_p0/test_xor_pred.out @@ -0,0 +1,15 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql_const -- +false true true false \N \N \N \N \N + +-- !sql_select -- +\N \N \N \N +\N false \N \N +\N true \N \N +false \N \N \N +false false false true +false true true false +true \N \N \N +true false true false +true true false true + diff --git a/regression-test/suites/correctness_p0/test_xor_pred.groovy b/regression-test/suites/correctness_p0/test_xor_pred.groovy new file mode 100644 index 00000000000..df165bd2134 --- /dev/null +++ b/regression-test/suites/correctness_p0/test_xor_pred.groovy @@ -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. + +suite("test_xor_pred") { + sql """ drop table if exists dbxor; """ + sql """ + CREATE TABLE IF NOT EXISTS dbxor ( + `k1` boolean NULL COMMENT "", + `k2` boolean NULL COMMENT "" + ) ENGINE=OLAP + DUPLICATE KEY(`k1`) + DISTRIBUTED BY HASH(`k1`) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1", + "storage_format" = "V2" + ); + """ + sql """set enable_nereids_planner=true,enable_fold_constant_by_be = false; """ + qt_sql_const """ + select true xor true,false xor true,true xor false,false xor false,null xor false,null xor true,true xor null ,false xor null,null xor null; + """ + sql """ + insert into dbxor values(true,true),(true,false),(false,true),(false,false),(true,null),(false,null),(null,true),(null,false),(null,null); + """ + qt_sql_select """ + select k1,k2 , k1 xor k2, not (k1 xor k2) from dbxor order by k1,k2; + """ + + test { + sql """ + select 1 xor 0; + """ + exception("Can not find the compatibility function signature: xor(TINYINT, TINYINT)") + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org