github-actions[bot] commented on code in PR #68667:
URL: https://github.com/apache/doris/pull/68667#discussion_r4141922700


##########
be/src/core/data_type_serde/data_type_variant_serde.cpp:
##########
@@ -157,6 +165,101 @@ Status DataTypeVariantSerDe::write_column_to_arrow(const 
IColumn& column, const
                                                    int64_t start, int64_t end,
                                                    const cctz::time_zone& ctz) 
const {
     const auto* var = check_and_get_column<ColumnVariant>(column);
+    if (array_builder->type()->id() == arrow::Type::STRUCT) {
+        // Legacy documents need JSON conversion; typed scalar roots can keep 
their type.
+        // The outer null map must remain SQL NULL on the wire.
+        if (start < 0 || end < start || end > column.size() ||
+            (null_map != nullptr && end > null_map->size())) {
+            return Status::InvalidArgument("Invalid Variant Arrow row range 
[{}, {})", start, end);
+        }
+        if (var->is_scalar_variant()) {
+            auto scalar_type = remove_nullable(var->get_root_type());
+            if (scalar_type->get_primitive_type() == TYPE_DECIMAL256) {
+                return Status::NotSupported(
+                        "Native Arrow Variant does not support Decimal256 
roots");
+            }
+            if 
(is_supported_variant_typed_identity(scalar_type->get_primitive_type())) {
+                // Avoid a JSON round trip that would turn exact decimal roots 
into doubles.
+                auto typed =
+                        
ColumnVariantV2::create_typed(make_nullable(var->get_root()), scalar_type);
+                return DataTypeVariantV2SerDe().write_column_to_arrow(
+                        *typed, null_map, array_builder, start, end, ctz);
+            }
+        }
+        const size_t rows = end - start;
+        NullMap selected_nulls(rows, 0);
+        NullMap root_mask(rows, 1);
+        bool has_roots = false;
+        bool has_documents = false;
+        for (size_t row = 0; row < rows; ++row) {
+            selected_nulls[row] = null_map != nullptr && (*null_map)[start + 
row];
+            if (selected_nulls[row]) {
+                continue;
+            }
+            const bool root_visible = var->is_scalar_variant()
+                                              ? 
!var->get_root()->is_null_at(start + row)
+                                              : 
var->is_visible_root_value(start + row);
+            root_mask[row] = !root_visible;
+            has_roots |= root_visible;
+            has_documents |= !root_visible;
+        }
+        ColumnPtr roots;
+        if (has_roots) {
+            // JSON reparsing loses decimal/temporal identities and rejects 
non-finite numbers.
+            // Reuse typed CAST for every visible root, including arrays and 
mixed-path batches.
+            auto root_type = remove_nullable(var->get_root_type());
+            auto target_type = std::make_shared<DataTypeVariantV2>();
+            // Invisible roots, including nullable roots, are already masked 
above.
+            Block root_block {
+                    {remove_nullable(var->get_root())->cut(start, rows), 
root_type, "root"},
+                    {target_type->create_column(), target_type, "encoded"}};
+            auto encode_root = 
CastWrapper::create_cast_to_variant_v2_wrapper(root_type);
+            RETURN_IF_ERROR(encode_root(nullptr, root_block, {0}, 1, rows, 
root_mask.data()));

Review Comment:
   [P1] Cover all legal legacy roots before invoking V2 CAST. FE permits MAP, 
STRUCT, TIMEV2, and ARRAY values to be cast to legacy VARIANT, but native 
Flight sends every visible root to this encoder. V2 CAST rejects 
MAP/STRUCT/TIMEV2 roots and ARRAY leaves containing MAP, STRUCT, TIMEV2, or 
legacy VARIANT, so queries that work in UTF8 mode fail in native mode. Extend 
the encoder or use a compatible fallback for unsupported source families, and 
test root and nested cases.



##########
be/src/core/data_type_serde/data_type_variant_serde.cpp:
##########
@@ -157,6 +165,101 @@ Status DataTypeVariantSerDe::write_column_to_arrow(const 
IColumn& column, const
                                                    int64_t start, int64_t end,
                                                    const cctz::time_zone& ctz) 
const {
     const auto* var = check_and_get_column<ColumnVariant>(column);
+    if (array_builder->type()->id() == arrow::Type::STRUCT) {
+        // Legacy documents need JSON conversion; typed scalar roots can keep 
their type.
+        // The outer null map must remain SQL NULL on the wire.
+        if (start < 0 || end < start || end > column.size() ||
+            (null_map != nullptr && end > null_map->size())) {
+            return Status::InvalidArgument("Invalid Variant Arrow row range 
[{}, {})", start, end);
+        }
+        if (var->is_scalar_variant()) {
+            auto scalar_type = remove_nullable(var->get_root_type());
+            if (scalar_type->get_primitive_type() == TYPE_DECIMAL256) {
+                return Status::NotSupported(
+                        "Native Arrow Variant does not support Decimal256 
roots");
+            }
+            if 
(is_supported_variant_typed_identity(scalar_type->get_primitive_type())) {
+                // Avoid a JSON round trip that would turn exact decimal roots 
into doubles.
+                auto typed =
+                        
ColumnVariantV2::create_typed(make_nullable(var->get_root()), scalar_type);

Review Comment:
   [P1] Preserve the legacy null-root value in the scalar shortcut. A legacy 
column parsed from `42` and JSON `null` remains scalar; UTF8 output serializes 
the null root as `{}`, while `create_typed` keeps its inner null map and native 
output emits Parquet Variant null. The value therefore changes with native mode 
(and with a mixed-path batch). Apply root visibility before this shortcut and 
test the scalar-only null row.



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to