This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch branch-c108335-hive-sql in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-c108335-hive-sql by this push: new da4790be099 Fix str_to_map and next_day bug and impl xpath string (#49470) da4790be099 is described below commit da4790be099154031e720697b336cd527fa002f8 Author: Socrates <suyit...@selectdb.com> AuthorDate: Tue Mar 25 17:37:49 2025 +0800 Fix str_to_map and next_day bug and impl xpath string (#49470) --- be/cmake/thirdparty.cmake | 2 + .../function_date_or_datetime_computation.cpp | 3 +- .../function_date_or_datetime_computation.h | 71 ++++---------- be/src/vec/functions/function_map.cpp | 29 +++++- be/src/vec/functions/function_string.cpp | 1 + be/src/vec/functions/function_string.h | 108 ++++++++++++--------- .../doris/catalog/BuiltinScalarFunctions.java | 2 + .../expressions/functions/scalar/NextDay.java | 9 +- .../scalar/{NextDay.java => XpathString.java} | 55 +++++------ .../expressions/visitor/ScalarFunctionVisitor.java | 5 + 10 files changed, 141 insertions(+), 144 deletions(-) diff --git a/be/cmake/thirdparty.cmake b/be/cmake/thirdparty.cmake index a165c4ab203..9f1e3aecb9d 100644 --- a/be/cmake/thirdparty.cmake +++ b/be/cmake/thirdparty.cmake @@ -175,3 +175,5 @@ endif() add_thirdparty(icuuc LIB64) add_thirdparty(icui18n LIB64) add_thirdparty(icudata LIB64) + +add_thirdparty(pugixml LIB64) diff --git a/be/src/vec/functions/function_date_or_datetime_computation.cpp b/be/src/vec/functions/function_date_or_datetime_computation.cpp index 736a6f48539..f60e32a3cdb 100644 --- a/be/src/vec/functions/function_date_or_datetime_computation.cpp +++ b/be/src/vec/functions/function_date_or_datetime_computation.cpp @@ -127,8 +127,7 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function<FunctionMinutesDiff>(); factory.register_function<FunctionSecondsDiff>(); - factory.register_function<FunctionNextDay<DateNextDayImpl>>(); - factory.register_function<FunctionNextDay<DateTimeNextDayImpl>>(); + factory.register_function<FunctionNextDay>(); factory.register_function<FunctionToYearWeekTwoArgs>(); factory.register_function<FunctionToWeekTwoArgs>(); diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h b/be/src/vec/functions/function_date_or_datetime_computation.h index 1c99aa5fc1f..d88fd0b1a66 100644 --- a/be/src/vec/functions/function_date_or_datetime_computation.h +++ b/be/src/vec/functions/function_date_or_datetime_computation.h @@ -1044,38 +1044,13 @@ public: String get_name() const override { return name; } size_t get_number_of_arguments() const override { return 2; } DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override { - return make_nullable(std::make_shared<typename FunctionImpl::ReturnType>()); + return make_nullable(std::make_shared<DataTypeDateV2>()); } Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, uint32_t result, size_t input_rows_count) const override { - // TODO: const optimize - return FunctionImpl::execute(context, block, arguments, result, input_rows_count); - } -}; - -static int day_of_week(const StringRef& weekday) { - static const std::unordered_map<std::string, int> weekday_map = { - {"SU", 1}, {"SUN", 1}, {"SUNDAY", 1}, {"MO", 2}, {"MON", 2}, {"MONDAY", 2}, - {"TU", 3}, {"TUE", 3}, {"TUESDAY", 3}, {"WE", 4}, {"WED", 4}, {"WEDNESDAY", 4}, - {"TH", 5}, {"THU", 5}, {"THURSDAY", 5}, {"FR", 6}, {"FRI", 6}, {"FRIDAY", 6}, - {"SA", 7}, {"SAT", 7}, {"SATURDAY", 7}, - }; - auto weekday_upper = weekday.to_string(); - std::transform(weekday_upper.begin(), weekday_upper.end(), weekday_upper.begin(), ::toupper); - auto it = weekday_map.find(weekday_upper); - if (it == weekday_map.end()) { - return 0; - } - return it->second; -} - -struct DateNextDayImpl { - using ReturnType = DataTypeDateV2; - static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, - uint32_t result, size_t input_rows_count) { CHECK_EQ(arguments.size(), 2); - auto res = ColumnVector<UInt32>::create(); + auto res = ColumnDateV2::create(); const auto* date_col = assert_cast<const ColumnDateV2*>(block.get_by_position(arguments[0]).column.get()); const auto* week_col = @@ -1098,35 +1073,23 @@ struct DateNextDayImpl { block.replace_by_position(result, std::move(res)); return Status::OK(); } -}; -struct DateTimeNextDayImpl { - using ReturnType = DataTypeDateTimeV2; - static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, - uint32_t result, size_t input_rows_count) { - CHECK_EQ(arguments.size(), 2); - auto res = ColumnVector<UInt64>::create(); - const auto* date_col = assert_cast<const ColumnDateTimeV2*>( - block.get_by_position(arguments[0]).column.get()); - const auto* week_col = - assert_cast<const ColumnString*>(block.get_by_position(arguments[1]).column.get()); - for (int i = 0; i < input_rows_count; ++i) { - auto date = date_col->get_element(i); - auto week = week_col->get_data_at(i); - auto week_day = day_of_week(week); - if (week_day == 0) { - return Status::InvalidArgument("Invalid weekday: {}", week); - } else { - auto dtv = binary_cast<UInt64, DateV2Value<DateTimeV2ValueType>>(date); - auto days_to_add = (week_day - dtv.day_of_week() + 7) % 7; - days_to_add = days_to_add == 0 ? 7 : days_to_add; - dtv.date_add_interval<TimeUnit::DAY>( - TimeInterval(TimeUnit::DAY, days_to_add, false)); - res->insert_value(binary_cast<DateV2Value<DateTimeV2ValueType>, UInt64>(dtv)); - } +private: + static int day_of_week(const StringRef& weekday) { + static const std::unordered_map<std::string, int> weekday_map = { + {"SU", 1}, {"SUN", 1}, {"SUNDAY", 1}, {"MO", 2}, {"MON", 2}, {"MONDAY", 2}, + {"TU", 3}, {"TUE", 3}, {"TUESDAY", 3}, {"WE", 4}, {"WED", 4}, {"WEDNESDAY", 4}, + {"TH", 5}, {"THU", 5}, {"THURSDAY", 5}, {"FR", 6}, {"FRI", 6}, {"FRIDAY", 6}, + {"SA", 7}, {"SAT", 7}, {"SATURDAY", 7}, + }; + auto weekday_upper = weekday.to_string(); + std::transform(weekday_upper.begin(), weekday_upper.end(), weekday_upper.begin(), + ::toupper); + auto it = weekday_map.find(weekday_upper); + if (it == weekday_map.end()) { + return 0; } - block.replace_by_position(result, std::move(res)); - return Status::OK(); + return it->second; } }; diff --git a/be/src/vec/functions/function_map.cpp b/be/src/vec/functions/function_map.cpp index 14233c68925..3d8b84bdf37 100644 --- a/be/src/vec/functions/function_map.cpp +++ b/be/src/vec/functions/function_map.cpp @@ -28,6 +28,7 @@ #include <utility> #include "common/status.h" +#include "util/simd/vstring_function.h" #include "vec/aggregate_functions/aggregate_function.h" #include "vec/columns/column.h" #include "vec/columns/column_array.h" @@ -326,9 +327,9 @@ public: const auto* kv_delim_column = assert_cast<const ColumnString*>(kv_delim_col.get()); for (size_t i = 0; i < input_rows_count; ++i) { - auto str = str_column->get_data_at(i); - auto pair_delim = pair_delim_column->get_data_at(i); - auto kv_delim = kv_delim_column->get_data_at(i); + const auto str = str_column->get_data_at(i).to_string_view(); + const auto pair_delim = pair_delim_column->get_data_at(i).to_string_view(); + const auto kv_delim = kv_delim_column->get_data_at(i).to_string_view(); auto kvs = split_pair_by_delim(str, pair_delim); for (const auto& kv : kvs) { @@ -356,8 +357,21 @@ public: private: static std::vector<std::string_view> split_pair_by_delim(const std::string_view& str, const std::string_view& delim) { + if (str.empty()) { + return {str}; + } + if (delim.empty()) { + std::vector<std::string_view> result; + size_t offset = 0; + while (offset < str.size()) { + auto len = get_utf8_byte_length(str[offset]); + result.push_back(str.substr(offset, len)); + offset += len; + } + return result; + } std::vector<std::string_view> result; - auto offset = 0; + size_t offset = 0; while (offset < str.size()) { auto pos = str.find(delim, offset); if (pos == std::string::npos) { @@ -372,6 +386,13 @@ private: static std::vector<std::string_view> split_kv_by_delim(const std::string_view& str, const std::string_view& delim) { + if (str.empty()) { + return {str}; + } + if (delim.empty()) { + auto len = get_utf8_byte_length(str[0]); + return {str.substr(0, len), str.substr(len)}; + } auto pos = str.find(delim); if (pos == std::string::npos) { return {str}; diff --git a/be/src/vec/functions/function_string.cpp b/be/src/vec/functions/function_string.cpp index 9b829a8c58a..1f6341058a0 100644 --- a/be/src/vec/functions/function_string.cpp +++ b/be/src/vec/functions/function_string.cpp @@ -1286,6 +1286,7 @@ void register_function_string(SimpleFunctionFactory& factory) { factory.register_function<FunctionStrcmp>(); factory.register_function<FunctionNgramSearch>(); factory.register_function<FunctionPrintf>(); + factory.register_function<FunctionXPathString>(); factory.register_alias(FunctionLeft::name, "strleft"); factory.register_alias(FunctionRight::name, "strright"); diff --git a/be/src/vec/functions/function_string.h b/be/src/vec/functions/function_string.h index ab70cc6fe26..cfd6f8e845c 100644 --- a/be/src/vec/functions/function_string.h +++ b/be/src/vec/functions/function_string.h @@ -19,6 +19,7 @@ #include <fmt/core.h> #include <fmt/printf.h> +#include <glog/logging.h> #include <sys/types.h> #include <algorithm> @@ -87,6 +88,7 @@ #include <string_view> #include "exprs/math_functions.h" +#include "pugixml.hpp" #include "udf/udf.h" #include "util/md5.h" #include "util/simd/vstring_function.h" @@ -5015,56 +5017,74 @@ public: } } block.replace_by_position(result, std::move(result_col)); + } +}; + +class FunctionXPathString : public IFunction { +public: + static constexpr auto name = "xpath_string"; + static FunctionPtr create() { return std::make_shared<FunctionXPathString>(); } + String get_name() const override { return name; } + size_t get_number_of_arguments() const override { return 2; } + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + return std::make_shared<DataTypeString>(); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + uint32_t result, size_t input_rows_count) const override { + CHECK_EQ(arguments.size(), 2); + auto col_res = ColumnString::create(); + bool col_const[2]; + ColumnPtr argument_columns[2]; + for (int i = 0; i < 2; ++i) { + col_const[i] = is_column_const(*block.get_by_position(arguments[i]).column); + } + argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>( + *block.get_by_position(arguments[0]).column) + .convert_to_full_column() + : block.get_by_position(arguments[0]).column; + default_preprocess_parameter_columns(argument_columns, col_const, {1}, block, arguments); + + const auto* col_xml = assert_cast<const ColumnString*>(argument_columns[0].get()); + const auto* col_xpath = assert_cast<const ColumnString*>(argument_columns[1].get()); + + for (size_t i = 0; i < input_rows_count; ++i) { + const auto& xml_str = col_xml->get_data_at(i); + const auto& xpath_str = col_xpath->get_data_at(i); + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_string(xml_str.to_string_view().data()); + if (!result) { + return Status::InvalidArgument("Failed to parse XML string: {}", + result.description()); + } + + pugi::xpath_node node = doc.select_node(xpath_str.to_string_view().data()); + if (!node) { + col_res->insert_default(); + continue; + } + auto text = get_text(node.node()); + col_res->insert_data(text.data(), text.size()); + } + block.get_by_position(result).column = std::move(col_res); return Status::OK(); } private: - static Status handle_format_arg(const StringRef& data, const DataTypePtr& type, - fmt::dynamic_format_arg_store<fmt::printf_context>& store) { - switch (type->get_type_id()) { - case TypeIndex::Int64: - store.push_back(get_value_from_data<int64_t>(data)); - return Status::OK(); - case TypeIndex::Int32: - store.push_back(get_value_from_data<int32_t>(data)); - return Status::OK(); - case TypeIndex::Int16: - store.push_back(get_value_from_data<int16_t>(data)); - return Status::OK(); - case TypeIndex::Int8: - store.push_back(get_value_from_data<int8_t>(data)); - return Status::OK(); - case TypeIndex::UInt64: - store.push_back(get_value_from_data<uint64_t>(data)); - return Status::OK(); - case TypeIndex::UInt32: - store.push_back(get_value_from_data<uint32_t>(data)); - return Status::OK(); - case TypeIndex::UInt16: - store.push_back(get_value_from_data<uint16_t>(data)); - return Status::OK(); - case TypeIndex::UInt8: - store.push_back(get_value_from_data<uint8_t>(data)); - return Status::OK(); - case TypeIndex::Float64: - store.push_back(get_value_from_data<double>(data)); - return Status::OK(); - case TypeIndex::Float32: - store.push_back(get_value_from_data<float>(data)); - return Status::OK(); - case TypeIndex::String: - store.push_back(data.to_string()); - return Status::OK(); - default: - return Status::InvalidArgument("Unsupported printf type: {}", type->get_name()); - } + // Build the text of the node and all its children. + static std::string get_text(const pugi::xml_node& node) { + std::string result; + build_text(node, result); + return result; } - template <typename T> - static T get_value_from_data(const StringRef& data) { - T value; - memcpy(&value, data.data, sizeof(value)); - return value; + static void build_text(const pugi::xml_node& node, std::string& builder) { + if (node.first_child().type() == pugi::node_pcdata) { + builder += node.text().as_string(); + } + for (pugi::xml_node child : node.children()) { + build_text(child, builder); + } } }; 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 2787cb0d9ca..0ce50a42631 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 @@ -481,6 +481,7 @@ 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.XpathString; 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; @@ -987,6 +988,7 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(XxHash32.class, "xxhash_32"), scalar(XxHash64.class, "xxhash_64"), scalar(Xor.class, "xor"), + scalar(XpathString.class, "xpath_string"), scalar(Year.class, "year"), scalar(YearCeil.class, "year_ceil"), scalar(YearFloor.class, "year_floor"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java index d47035e6d7e..9a04f515737 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java @@ -23,9 +23,6 @@ import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSi import org.apache.doris.nereids.trees.expressions.functions.PropagateNullableOnDateLikeV2Args; import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; -import org.apache.doris.nereids.types.DateTimeType; -import org.apache.doris.nereids.types.DateTimeV2Type; -import org.apache.doris.nereids.types.DateType; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.types.StringType; @@ -53,11 +50,7 @@ import java.util.List; public class NextDay extends ScalarFunction implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullableOnDateLikeV2Args { private static final List<FunctionSignature> SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT) - .args(DateTimeV2Type.SYSTEM_DEFAULT, StringType.INSTANCE), - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, StringType.INSTANCE), - FunctionSignature.ret(DateTimeType.INSTANCE).args(DateTimeType.INSTANCE, StringType.INSTANCE), - FunctionSignature.ret(DateType.INSTANCE).args(DateType.INSTANCE, StringType.INSTANCE)); + FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, StringType.INSTANCE)); public NextDay(Expression arg0, Expression arg1) { super("next_day", arg0, arg1); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/XpathString.java similarity index 52% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/XpathString.java index d47035e6d7e..475b899a8d6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/NextDay.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/XpathString.java @@ -20,14 +20,11 @@ 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.PropagateNullableOnDateLikeV2Args; +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.DateTimeType; -import org.apache.doris.nereids.types.DateTimeV2Type; -import org.apache.doris.nereids.types.DateType; -import org.apache.doris.nereids.types.DateV2Type; 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; @@ -35,38 +32,32 @@ import com.google.common.collect.ImmutableList; import java.util.List; /** - * ScalarFunction 'days_add'. - * next_day(expr, dayOfWeek) - * - expr: A DATE expression. - * - dayOfWeek: A STRING expression identifying a day of the week. - * Returns the first DATE that is later than expr and has the same day of the - * week as dayOfWeek. - * dayOfWeek must be one of the following (case insensitive): - * 'SU', 'SUN', 'SUNDAY' - * 'MO', 'MON', 'MONDAY' - * 'TU', 'TUE', 'TUESDAY' - * 'WE', 'WED', 'WEDNESDAY' - * 'TH', 'THU', 'THURSDAY' - * 'FR', 'FRI', 'FRIDAY' - * 'SA', 'SAT', 'SATURDAY' + * ScalarFunction 'xpath_string'. */ -public class NextDay extends ScalarFunction - implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullableOnDateLikeV2Args { - private static final List<FunctionSignature> SIGNATURES = ImmutableList.of( - FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT) - .args(DateTimeV2Type.SYSTEM_DEFAULT, StringType.INSTANCE), - FunctionSignature.ret(DateV2Type.INSTANCE).args(DateV2Type.INSTANCE, StringType.INSTANCE), - FunctionSignature.ret(DateTimeType.INSTANCE).args(DateTimeType.INSTANCE, StringType.INSTANCE), - FunctionSignature.ret(DateType.INSTANCE).args(DateType.INSTANCE, StringType.INSTANCE)); +public class XpathString extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { - public NextDay(Expression arg0, Expression arg1) { - super("next_day", arg0, arg1); + public static final List<FunctionSignature> SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT) + .args(VarcharType.SYSTEM_DEFAULT, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(StringType.INSTANCE) + .args(StringType.INSTANCE, StringType.INSTANCE) + ); + + /** + * constructor with 2 arguments. + */ + public XpathString(Expression arg0, Expression arg1) { + super("xpath_string", arg0, arg1); } + /** + * withChildren. + */ @Override - public NextDay withChildren(List<Expression> children) { + public XpathString withChildren(List<Expression> children) { Preconditions.checkArgument(children.size() == 2); - return new NextDay(children.get(0), children.get(1)); + return new XpathString(children.get(0), children.get(1)); } @Override @@ -76,6 +67,6 @@ public class NextDay extends ScalarFunction @Override public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { - return visitor.visitNextDay(this, context); + return visitor.visitXpathString(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 01c51c20c43..72bd256f93a 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 @@ -478,6 +478,7 @@ 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.XpathString; 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; @@ -2359,6 +2360,10 @@ public interface ScalarFunctionVisitor<R, C> { return visitScalarFunction(xor, context); } + default R visitXpathString(XpathString xpathString, C context) { + return visitScalarFunction(xpathString, context); + } + // struct function default R visitCreateStruct(CreateStruct createStruct, C context) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org