dalingmeng commented on code in PR #340:
URL: https://github.com/apache/paimon-cpp/pull/340#discussion_r4023077879


##########
src/paimon/common/utils/arrow/arrow_utils_test.cpp:
##########
@@ -220,6 +220,57 @@ TEST(ArrowUtilsTest, TestCheckNullableMatchWithStruct) {
     }
 }
 
+TEST(ArrowUtilsTest, TestCheckNullableMatchParentNullMasksChildren) {
+    auto child = arrow::field("child", arrow::int32(), /*nullable=*/false);
+    auto struct_field = arrow::field("parent", arrow::struct_({child}), 
/*nullable=*/true);
+    auto vector_type =
+        arrow::fixed_size_list(arrow::field("item", arrow::float32(), 
/*nullable=*/false), 3);
+    auto vector_field = arrow::field("embedding", vector_type, 
/*nullable=*/true);
+    auto schema = arrow::schema({struct_field, vector_field});
+
+    // Do not build the complete batch with ArrayFromJSON: for a null STRUCT 
it appends a valid
+    // default value to primitive children, which cannot represent the hidden 
child null under test.
+    auto parent_with_validity = checked_pointer_cast<arrow::StructArray>(
+        arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({child}), 
R"([null, [1]])")
+            .ValueOrDie());
+    std::shared_ptr<arrow::Array> child_array =
+        arrow::ipc::internal::json::ArrayFromJSON(arrow::int32(), "[null, 
1]").ValueOrDie();
+    std::shared_ptr<arrow::StructArray> parent =
+        arrow::StructArray::Make({child_array}, {child}, 
parent_with_validity->null_bitmap(),
+                                 parent_with_validity->null_count())
+            .ValueOrDie();
+    auto vector = checked_pointer_cast<arrow::FixedSizeListArray>(
+        arrow::ipc::internal::json::ArrayFromJSON(vector_type, R"([null, [1.0, 
2.0, 3.0]])")
+            .ValueOrDie());
+    std::shared_ptr<arrow::StructArray> batch =
+        arrow::StructArray::Make({parent, vector}, {struct_field, 
vector_field}).ValueOrDie();
+
+    ASSERT_OK(ArrowUtils::CheckNullabilityMatch(schema, batch));
+}
+
+TEST(ArrowUtilsTest, TestCheckNullableMatchRejectsVisibleChildNulls) {
+    auto child = arrow::field("child", arrow::int32(), /*nullable=*/false);
+    auto struct_field = arrow::field("parent", arrow::struct_({child}), 
/*nullable=*/true);
+    std::shared_ptr<arrow::Array> struct_batch =
+        
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({struct_field}), 
R"([[[null]]])")
+            .ValueOrDie();
+    ASSERT_NOK_WITH_MSG(
+        ArrowUtils::CheckNullabilityMatch(arrow::schema({struct_field}), 
struct_batch),
+        "CheckNullabilityMatch failed, field child not nullable while data 
have null value");
+
+    auto vector_type =
+        arrow::fixed_size_list(arrow::field("item", arrow::float32(), 
/*nullable=*/false), 3);
+    auto vector_field = arrow::field("embedding", vector_type, 
/*nullable=*/true);
+    std::shared_ptr<arrow::Array> vector_batch =
+        
arrow::ipc::internal::json::ArrayFromJSON(arrow::struct_({vector_field}),
+                                                  R"([[[1.0, null, 3.0]]])")
+            .ValueOrDie();
+    ASSERT_NOK_WITH_MSG(
+        ArrowUtils::CheckNullabilityMatch(arrow::schema({vector_field}), 
vector_batch),
+        "VECTOR field embedding is invalid: CheckNullabilityMatch failed, 
field item not nullable "
+        "while data have null value");
+}
+

Review Comment:
   [Tests] Add parent-null coverage for LIST / MAP / sliced / deeply-nestedThe 
new TestCheckNullableMatchParentNullMasksChildren and 
TestCheckNullableMatchRejectsVisibleChildNulls only cover STRUCT and 
VECTOR(FSL). But the VisibleRanges fix also governs LIST/MAP, and the old 
InnerCheckNullabilityMatch recursed into the whole list_array->values() for 
LIST without excluding values hidden under a null parent row — one of the main 
false-positive paths. Suggest adding these regression cases to lock in the fix:
   LIST: a nullable list row is null while its value_field is declared 
not-nullable, and the values in that parent-null row's range contain null → 
should pass (no false positive); a null in a visible row → should be rejected.
   MAP: parent map row is null, key/item not-nullable with nulls at the 
corresponding positions → should pass.
   Sliced array (offset ≠ 0): validate a sliced nested array to confirm 
value_offset mapping and IsValid indexing remain correct.
   Deeply nested (STRUCT > LIST > STRUCT): multi-level visible-range narrowing, 
where a mid-level null parent masks deeper child nulls.



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

Reply via email to