Skip to content

Commit f20702b

Browse files
committed
Faster api
1 parent a8df36f commit f20702b

File tree

1 file changed

+79
-13
lines changed

1 file changed

+79
-13
lines changed

arrow-select/src/coalesce/primitive.rs

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717

1818
use crate::coalesce::InProgressArray;
19+
use crate::filter::{FilterPredicate, IndexIterator, IterationStrategy, SlicesIterator};
1920
use arrow_array::cast::AsArray;
2021
use arrow_array::{Array, ArrayRef, ArrowPrimitiveType, PrimitiveArray};
2122
use arrow_buffer::{NullBufferBuilder, ScalarBuffer};
@@ -92,8 +93,8 @@ impl<T: ArrowPrimitiveType + Debug> InProgressArray for InProgressPrimitiveArray
9293
Ok(())
9394
}
9495

95-
/// Copy rows by indices using an iterator (internal helper)
96-
fn copy_rows_by_indices(&mut self, indices: &[usize]) -> Result<(), ArrowError> {
96+
/// Copy rows by indices using a predicate
97+
fn copy_rows_by_filter(&mut self, filter: &FilterPredicate) -> Result<(), ArrowError> {
9798
self.ensure_capacity();
9899

99100
let s = self
@@ -107,21 +108,86 @@ impl<T: ArrowPrimitiveType + Debug> InProgressArray for InProgressPrimitiveArray
107108
.as_primitive::<T>();
108109

109110
let values = s.values();
110-
111-
// Copy values and nulls for each index
112-
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
113-
for &idx in indices {
114-
if nulls.is_null(idx) {
115-
self.nulls.append_null();
111+
let count = filter.count();
112+
113+
// Use the predicate's strategy for optimal iteration
114+
match filter.strategy() {
115+
IterationStrategy::SlicesIterator => {
116+
// Copy values using slices
117+
for (start, end) in SlicesIterator::new(filter.filter_array()) {
118+
self.current.extend_from_slice(&values[start..end]);
119+
}
120+
// Copy nulls using slices
121+
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
122+
for (start, end) in SlicesIterator::new(filter.filter_array()) {
123+
let slice = nulls.slice(start, end - start);
124+
self.nulls.append_buffer(&slice);
125+
}
116126
} else {
117-
self.nulls.append_non_null();
127+
self.nulls.append_n_non_nulls(count);
118128
}
119129
}
120-
} else {
121-
self.nulls.append_n_non_nulls(indices.len());
130+
IterationStrategy::Slices(slices) => {
131+
// Copy values using precomputed slices
132+
for &(start, end) in slices {
133+
self.current.extend_from_slice(&values[start..end]);
134+
}
135+
// Copy nulls using slices
136+
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
137+
for &(start, end) in slices {
138+
let slice = nulls.slice(start, end - start);
139+
self.nulls.append_buffer(&slice);
140+
}
141+
} else {
142+
self.nulls.append_n_non_nulls(count);
143+
}
144+
}
145+
IterationStrategy::IndexIterator => {
146+
// Copy values and nulls for each index
147+
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
148+
for idx in IndexIterator::new(filter.filter_array(), count) {
149+
if nulls.is_null(idx) {
150+
self.nulls.append_null();
151+
} else {
152+
self.nulls.append_non_null();
153+
}
154+
self.current.push(values[idx]);
155+
}
156+
} else {
157+
self.nulls.append_n_non_nulls(count);
158+
for idx in IndexIterator::new(filter.filter_array(), count) {
159+
self.current.push(values[idx]);
160+
}
161+
}
162+
}
163+
IterationStrategy::Indices(indices) => {
164+
// Copy values and nulls using precomputed indices
165+
if let Some(nulls) = s.nulls().filter(|n| n.null_count() > 0) {
166+
for &idx in indices {
167+
if nulls.is_null(idx) {
168+
self.nulls.append_null();
169+
} else {
170+
self.nulls.append_non_null();
171+
}
172+
}
173+
} else {
174+
self.nulls.append_n_non_nulls(count);
175+
}
176+
self.current.extend(indices.iter().map(|&idx| values[idx]));
177+
}
178+
IterationStrategy::All => {
179+
// Copy all values
180+
self.current.extend_from_slice(values);
181+
if let Some(nulls) = s.nulls() {
182+
self.nulls.append_buffer(nulls);
183+
} else {
184+
self.nulls.append_n_non_nulls(values.len());
185+
}
186+
}
187+
IterationStrategy::None => {
188+
// Nothing to copy
189+
}
122190
}
123-
self.current
124-
.extend(indices.into_iter().map(|idx| values[*idx]));
125191

126192
Ok(())
127193
}

0 commit comments

Comments
 (0)