@@ -32,30 +32,52 @@ inline Status cast_from_variant_impl(FunctionContext* context, Block& block,
3232 const auto & col_with_type_and_name = block.get_by_position (arguments[0 ]);
3333 const auto & col_from = col_with_type_and_name.column ;
3434 const IColumn* variant_column = col_from.get ();
35- if (const auto * nullable = check_and_get_column<ColumnNullable>(*variant_column)) {
35+ const auto * nullable = check_and_get_column<ColumnNullable>(*variant_column);
36+ if (nullable != nullptr ) {
3637 variant_column = &nullable->get_nested_column ();
3738 }
38- const auto & variant = assert_cast<const ColumnVariant&>(* variant_column);
39+ const auto * variant = assert_cast<const ColumnVariant*>( variant_column);
3940 ColumnPtr col_to = data_type_to->create_column ();
4041
41- if (!variant.is_finalized ()) {
42- // ColumnVariant should be finalized before parsing, finalize maybe modify original column structure
43- variant.assume_mutable ()->finalize ();
42+ ColumnPtr finalized_input_column;
43+ if (!variant->is_finalized ()) {
44+ // Local exchange can share the same input block across multiple downstream tasks.
45+ // Finalize a private copy so variant casts never mutate shared input columns.
46+ auto finalized_variant = variant->clone_finalized ();
47+ variant = assert_cast<const ColumnVariant*>(finalized_variant.get ());
48+ if (nullable != nullptr ) {
49+ auto cloned_null_map =
50+ nullable->get_null_map_column_ptr ()->clone_resized (input_rows_count);
51+ finalized_input_column = ColumnNullable::create (std::move (finalized_variant),
52+ std::move (cloned_null_map));
53+ } else {
54+ finalized_input_column = std::move (finalized_variant);
55+ }
4456 }
57+ auto execute_on_finalized_input = [&](auto && executor) -> Status {
58+ if (!finalized_input_column) {
59+ return executor (block);
60+ }
61+ Block finalized_block = block;
62+ finalized_block.replace_by_position (arguments[0 ], finalized_input_column);
63+ RETURN_IF_ERROR (executor (finalized_block));
64+ block.replace_by_position (result, finalized_block.get_by_position (result).column );
65+ return Status::OK ();
66+ };
4567
4668 // It's important to convert as many elements as possible in this context. For instance,
4769 // if the root of this variant column is a number column, converting it to a number column
4870 // is acceptable. However, if the destination type is a string and root is none scalar root, then
4971 // we should convert the entire tree to a string.
50- bool is_root_valuable = variant. is_scalar_variant () ||
51- (!variant. is_null_root () &&
52- variant. get_root_type ()->get_primitive_type () != INVALID_TYPE &&
72+ bool is_root_valuable = variant-> is_scalar_variant () ||
73+ (!variant-> is_null_root () &&
74+ variant-> get_root_type ()->get_primitive_type () != INVALID_TYPE &&
5375 !is_string_type (data_type_to->get_primitive_type ()) &&
5476 data_type_to->get_primitive_type () != TYPE_JSONB );
5577
5678 if (is_root_valuable) {
57- ColumnPtr nested = variant. get_root ();
58- auto nested_from_type = variant. get_root_type ();
79+ ColumnPtr nested = variant-> get_root ();
80+ auto nested_from_type = variant-> get_root_type ();
5981 // DCHECK(nested_from_type->is_nullable());
6082 DCHECK (!data_type_to->is_nullable ());
6183 auto new_context = context == nullptr ? nullptr : context->clone ();
@@ -84,16 +106,21 @@ inline Status cast_from_variant_impl(FunctionContext* context, Block& block,
84106 {0 , 1 }, input_rows_count);
85107 }
86108 } else {
87- if (variant. only_have_default_values ()) {
109+ if (variant-> only_have_default_values ()) {
88110 col_to->assume_mutable ()->insert_many_defaults (input_rows_count);
89111 col_to = make_nullable (col_to, true );
90112 } else if (is_string_type (data_type_to->get_primitive_type ())) {
91113 // serialize to string
92- return CastToStringFunction::execute_impl (context, block, arguments, result,
93- input_rows_count);
114+ return execute_on_finalized_input ([&](Block& finalized_block) {
115+ return CastToStringFunction::execute_impl (context, finalized_block, arguments,
116+ result, input_rows_count);
117+ });
94118 } else if (data_type_to->get_primitive_type () == TYPE_JSONB ) {
95119 // serialize to json by parsing
96- return cast_from_generic_to_jsonb (context, block, arguments, result, input_rows_count);
120+ return execute_on_finalized_input ([&](Block& finalized_block) {
121+ return cast_from_generic_to_jsonb (context, finalized_block, arguments, result,
122+ input_rows_count);
123+ });
97124 } else if (!data_type_to->is_nullable () &&
98125 !is_string_type (data_type_to->get_primitive_type ())) {
99126 // other types
0 commit comments