This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
commit 31984bb4f0175c2cfc9a10685cbe3db306c03749 Author: Uniqueyou <[email protected]> AuthorDate: Wed Apr 10 10:05:58 2024 +0800 [feature](function) support quote string function #33055 --- be/src/vec/functions/function_string.cpp | 28 +++++++++ be/test/vec/function/function_string_test.cpp | 12 ++++ .../sql-functions/string-functions/quote.md | 47 +++++++++++++++ .../sql-functions/string-functions/quote.md | 47 +++++++++++++++ .../doris/catalog/BuiltinScalarFunctions.java | 2 + .../trees/expressions/functions/scalar/Quote.java | 69 ++++++++++++++++++++++ .../expressions/visitor/ScalarFunctionVisitor.java | 5 ++ gensrc/script/doris_builtins_functions.py | 2 + 8 files changed, 212 insertions(+) diff --git a/be/src/vec/functions/function_string.cpp b/be/src/vec/functions/function_string.cpp index 8aee837ac63..69f8699b5c8 100644 --- a/be/src/vec/functions/function_string.cpp +++ b/be/src/vec/functions/function_string.cpp @@ -21,6 +21,7 @@ #include <math.h> #include <re2/stringpiece.h> +#include <cstddef> #include <string_view> #include "common/status.h" @@ -57,6 +58,30 @@ struct StringASCII { } }; +struct NameQuote { + static constexpr auto name = "quote"; +}; + +struct NameQuoteImpl { + static Status vector(const ColumnString::Chars& data, const ColumnString::Offsets& offsets, + ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets) { + size_t offset_size = offsets.size(); + size_t pos = 0; + res_offsets.resize(offset_size); + res_data.resize(data.size() + offset_size * 2); + for (int i = 0; i < offset_size; i++) { + const unsigned char* raw_str = &data[offsets[i - 1]]; + ColumnString::Offset size = offsets[i] - offsets[i - 1]; + res_data[pos] = '\''; + std::memcpy(res_data.data() + pos + 1, raw_str, size); + res_data[pos + size + 1] = '\''; + pos += size + 2; + res_offsets[i] = pos; + } + return Status::OK(); + } +}; + struct NameStringLenght { static constexpr auto name = "length"; }; @@ -1052,6 +1077,8 @@ using FunctionStringLocate = using FunctionStringFindInSet = FunctionBinaryToType<DataTypeString, DataTypeString, StringFindInSetImpl, NameFindInSet>; +using FunctionQuote = FunctionStringToString<NameQuoteImpl, NameQuote>; + using FunctionToLower = FunctionStringToString<TransferImpl<NameToLower>, NameToLower>; using FunctionToUpper = FunctionStringToString<TransferImpl<NameToUpper>, NameToUpper>; @@ -1082,6 +1109,7 @@ void register_function_string(SimpleFunctionFactory& factory) { factory.register_function<FunctionStringFindInSet>(); factory.register_function<FunctionStringLocate>(); factory.register_function<FunctionStringLocatePos>(); + factory.register_function<FunctionQuote>(); factory.register_function<FunctionReverseCommon>(); factory.register_function<FunctionUnHex>(); factory.register_function<FunctionToLower>(); diff --git a/be/test/vec/function/function_string_test.cpp b/be/test/vec/function/function_string_test.cpp index d8d1a57b8eb..2c0fecbb300 100644 --- a/be/test/vec/function/function_string_test.cpp +++ b/be/test/vec/function/function_string_test.cpp @@ -215,6 +215,18 @@ TEST(function_string_test, function_string_length_test) { static_cast<void>(check_function<DataTypeInt32, true>(func_name, input_types, data_set)); } +TEST(function_string_test, function_string_quote_test) { + std::string func_name = "quote"; + InputTypeSet input_types = {TypeIndex::String}; + DataSet data_set = {{{std::string("hello")}, std::string(R"('hello')")}, + {{std::string("hello\t\n\nworld")}, std::string("'hello\t\n\nworld'")}, + {{std::string("HELLO,!^%")}, std::string("'HELLO,!^%'")}, + {{std::string("MYtestStr\\t\\n")}, std::string("'MYtestStr\\t\\n'")}, + {{std::string("")}, std::string("''")}, + {{Null()}, Null()}}; + static_cast<void>(check_function<DataTypeString, true>(func_name, input_types, data_set)); +} + TEST(function_string_test, function_append_trailing_char_if_absent_test) { std::string func_name = "append_trailing_char_if_absent"; diff --git a/docs/en/docs/sql-manual/sql-functions/string-functions/quote.md b/docs/en/docs/sql-manual/sql-functions/string-functions/quote.md new file mode 100644 index 00000000000..06246341bd5 --- /dev/null +++ b/docs/en/docs/sql-manual/sql-functions/string-functions/quote.md @@ -0,0 +1,47 @@ +--- +{ + "title": "QUOTE", + "language": "en" +} +--- + +<!-- +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. +--> + +## quote +### description +#### Syntax + +`VARCHAR quote(VARCHAR str)` + + +Output all the strings in the argument as is and wrap them with '' + +### example + +``` +mysql> select quote('hello world!\\t'); ++-------------------------+ +| quote('hello world!\t') | ++-------------------------+ +| 'hello world!\t' | ++-------------------------+ +``` +### keywords + QUOTE diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/quote.md b/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/quote.md new file mode 100644 index 00000000000..ecc0c7d40d4 --- /dev/null +++ b/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/quote.md @@ -0,0 +1,47 @@ +--- +{ + "title": "QUOTE", + "language": "zh-CN" +} +--- + +<!-- +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. +--> + +## quote +### description +#### Syntax + +`VARCHAR quote(VARCHAR str)` + + +将参数中所有的字符串按原样输出,并用''套起来 + +### example + +``` +mysql> select quote('hello world!\\t'); ++-------------------------+ +| quote('hello world!\t') | ++-------------------------+ +| 'hello world!\t' | ++-------------------------+ +``` +### keywords + QUOTE 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 d28cb751eaa..d27b0f3a311 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 @@ -317,6 +317,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Protocol; import org.apache.doris.nereids.trees.expressions.functions.scalar.QuantilePercent; import org.apache.doris.nereids.trees.expressions.functions.scalar.QuantileStateEmpty; import org.apache.doris.nereids.trees.expressions.functions.scalar.Quarter; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Quote; import org.apache.doris.nereids.trees.expressions.functions.scalar.Radians; import org.apache.doris.nereids.trees.expressions.functions.scalar.Random; import org.apache.doris.nereids.trees.expressions.functions.scalar.RandomBytes; @@ -868,6 +869,7 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(Unhex.class, "unhex"), scalar(UnixTimestamp.class, "unix_timestamp"), scalar(Upper.class, "ucase", "upper"), + scalar(Quote.class, "quote"), scalar(UrlDecode.class, "url_decode"), scalar(User.class, "user"), scalar(UtcTimestamp.class, "utc_timestamp"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quote.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quote.java new file mode 100644 index 00000000000..25f97e6e395 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Quote.java @@ -0,0 +1,69 @@ +// 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.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'quote'. This class is not generated by GenerateFunction. + */ +public class Quote extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(StringType.INSTANCE).args(StringType.INSTANCE)); + + /** + * constructor with 1 argument. + */ + public Quote(Expression arg) { + super("quote", arg); + } + + /** + * withChildren. + */ + @Override + public Quote withChildren(List<Expression> children) { + Preconditions.checkArgument(children.size() == 1); + return new Quote(children.get(0)); + } + + @Override + public List<FunctionSignature> getSignatures() { + return SIGNATURES; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitQuote(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 83a4a2aa027..baa801f7786 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 @@ -316,6 +316,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Protocol; import org.apache.doris.nereids.trees.expressions.functions.scalar.QuantilePercent; import org.apache.doris.nereids.trees.expressions.functions.scalar.QuantileStateEmpty; import org.apache.doris.nereids.trees.expressions.functions.scalar.Quarter; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Quote; import org.apache.doris.nereids.trees.expressions.functions.scalar.Radians; import org.apache.doris.nereids.trees.expressions.functions.scalar.Random; import org.apache.doris.nereids.trees.expressions.functions.scalar.RandomBytes; @@ -1987,6 +1988,10 @@ public interface ScalarFunctionVisitor<R, C> { return visitScalarFunction(upper, context); } + default R visitQuote(Quote quote, C context) { + return visitScalarFunction(quote, context); + } + default R visitUser(User user, C context) { return visitScalarFunction(user, context); } diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 3d87ab86fd2..0e7615829d9 100644 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -1576,6 +1576,7 @@ visible_functions = { [['char_length', 'character_length'], 'INT', ['VARCHAR'], ''], [['lower', 'lcase'], 'VARCHAR', ['VARCHAR'], ''], [['upper', 'ucase'], 'VARCHAR', ['VARCHAR'], ''], + [['quote'], 'VARCHAR', ['VARCHAR'], ''], [['initcap'], 'VARCHAR', ['VARCHAR'], ''], [['trim'], 'VARCHAR', ['VARCHAR','VARCHAR'], ''], [['trim'], 'VARCHAR', ['VARCHAR'], ''], @@ -1638,6 +1639,7 @@ visible_functions = { [['char_length', 'character_length'], 'INT', ['STRING'], ''], [['lower', 'lcase'], 'STRING', ['STRING'], ''], [['upper', 'ucase'], 'STRING', ['STRING'], ''], + [['quote'], 'STRING', ['STRING'], ''], [['trim'], 'STRING', ['STRING'], ''], [['trim'], 'STRING', ['STRING','STRING'], ''], [['ltrim'], 'STRING', ['STRING'], ''], --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
