| 43 | /// \param input A LIST_VIEW or LARGE_LIST_VIEW array |
| 44 | template <typename offset_type> |
| 45 | std::optional<int64_t> MinViewOffset(const ArraySpan& input) { |
| 46 | const uint8_t* validity = input.buffers[0].data; |
| 47 | const auto* offsets = input.GetValues<offset_type>(1); |
| 48 | const auto* sizes = input.GetValues<offset_type>(2); |
| 49 | |
| 50 | // Make an access to the sizes buffer only when strictly necessary. |
| 51 | #define MINIMIZE_MIN_VIEW_OFFSET(i) \ |
| 52 | auto offset = offsets[i]; \ |
| 53 | if (min_offset.has_value()) { \ |
| 54 | if (offset < *min_offset && sizes[i] > 0) { \ |
| 55 | if (offset == 0) { \ |
| 56 | return 0; \ |
| 57 | } \ |
| 58 | min_offset = offset; \ |
| 59 | } \ |
| 60 | } else { \ |
| 61 | if (sizes[i] > 0) { \ |
| 62 | if (offset == 0) { \ |
| 63 | return 0; \ |
| 64 | } \ |
| 65 | min_offset = offset; \ |
| 66 | } \ |
| 67 | } |
| 68 | |
| 69 | std::optional<offset_type> min_offset; |
| 70 | if (validity == nullptr) { |
| 71 | for (int64_t i = 0; i < input.length; i++) { |
| 72 | MINIMIZE_MIN_VIEW_OFFSET(i); |
| 73 | } |
| 74 | } else { |
| 75 | SetBitRunReader reader(validity, input.offset, input.length); |
| 76 | while (true) { |
| 77 | const auto run = reader.NextRun(); |
| 78 | if (run.length == 0) { |
| 79 | break; |
| 80 | } |
| 81 | for (int64_t i = run.position; i < run.position + run.length; ++i) { |
| 82 | MINIMIZE_MIN_VIEW_OFFSET(i); |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | return min_offset; |
| 87 | |
| 88 | #undef MINIMIZE_MIN_VIEW_OFFSET |
| 89 | } |
| 90 | |
| 91 | /// \pre input.length() > 0 && input.null_count() != input.length() |
| 92 | /// \param input A LIST_VIEW or LARGE_LIST_VIEW array |