| 268 | } |
| 269 | |
| 270 | fn consume_batch(&mut self) -> Result<ArrayRef> { |
| 271 | let row_count = self.selections.len(); |
| 272 | if row_count == 0 { |
| 273 | return Ok(new_empty_array(self.inner.get_data_type())); |
| 274 | } |
| 275 | |
| 276 | let start_position = self.outer_position - row_count; |
| 277 | |
| 278 | let selection_buffer = self.selections.finish(); |
| 279 | |
| 280 | let start_batch = start_position / self.batch_size; |
| 281 | let end_batch = (start_position + row_count - 1) / self.batch_size; |
| 282 | |
| 283 | let mut selected_arrays = Vec::new(); |
| 284 | for batch_id in start_batch..=end_batch { |
| 285 | let batch_start = batch_id * self.batch_size; |
| 286 | let batch_end = batch_start + self.batch_size - 1; |
| 287 | let batch_id = self.get_batch_id_from_position(batch_start); |
| 288 | |
| 289 | // Calculate the overlap between the start_position and the batch |
| 290 | let overlap_start = start_position.max(batch_start); |
| 291 | let overlap_end = (start_position + row_count - 1).min(batch_end); |
| 292 | |
| 293 | if overlap_start > overlap_end { |
| 294 | continue; |
| 295 | } |
| 296 | |
| 297 | let selection_start = overlap_start - start_position; |
| 298 | let selection_length = overlap_end - overlap_start + 1; |
| 299 | let mask = selection_buffer.slice(selection_start, selection_length); |
| 300 | |
| 301 | if mask.count_set_bits() == 0 { |
| 302 | continue; |
| 303 | } |
| 304 | |
| 305 | let mask_array = BooleanArray::from(mask); |
| 306 | // Read from local cache instead of shared cache to avoid cache eviction issues |
| 307 | let cached = self |
| 308 | .local_cache |
| 309 | .get(&batch_id) |
| 310 | .expect("data must be already cached in the read_records call, this is a bug"); |
| 311 | let cached = cached.slice(overlap_start - batch_start, selection_length); |
| 312 | let filtered = arrow_select::filter::filter(&cached, &mask_array)?; |
| 313 | selected_arrays.push(filtered); |
| 314 | } |
| 315 | |
| 316 | self.selections = BooleanBufferBuilder::new(0); |
| 317 | |
| 318 | // Only remove batches from local buffer that are completely behind current position |
| 319 | // Keep the current batch and any future batches as they might still be needed |
| 320 | let current_batch_id = self.get_batch_id_from_position(self.outer_position); |
| 321 | self.local_cache |
| 322 | .retain(|batch_id, _| batch_id.val >= current_batch_id.val); |
| 323 | |
| 324 | // For consumers, cleanup batches that have been completely consumed |
| 325 | // This reduces the memory usage of the shared cache |
| 326 | if self.role == CacheRole::Consumer { |
| 327 | self.cleanup_consumed_batches(); |