| 93 | /// For each row in [start, end), finds the flat index of the matching key. |
| 94 | template <typename Matcher> |
| 95 | void findKeyPositions( |
| 96 | const ColumnArray::Offsets & offsets, |
| 97 | const Matcher & matcher, |
| 98 | size_t start, |
| 99 | size_t end, |
| 100 | PaddedPODArray<size_t> & matched_positions) |
| 101 | { |
| 102 | size_t num_rows = end - start; |
| 103 | matched_positions.resize(num_rows); |
| 104 | |
| 105 | /// Relative offset of the key within the map from the previous row. |
| 106 | /// Used for position prediction. |
| 107 | size_t predicted_relative_pos = 0; |
| 108 | bool have_prediction = false; |
| 109 | |
| 110 | for (size_t i = start; i < end; ++i) |
| 111 | { |
| 112 | size_t positions_row_idx = i - start; |
| 113 | size_t offset_start = offsets[ssize_t(i) - 1]; |
| 114 | size_t offset_end = offsets[i]; |
| 115 | |
| 116 | /// Try the predicted position first. |
| 117 | if (have_prediction) |
| 118 | { |
| 119 | size_t predicted_pos = offset_start + predicted_relative_pos; |
| 120 | if (predicted_pos < offset_end && matcher.match(predicted_pos)) |
| 121 | { |
| 122 | matched_positions[positions_row_idx] = predicted_pos; |
| 123 | continue; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | /// Prediction missed or not available. Fall back to linear scan. |
| 128 | bool found = false; |
| 129 | for (size_t j = offset_start; j < offset_end; ++j) |
| 130 | { |
| 131 | if (matcher.match(j)) |
| 132 | { |
| 133 | matched_positions[positions_row_idx] = j; |
| 134 | predicted_relative_pos = j - offset_start; |
| 135 | have_prediction = true; |
| 136 | found = true; |
| 137 | break; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | if (!found) |
| 142 | { |
| 143 | /// Keep the prediction unchanged: if only this row is missing the key, |
| 144 | /// subsequent rows likely have the same key order, so the prediction |
| 145 | /// may still be valid. A wrong prediction costs only one extra match call. |
| 146 | matched_positions[positions_row_idx] = KEY_NOT_FOUND; |
| 147 | } |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /// Dispatches to the appropriate specialized matcher based on the key column type, |
| 152 | /// then calls findKeyPositions with that matcher. |
no test coverage detected