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


##########
be/src/storage/segment/variant/variant_column_writer_impl.cpp:
##########
@@ -596,6 +600,17 @@ Status VariantSubcolumnWriter::_append_v2(const 
VariantColumnData& column, size_
                                        column.row_pos, column.row_pos + 
num_rows, source->size());
     }
     DORIS_CHECK(outer_nulls.empty() || outer_nulls.size() == num_rows);
+    if (_v2_builder == nullptr) {
+        RETURN_IF_ERROR(_initialize_v2_builder());
+        if (_running_type != nullptr) {
+            // Continue from the type inferred by the sealed chunks. Appending 
a value that the
+            // previous chunks' type cannot hold (for example a bool after 
integers) then takes
+            // the builder's own JSONB fallback inside this chunk instead of 
being merged away.
+            RETURN_IF_ERROR(_v2_builder->convert_to(_running_type));

Review Comment:
   [P1] Preserve value-dependent fallback across chunk boundaries
   
   Seeding an empty builder with `_running_type` does not reproduce promotions 
that depend on the sealed values. For an untyped extracted path, fill one chunk 
with scale-1 Decimal128 values near the precision-38 maximum, then append 
`1e-38` in the next chunk. The empty builder widens successfully to 
Decimal128(38,38), but the earlier values overflow that type. At finalization, 
`chunk.builder->convert_to(flush_type)` uses `promote(..., true)`, filters 
their row IDs, and writes NULLs instead (or fails subsequent path-stat checks). 
The uninterrupted builder preserves these values by falling back to JSONB, as 
`PreservesRowsWhenInferredDecimalPromotionOverflows` already checks. Evaluate 
inferred promotions against retained chunks and use a lossless whole-path 
fallback; cast-null filtering should remain limited to explicit storage 
coercion.



##########
be/src/storage/segment/variant/v2/variant_path_builder.cpp:
##########
@@ -1038,6 +1038,10 @@ bool cast_introduced_null(const IColumn& source, const 
IColumn& target) {
 
 } // namespace
 
+DataTypePtr variant_path_least_common_type(const DataTypePtr& left, const 
DataTypePtr& right) {
+    return path_least_common_type(left, right);

Review Comment:
   [P1] Unwrap nullable arrays before merging chunk types
   
   `VariantPathBuilder::type()` returns `Nullable(...)`, so finalization passes 
nullable arrays through this wrapper. The internal `path_least_common_type` 
checks for `DataTypeArray` directly; those checks miss the nullable wrapper and 
delegate to `get_least_supertype_jsonb`, whose recursive decimal merge selects 
the first scale. If an untyped extracted path has `[1.23]` (scale 2) in an 
earlier chunk and `[1.2345]` (scale 4) in a later chunk, the second builder 
correctly widens to scale 4, but this final merge chooses scale 2 and the final 
cast changes `[1.2345]` to `[1.23]`. Single-builder inference retains scale 4. 
Unwrap the outer nullable types before dispatching so array elements use the 
metadata-aware common-type rules, and cover this with a multi-chunk 
decimal-array test.



-- 
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