github-actions[bot] commented on code in PR #24554: URL: https://github.com/apache/doris/pull/24554#discussion_r1349516460
########## be/src/vec/data_types/data_type_object.h: ########## @@ -50,34 +51,40 @@ bool is_nullable; public: - DataTypeObject(const String& schema_format_, bool is_nullable_); + DataTypeObject(const String& schema_format_ = "json", bool is_nullable_ = true); const char* get_family_name() const override { return "Variant"; } TypeIndex get_type_id() const override { return TypeIndex::VARIANT; } PrimitiveType get_type_as_primitive_type() const override { return TYPE_VARIANT; } TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::VARIANT; } + doris::FieldType get_type_as_field_type() const override { + return doris::FieldType::OLAP_FIELD_TYPE_VARIANT; + } MutableColumnPtr create_column() const override { return ColumnObject::create(is_nullable); } bool is_object() const override { return true; } bool equals(const IDataType& rhs) const override; bool hasNullableSubcolumns() const { return is_nullable; } bool get_is_parametric() const override { return true; } - bool can_be_inside_nullable() const override { return true; } bool have_subtypes() const override { return true; }; + bool can_be_inside_nullable() const override { return false; } int64_t get_uncompressed_serialized_bytes(const IColumn& column, int be_exec_version) const override; - std::string to_string(const IColumn& column, size_t row_num) const override { - const auto& column_object = assert_cast<const ColumnObject&>(column); - return "Variant: " + column_object.get_keys_str(); - } + std::string to_string(const IColumn& column, size_t row_num) const override; Review Comment: warning: function 'to_string' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] std::string to_string(const IColumn& column, size_t row_num) const override; ``` ########## be/src/vec/data_types/data_type_quantilestate.h: ########## @@ -57,6 +57,9 @@ class DataTypeQuantileState : public IDataType { TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::QUANTILE_STATE; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/data_types/data_type_time_v2.h: ########## @@ -62,6 +62,9 @@ class DataTypeDateV2 final : public DataTypeNumberBase<UInt32> { TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::DATEV2; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/data_types/data_type_string.h: ########## @@ -60,6 +60,9 @@ class DataTypeString : public IDataType { TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::STRING; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/olap/olap_data_convertor.h: ########## @@ -480,6 +483,22 @@ class OlapBlockDataConvertor { UInt64 _base_offset; }; //OlapColumnDataConvertorMap + class OlapColumnDataConvertorVariant : public OlapColumnDataConvertorBase { + public: + OlapColumnDataConvertorVariant() Review Comment: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default] be/src/vec/olap/olap_data_convertor.h:488: ```diff - : _root_data_convertor(std::make_unique<OlapColumnDataConvertorVarChar>(true)) {} + : _root_data_convertor(std::make_unique<OlapColumnDataConvertorVarChar>(true)) = default; ``` ########## be/src/vec/data_types/data_type_object.h: ########## @@ -50,34 +51,40 @@ bool is_nullable; public: - DataTypeObject(const String& schema_format_, bool is_nullable_); + DataTypeObject(const String& schema_format_ = "json", bool is_nullable_ = true); const char* get_family_name() const override { return "Variant"; } TypeIndex get_type_id() const override { return TypeIndex::VARIANT; } PrimitiveType get_type_as_primitive_type() const override { return TYPE_VARIANT; } TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::VARIANT; } + doris::FieldType get_type_as_field_type() const override { + return doris::FieldType::OLAP_FIELD_TYPE_VARIANT; + } MutableColumnPtr create_column() const override { return ColumnObject::create(is_nullable); } bool is_object() const override { return true; } bool equals(const IDataType& rhs) const override; bool hasNullableSubcolumns() const { return is_nullable; } bool get_is_parametric() const override { return true; } - bool can_be_inside_nullable() const override { return true; } bool have_subtypes() const override { return true; }; + bool can_be_inside_nullable() const override { return false; } Review Comment: warning: function 'can_be_inside_nullable' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] bool can_be_inside_nullable() const override { return false; } ``` ########## be/src/vec/functions/function_cast.h: ########## @@ -1845,12 +1948,119 @@ case TypeIndex::Float64: return &ConvertImplNumberToJsonb<ColumnFloat64>::execute; case TypeIndex::String: - return &ConvertImplGenericFromString::execute; + if (string_as_jsonb_string) { + // We convert column string to jsonb type just add a string jsonb field to dst column instead of parse + // each line in original string column. + return &ConvertImplStringToJsonbAsJsonbString::execute; + } else { + return &ConvertImplGenericFromString::execute; + } default: return &ConvertImplGenericToJsonb::execute; } } + struct ConvertImplGenericFromVariant { + static Status execute(const FunctionCast* fn, FunctionContext* context, Block& block, + const ColumnNumbers& arguments, const size_t result, + size_t input_rows_count) { + auto& data_type_to = block.get_by_position(result).type; + const auto& col_with_type_and_name = block.get_by_position(arguments[0]); + auto& col_from = col_with_type_and_name.column; + auto& variant = assert_cast<const ColumnObject&>(*col_from); + ColumnPtr col_to = data_type_to->create_column(); + if (!variant.is_finalized()) { + variant.assume_mutable()->finalize(); + } + + if (variant.is_scalar_variant()) { + ColumnPtr nested = variant.get_root(); + auto nested_from_type = variant.get_root_type(); + DCHECK(nested_from_type->is_nullable()); + DCHECK(!data_type_to->is_nullable()); + auto new_context = context->clone(); + new_context->set_jsonb_string_as_string(true); + // dst type nullable has been removed, so we should remove the inner nullable of root column + auto wrapper = fn->prepare_impl( + new_context.get(), remove_nullable(nested_from_type), data_type_to, true); + Block tmp_block {{remove_nullable(nested), remove_nullable(nested_from_type), ""}}; + tmp_block.insert({nullptr, data_type_to, ""}); + /// Perform the requested conversion. + Status st = wrapper(new_context.get(), tmp_block, {0}, 1, input_rows_count); + if (!st.ok()) { + // Fill with default values, which is null + col_to->assume_mutable()->insert_many_defaults(input_rows_count); + col_to = make_nullable(col_to, true); + } else { + col_to = tmp_block.get_by_position(1).column; + // Note: here we should return the nullable result column + col_to = wrap_in_nullable( + col_to, + Block({{nested, nested_from_type, ""}, {col_to, data_type_to, ""}}), + {0}, 1, input_rows_count); + } + } else { + // Could not cast to any other types when it hierarchical like '{"a" : 1}' + if (!data_type_to->is_nullable() && !WhichDataType(data_type_to).is_string()) { + // TODO we should convert as many as possible here, for examle + // this variant column's root is a number column, to convert to number column + // is also acceptable + // return Status::InvalidArgument(fmt::format("Could not cast from variant to {}", + // data_type_to->get_name())); + col_to->assume_mutable()->insert_many_defaults(input_rows_count); + col_to = make_nullable(col_to, true); + } else if (WhichDataType(data_type_to).is_string()) { + return ConvertImplGenericToString::execute2(context, block, arguments, result, + input_rows_count); + } else { + assert_cast<ColumnNullable&>(*col_to->assume_mutable()) + .insert_many_defaults(input_rows_count); + } + } + if (col_to->size() != input_rows_count) { + return Status::InternalError("Unmatched row count {}, expected {}", col_to->size(), + input_rows_count); + } + + block.replace_by_position(result, std::move(col_to)); + return Status::OK(); + } + }; + + struct ConvertImplGenericToVariant { + static Status execute(FunctionContext* context, Block& block, + const ColumnNumbers& arguments, const size_t result, + size_t input_rows_count) { + // auto& data_type_to = block.get_by_position(result).type; + const auto& col_with_type_and_name = block.get_by_position(arguments[0]); + auto& from_type = col_with_type_and_name.type; + auto& col_from = col_with_type_and_name.column; + + // set variant root column/type to from column/type + auto variant = ColumnObject::create(true /*always nullable*/); + variant->create_root(from_type, col_from->assume_mutable()); + + block.replace_by_position(result, std::move(variant)); + return Status::OK(); + } + }; + + // create cresponding variant value to wrap from_type + WrapperType create_variant_wrapper(const DataTypePtr& from_type, + const DataTypeObject& to_type) const { + return &ConvertImplGenericToVariant::execute; + } + + // create cresponding type convert from variant + WrapperType create_variant_wrapper(const DataTypeObject& from_type, Review Comment: warning: function 'create_variant_wrapper' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] WrapperType create_variant_wrapper(const DataTypeObject& from_type, ``` ########## be/src/vec/olap/olap_data_convertor.h: ########## @@ -480,6 +483,22 @@ UInt64 _base_offset; }; //OlapColumnDataConvertorMap + class OlapColumnDataConvertorVariant : public OlapColumnDataConvertorBase { + public: + OlapColumnDataConvertorVariant() + : _root_data_convertor(std::make_unique<OlapColumnDataConvertorVarChar>(true)) {} + void set_source_column(const ColumnWithTypeAndName& typed_column, size_t row_pos, + size_t num_rows) override; + Status convert_to_olap() override; + + const void* get_data() const override; + const void* get_data_at(size_t offset) const override; Review Comment: warning: function 'get_data_at' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] const void* get_data_at(size_t offset) const override; ``` ########## be/src/vec/data_types/data_type_object.h: ########## @@ -50,34 +51,40 @@ class DataTypeObject : public IDataType { bool is_nullable; public: - DataTypeObject(const String& schema_format_, bool is_nullable_); + DataTypeObject(const String& schema_format_ = "json", bool is_nullable_ = true); const char* get_family_name() const override { return "Variant"; } TypeIndex get_type_id() const override { return TypeIndex::VARIANT; } PrimitiveType get_type_as_primitive_type() const override { return TYPE_VARIANT; } TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::VARIANT; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/data_types/data_type_object.h: ########## @@ -50,34 +51,40 @@ bool is_nullable; public: - DataTypeObject(const String& schema_format_, bool is_nullable_); + DataTypeObject(const String& schema_format_ = "json", bool is_nullable_ = true); const char* get_family_name() const override { return "Variant"; } TypeIndex get_type_id() const override { return TypeIndex::VARIANT; } PrimitiveType get_type_as_primitive_type() const override { return TYPE_VARIANT; } TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::VARIANT; } + doris::FieldType get_type_as_field_type() const override { + return doris::FieldType::OLAP_FIELD_TYPE_VARIANT; + } MutableColumnPtr create_column() const override { return ColumnObject::create(is_nullable); } bool is_object() const override { return true; } bool equals(const IDataType& rhs) const override; bool hasNullableSubcolumns() const { return is_nullable; } bool get_is_parametric() const override { return true; } - bool can_be_inside_nullable() const override { return true; } bool have_subtypes() const override { return true; }; + bool can_be_inside_nullable() const override { return false; } int64_t get_uncompressed_serialized_bytes(const IColumn& column, int be_exec_version) const override; - std::string to_string(const IColumn& column, size_t row_num) const override { - const auto& column_object = assert_cast<const ColumnObject&>(column); - return "Variant: " + column_object.get_keys_str(); - } + std::string to_string(const IColumn& column, size_t row_num) const override; + void to_string(const IColumn& column, size_t row_num, BufferWritable& ostr) const override; char* serialize(const IColumn& column, char* buf, int be_exec_version) const override; const char* deserialize(const char* buf, IColumn* column, int be_exec_version) const override; - [[noreturn]] Field get_default() const override { - LOG(FATAL) << "Method getDefault() is not implemented for data type " << get_name(); - } + Field get_default() const override { return VariantMap(); } - [[noreturn]] Field get_field(const TExprNode& node) const override { - LOG(FATAL) << "Unimplemented get_field for object"; + Field get_field(const TExprNode& node) const override { Review Comment: warning: function 'get_field' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] Field get_field(const TExprNode& node) const override { ``` ########## be/src/vec/data_types/data_type_time_v2.h: ########## @@ -114,6 +117,9 @@ TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::DATETIMEV2; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/functions/function_cast.h: ########## @@ -22,11 +22,13 @@ #include <cctz/time_zone.h> Review Comment: warning: 'cctz/time_zone.h' file not found [clang-diagnostic-error] ```cpp #include <cctz/time_zone.h> ^ ``` ########## be/src/vec/data_types/data_type_object.h: ########## @@ -50,34 +51,40 @@ bool is_nullable; public: - DataTypeObject(const String& schema_format_, bool is_nullable_); + DataTypeObject(const String& schema_format_ = "json", bool is_nullable_ = true); const char* get_family_name() const override { return "Variant"; } TypeIndex get_type_id() const override { return TypeIndex::VARIANT; } PrimitiveType get_type_as_primitive_type() const override { return TYPE_VARIANT; } TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::VARIANT; } + doris::FieldType get_type_as_field_type() const override { + return doris::FieldType::OLAP_FIELD_TYPE_VARIANT; + } MutableColumnPtr create_column() const override { return ColumnObject::create(is_nullable); } bool is_object() const override { return true; } bool equals(const IDataType& rhs) const override; bool hasNullableSubcolumns() const { return is_nullable; } bool get_is_parametric() const override { return true; } - bool can_be_inside_nullable() const override { return true; } bool have_subtypes() const override { return true; }; + bool can_be_inside_nullable() const override { return false; } int64_t get_uncompressed_serialized_bytes(const IColumn& column, int be_exec_version) const override; - std::string to_string(const IColumn& column, size_t row_num) const override { - const auto& column_object = assert_cast<const ColumnObject&>(column); - return "Variant: " + column_object.get_keys_str(); - } + std::string to_string(const IColumn& column, size_t row_num) const override; + void to_string(const IColumn& column, size_t row_num, BufferWritable& ostr) const override; char* serialize(const IColumn& column, char* buf, int be_exec_version) const override; const char* deserialize(const char* buf, IColumn* column, int be_exec_version) const override; - [[noreturn]] Field get_default() const override { - LOG(FATAL) << "Method getDefault() is not implemented for data type " << get_name(); - } + Field get_default() const override { return VariantMap(); } Review Comment: warning: function 'get_default' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] Field get_default() const override { return VariantMap(); } ``` ########## be/src/vec/data_types/data_type_time.h: ########## @@ -57,6 +57,9 @@ class DataTypeTime final : public DataTypeNumberBase<Float64> { TPrimitiveType::type get_type_as_tprimitive_type() const override { return TPrimitiveType::TIME; } + doris::FieldType get_type_as_field_type() const override { Review Comment: warning: function 'get_type_as_field_type' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] doris::FieldType get_type_as_field_type() const override { ``` ########## be/src/vec/data_types/serde/data_type_serde.h: ########## @@ -17,6 +17,7 @@ #pragma once +#include <rapidjson/document.h> Review Comment: warning: 'rapidjson/document.h' file not found [clang-diagnostic-error] ```cpp #include <rapidjson/document.h> ^ ``` ########## be/src/vec/functions/function_cast.h: ########## @@ -1796,13 +1899,8 @@ } // check jsonb value type and get to_type value - WrapperType create_jsonb_wrapper(const DataTypeJsonb& from_type, - const DataTypePtr& to_type) const { - // Conversion from String through parsing. - if (check_and_get_data_type<DataTypeString>(to_type.get())) { - return &ConvertImplGenericToString::execute2; - } - + WrapperType create_jsonb_wrapper(const DataTypeJsonb& from_type, const DataTypePtr& to_type, Review Comment: warning: function 'create_jsonb_wrapper' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] WrapperType create_jsonb_wrapper(const DataTypeJsonb& from_type, const DataTypePtr& to_type, ``` ########## be/src/vec/functions/function_cast.h: ########## @@ -1818,17 +1916,22 @@ return &ConvertImplFromJsonb<TypeIndex::Int128, ColumnInt128>::execute; case TypeIndex::Float64: return &ConvertImplFromJsonb<TypeIndex::Float64, ColumnFloat64>::execute; + case TypeIndex::String: + if (!jsonb_string_as_string) { + // Conversion from String through parsing. + return &ConvertImplGenericToString::execute2; + } else { + return ConvertImplGenericFromJsonb::execute; + } default: - return create_unsupport_wrapper(from_type.get_name(), to_type->get_name()); + return ConvertImplGenericFromJsonb::execute; } - - return nullptr; } // create cresponding jsonb value with type to_type // use jsonb writer to create jsonb value - WrapperType create_jsonb_wrapper(const DataTypePtr& from_type, - const DataTypeJsonb& to_type) const { + WrapperType create_jsonb_wrapper(const DataTypePtr& from_type, const DataTypeJsonb& to_type, Review Comment: warning: function 'create_jsonb_wrapper' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] WrapperType create_jsonb_wrapper(const DataTypePtr& from_type, const DataTypeJsonb& to_type, ``` ########## be/src/vec/functions/function_cast.h: ########## @@ -1845,12 +1948,119 @@ case TypeIndex::Float64: return &ConvertImplNumberToJsonb<ColumnFloat64>::execute; case TypeIndex::String: - return &ConvertImplGenericFromString::execute; + if (string_as_jsonb_string) { + // We convert column string to jsonb type just add a string jsonb field to dst column instead of parse + // each line in original string column. + return &ConvertImplStringToJsonbAsJsonbString::execute; + } else { + return &ConvertImplGenericFromString::execute; + } default: return &ConvertImplGenericToJsonb::execute; } } + struct ConvertImplGenericFromVariant { + static Status execute(const FunctionCast* fn, FunctionContext* context, Block& block, + const ColumnNumbers& arguments, const size_t result, + size_t input_rows_count) { + auto& data_type_to = block.get_by_position(result).type; + const auto& col_with_type_and_name = block.get_by_position(arguments[0]); + auto& col_from = col_with_type_and_name.column; + auto& variant = assert_cast<const ColumnObject&>(*col_from); + ColumnPtr col_to = data_type_to->create_column(); + if (!variant.is_finalized()) { + variant.assume_mutable()->finalize(); + } + + if (variant.is_scalar_variant()) { + ColumnPtr nested = variant.get_root(); + auto nested_from_type = variant.get_root_type(); + DCHECK(nested_from_type->is_nullable()); + DCHECK(!data_type_to->is_nullable()); + auto new_context = context->clone(); + new_context->set_jsonb_string_as_string(true); + // dst type nullable has been removed, so we should remove the inner nullable of root column + auto wrapper = fn->prepare_impl( + new_context.get(), remove_nullable(nested_from_type), data_type_to, true); + Block tmp_block {{remove_nullable(nested), remove_nullable(nested_from_type), ""}}; + tmp_block.insert({nullptr, data_type_to, ""}); + /// Perform the requested conversion. + Status st = wrapper(new_context.get(), tmp_block, {0}, 1, input_rows_count); + if (!st.ok()) { + // Fill with default values, which is null + col_to->assume_mutable()->insert_many_defaults(input_rows_count); + col_to = make_nullable(col_to, true); + } else { + col_to = tmp_block.get_by_position(1).column; + // Note: here we should return the nullable result column + col_to = wrap_in_nullable( + col_to, + Block({{nested, nested_from_type, ""}, {col_to, data_type_to, ""}}), + {0}, 1, input_rows_count); + } + } else { + // Could not cast to any other types when it hierarchical like '{"a" : 1}' + if (!data_type_to->is_nullable() && !WhichDataType(data_type_to).is_string()) { + // TODO we should convert as many as possible here, for examle + // this variant column's root is a number column, to convert to number column + // is also acceptable + // return Status::InvalidArgument(fmt::format("Could not cast from variant to {}", + // data_type_to->get_name())); + col_to->assume_mutable()->insert_many_defaults(input_rows_count); + col_to = make_nullable(col_to, true); + } else if (WhichDataType(data_type_to).is_string()) { + return ConvertImplGenericToString::execute2(context, block, arguments, result, + input_rows_count); + } else { + assert_cast<ColumnNullable&>(*col_to->assume_mutable()) + .insert_many_defaults(input_rows_count); + } + } + if (col_to->size() != input_rows_count) { + return Status::InternalError("Unmatched row count {}, expected {}", col_to->size(), + input_rows_count); + } + + block.replace_by_position(result, std::move(col_to)); + return Status::OK(); + } + }; + + struct ConvertImplGenericToVariant { + static Status execute(FunctionContext* context, Block& block, + const ColumnNumbers& arguments, const size_t result, + size_t input_rows_count) { + // auto& data_type_to = block.get_by_position(result).type; + const auto& col_with_type_and_name = block.get_by_position(arguments[0]); + auto& from_type = col_with_type_and_name.type; + auto& col_from = col_with_type_and_name.column; + + // set variant root column/type to from column/type + auto variant = ColumnObject::create(true /*always nullable*/); + variant->create_root(from_type, col_from->assume_mutable()); + + block.replace_by_position(result, std::move(variant)); + return Status::OK(); + } + }; + + // create cresponding variant value to wrap from_type + WrapperType create_variant_wrapper(const DataTypePtr& from_type, Review Comment: warning: function 'create_variant_wrapper' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] WrapperType create_variant_wrapper(const DataTypePtr& from_type, ``` ########## be/src/vec/olap/olap_data_convertor.h: ########## @@ -480,6 +483,22 @@ UInt64 _base_offset; }; //OlapColumnDataConvertorMap + class OlapColumnDataConvertorVariant : public OlapColumnDataConvertorBase { + public: + OlapColumnDataConvertorVariant() + : _root_data_convertor(std::make_unique<OlapColumnDataConvertorVarChar>(true)) {} + void set_source_column(const ColumnWithTypeAndName& typed_column, size_t row_pos, + size_t num_rows) override; + Status convert_to_olap() override; + + const void* get_data() const override; Review Comment: warning: function 'get_data' should be marked [[nodiscard]] [modernize-use-nodiscard] ```suggestion [[nodiscard]] const void* get_data() const override; ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org