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


##########
src/paimon/common/utils/arrow/arrow_utils.cpp:
##########
@@ -90,6 +89,153 @@ bool HasUndeclaredDictionaryChild(const 
std::shared_ptr<arrow::DataType>& type,
     return false;
 }
 
+// Positions in the current array which remain visible through every nullable 
ancestor.
+struct VisibleRange {
+    int64_t offset;
+    int64_t length;
+};
+
+using VisibleRanges = std::vector<VisibleRange>;
+
+void AppendVisibleRange(int64_t offset, int64_t length, VisibleRanges* ranges) 
{
+    if (length == 0) {
+        return;
+    }
+    if (!ranges->empty()) {
+        VisibleRange& last = ranges->back();
+        if (last.offset + last.length == offset) {
+            last.length += length;
+            return;
+        }
+    }
+    ranges->push_back({offset, length});
+}
+
+Status NullabilityMismatch(const arrow::Field& field) {
+    return Status::Invalid(fmt::format(
+        "CheckNullabilityMatch failed, field {} not nullable while data have 
null value",
+        field.name()));
+}
+
+Result<VisibleRanges> IntersectWithValidity(const arrow::Array& array,
+                                            const VisibleRanges& 
visible_ranges,
+                                            const arrow::Field& field) {
+    const bool nullable = field.nullable();
+    if (visible_ranges.empty()) {
+        return VisibleRanges{};
+    }
+
+    const int64_t null_count = array.null_count();
+    if (null_count == 0) {
+        return visible_ranges;
+    }
+    if (null_count == array.length()) {
+        if (!nullable) {
+            return NullabilityMismatch(field);
+        }
+        return VisibleRanges{};
+    }
+
+    VisibleRanges valid_ranges;
+    for (const VisibleRange& range : visible_ranges) {

Review Comment:
   Non-blocking / optional (up to you):IntersectWithValidity scans visible 
ranges bit-by-bit via array.IsValid(i). Correct as-is — just a perf note: 
Arrow's arrow::internal::SetBitRunReader (arrow/util/bit_run_reader.h) scans 
the validity bitmap word-by-word and yields runs of set bits directly, skipping 
all-ones words instead of testing each bit. Since validity bitmaps are usually 
mostly-ones and this runs on the main write path, it could help on large arrays 
— and its output is exactly the "valid ranges" we're building here.
   
       VisibleRanges valid_ranges;
       const uint8_t* bitmap = array.null_bitmap_data();
       for (const VisibleRange& range : visible_ranges) {
           const int64_t base = array.offset() + range.offset;  // IsValid(i) 
uses logical index; bitmap bit is array.offset()+i
           arrow::internal::SetBitRunReader reader(bitmap, base, range.length);
           int64_t covered = 0;
           for (auto run = reader.NextRun(); !run.AtEnd(); run = 
reader.NextRun()) {
               AppendVisibleRange(range.offset + run.position, run.length, 
&valid_ranges);  // position is relative to base
               covered += run.length;
           }
           if (!nullable && covered != range.length) {  // a visible-range 
null; can't use global null_count (nulls may sit under a null parent)
               return NullabilityMismatch(field);
           }
       }
       return valid_ranges;
   
   Note this would be the first use of bit_run_reader.h in the repo, so feel 
free to skip if you'd rather not introduce a new pattern for a 
micro-optimization.



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