1use super::*;
2
3impl<'host, H: WindowHost + ?Sized> WindowExecutor<'host, H> {
4 pub(crate) fn execute_select_with_window_functions(
7 &self,
8 stmt: &SelectStatement,
9 ctx: &ExecutionContext,
10 base_rows: &[(i64, Row)],
11 base_columns: &[String],
12 ) -> Result<Box<dyn QueryResult>> {
13 self.execute_select_with_window_functions_internal(
14 stmt,
15 ctx,
16 base_rows,
17 base_columns,
18 None,
19 None,
20 )
21 }
22
23 pub(crate) fn execute_select_with_window_functions_presorted(
27 &self,
28 stmt: &SelectStatement,
29 ctx: &ExecutionContext,
30 base_rows: &[(i64, Row)],
31 base_columns: &[String],
32 pre_sorted: Option<WindowPreSortedState>,
33 ) -> Result<Box<dyn QueryResult>> {
34 self.execute_select_with_window_functions_internal(
35 stmt,
36 ctx,
37 base_rows,
38 base_columns,
39 pre_sorted,
40 None,
41 )
42 }
43
44 pub(crate) fn execute_select_with_window_functions_pregrouped(
48 &self,
49 stmt: &SelectStatement,
50 ctx: &ExecutionContext,
51 base_rows: &[(i64, Row)],
52 base_columns: &[String],
53 pre_grouped: WindowPreGroupedState,
54 ) -> Result<Box<dyn QueryResult>> {
55 self.execute_select_with_window_functions_internal(
56 stmt,
57 ctx,
58 base_rows,
59 base_columns,
60 None,
61 Some(pre_grouped),
62 )
63 }
64
65 pub(super) fn execute_select_with_window_functions_internal(
67 &self,
68 stmt: &SelectStatement,
69 ctx: &ExecutionContext,
70 base_rows: &[(i64, Row)],
71 base_columns: &[String],
72 pre_sorted: Option<WindowPreSortedState>,
73 pre_grouped: Option<WindowPreGroupedState>,
74 ) -> Result<Box<dyn QueryResult>> {
75 let window_functions = self.parse_window_functions(stmt, base_columns)?;
77
78 if window_functions.is_empty() {
79 let mut rows = RowVec::with_capacity(base_rows.len());
81 for (id, row) in base_rows.iter() {
82 rows.push((*id, row.clone()));
83 }
84 return Ok(Box::new(ExecutorResult::new(base_columns.to_vec(), rows)));
85 }
86
87 if stmt.order_by.is_empty() && stmt.offset.is_none() {
92 if let Some(limit_expr) = &stmt.limit {
93 let has_partition_by = window_functions
94 .iter()
95 .any(|wf| !wf.partition_by_exprs.is_empty());
96
97 if has_partition_by && Self::all_partitions_match(&window_functions) {
98 if let Expression::IntegerLiteral(lit) = limit_expr.as_ref() {
99 let limit_val = lit.value;
100 if limit_val > 0 {
101 return self.execute_select_with_window_functions_streaming(
102 stmt,
103 ctx,
104 base_rows,
105 base_columns,
106 &window_functions,
107 limit_val as usize,
108 );
109 }
110 }
111 }
112 }
113 }
114
115 let mut col_index_map = build_column_index_map(base_columns);
117
118 for col_expr in stmt.columns.iter() {
123 if let Expression::Aliased(aliased) = col_expr {
124 let alias_lower = aliased.alias.value_lower.as_str();
125 if let Some(&idx) = col_index_map.get(alias_lower) {
126 let patterns = self.extract_aggregate_patterns(aliased.expression.as_ref());
128 for pattern in patterns {
129 col_index_map.insert(pattern.to_lowercase(), idx);
130 }
131 }
132 }
133 }
134
135 let mut order_by_cache: Vec<(String, ColumnarOrderByValues)> = Vec::new();
145 for wf in &window_functions {
146 if !wf.order_by.is_empty() {
147 let cache_key = Self::order_by_cache_key(&wf.order_by);
149 let already_cached = order_by_cache.iter().any(|(key, _)| key == &cache_key);
151 if !already_cached {
152 let precomputed = self.precompute_order_by_values(
153 &wf.order_by,
154 base_rows,
155 base_columns,
156 &col_index_map,
157 ctx,
158 )?;
159 order_by_cache.push((cache_key, precomputed));
160 }
161 }
162 }
163
164 let mut window_value_map: StringMap<Vec<Value>> = StringMap::new();
165 for wf in &window_functions {
166 let window_values = self.compute_window_function(
167 wf,
168 base_rows,
169 base_columns,
170 &col_index_map,
171 ctx,
172 pre_sorted.as_ref(),
173 pre_grouped.as_ref(),
174 &order_by_cache,
175 )?;
176 window_value_map.insert(wf.column_name.to_lowercase(), window_values);
177 }
178
179 let mut result_columns = Vec::new();
182
183 let select_items = self.parse_select_list_for_window(stmt, base_columns, &window_functions);
185
186 for item in &select_items {
187 result_columns.push(item.output_name.clone());
188 }
189
190 let num_rows = base_rows.len();
195
196 let agg_aliases: Vec<(String, usize)> =
198 col_index_map.iter().map(|(k, v)| (k.clone(), *v)).collect();
199
200 let transformed_items: Vec<_> = select_items
203 .iter()
204 .map(|item| match &item.source {
205 SelectItemSource::ExpressionWithWindow(expr, wf_names) => {
206 let mut counter = 0;
207 let transformed =
208 Self::replace_windows_with_identifiers(expr, wf_names, &mut counter);
209 (item, Some(transformed), Some(wf_names.clone()))
210 }
211 _ => (item, None, None),
212 })
213 .collect();
214
215 let mut extended_columns = base_columns.to_vec();
217 let mut added_wf_names: Vec<String> = Vec::new();
218 for (_, _, wf_names_opt) in &transformed_items {
219 if let Some(wf_names) = wf_names_opt {
220 for wf_name in wf_names {
221 if !added_wf_names.contains(wf_name) {
222 extended_columns.push(wf_name.clone());
223 added_wf_names.push(wf_name.clone());
224 }
225 }
226 }
227 }
228
229 let base_expr_items: Vec<(usize, &Expression)> = transformed_items
231 .iter()
232 .enumerate()
233 .filter_map(|(i, (item, _, _))| {
234 if let SelectItemSource::Expression(expr) = &item.source {
235 Some((i, expr))
236 } else {
237 None
238 }
239 })
240 .collect();
241
242 let ext_expr_items: Vec<(usize, &Expression)> = transformed_items
244 .iter()
245 .enumerate()
246 .filter_map(|(i, (_, transformed_opt, _))| transformed_opt.as_ref().map(|t| (i, t)))
247 .collect();
248
249 let base_exprs: Vec<Expression> =
252 base_expr_items.iter().map(|(_, e)| (*e).clone()).collect();
253 let mut base_eval = if !base_exprs.is_empty() {
254 Some(
255 MultiExpressionEval::compile_with_aliases(&base_exprs, base_columns, &agg_aliases)?
256 .with_context(ctx),
257 )
258 } else {
259 None
260 };
261
262 let ext_exprs: Vec<Expression> = ext_expr_items.iter().map(|(_, e)| (*e).clone()).collect();
265 let mut ext_eval = if !ext_exprs.is_empty() {
266 Some(
267 MultiExpressionEval::compile_with_aliases(
268 &ext_exprs,
269 &extended_columns,
270 &agg_aliases,
271 )?
272 .with_context(ctx),
273 )
274 } else {
275 None
276 };
277
278 let ext_values_capacity = if !ext_expr_items.is_empty() {
280 base_rows.first().map_or(0, |r| r.1.len()) + added_wf_names.len()
281 } else {
282 0
283 };
284 let mut ext_values: CompactVec<Value> = CompactVec::with_capacity(ext_values_capacity);
285
286 let num_items = select_items.len();
288
289 let mut column_data: Vec<Vec<Value>> = Vec::with_capacity(num_items);
296
297 let wf_names_in_exprs: std::collections::HashSet<&str> =
299 added_wf_names.iter().map(|s| s.as_str()).collect();
300
301 for (item, _, _) in &transformed_items {
304 match &item.source {
305 SelectItemSource::WindowFunction(wf_name_lower) => {
306 let source_values = window_value_map.get(wf_name_lower).ok_or_else(|| {
307 Error::internal(format!(
308 "window projection source {wf_name_lower} is missing"
309 ))
310 })?;
311 if source_values.len() != num_rows {
312 return Err(Error::internal(format!(
313 "window projection source {wf_name_lower} has {} rows, expected {num_rows}",
314 source_values.len()
315 )));
316 }
317 if wf_names_in_exprs.contains(wf_name_lower.as_str()) {
320 let values = source_values.clone();
322 column_data.push(values);
323 } else {
324 let values = window_value_map.remove(wf_name_lower).ok_or_else(|| {
326 Error::internal(format!(
327 "window projection source {wf_name_lower} disappeared"
328 ))
329 })?;
330 column_data.push(values);
331 }
332 }
333 SelectItemSource::BaseColumn(base_col_idx) => {
334 let mut values = Vec::with_capacity(num_rows);
336 for (_, base_row) in base_rows {
337 values.push(base_row.get(*base_col_idx).cloned().ok_or_else(|| {
338 Error::internal(format!(
339 "window base projection index {base_col_idx} is outside row width {}",
340 base_row.len()
341 ))
342 })?);
343 }
344 column_data.push(values);
345 }
346 SelectItemSource::Expression(_) | SelectItemSource::ExpressionWithWindow(_, _) => {
347 column_data.push(vec![NULL_VALUE; num_rows]);
349 }
350 }
351 }
352
353 let has_expressions = !base_expr_items.is_empty() || !ext_expr_items.is_empty();
355 if has_expressions {
356 for (row_idx, (_, base_row)) in base_rows.iter().enumerate() {
357 if let Some(ref mut eval) = base_eval {
359 let base_results = eval.eval_all(base_row)?;
360 if base_results.len() != base_expr_items.len() {
361 return Err(Error::internal(format!(
362 "window base projection produced {} values, expected {}",
363 base_results.len(),
364 base_expr_items.len()
365 )));
366 }
367 for (eval_idx, (item_idx, _)) in base_expr_items.iter().enumerate() {
368 column_data[*item_idx][row_idx] = base_results[eval_idx].clone();
369 }
370 }
371
372 if !ext_expr_items.is_empty() {
374 if let Some(ref mut eval) = ext_eval {
375 ext_values.clear();
377 ext_values.extend(base_row.iter().cloned());
378 for wf_name in &added_wf_names {
379 let wf_value = window_value_map
380 .get(wf_name)
381 .and_then(|vals| vals.get(row_idx).cloned())
382 .ok_or_else(|| {
383 Error::internal(format!(
384 "window expression source {wf_name} is missing row {row_idx}"
385 ))
386 })?;
387 ext_values.push(wf_value);
388 }
389 let ext_row = Row::from_compact_vec(ext_values.clone());
390
391 let ext_result_values = eval.eval_all(&ext_row)?;
392 if ext_result_values.len() != ext_expr_items.len() {
393 return Err(Error::internal(format!(
394 "window extended projection produced {} values, expected {}",
395 ext_result_values.len(),
396 ext_expr_items.len()
397 )));
398 }
399 for (eval_idx, (item_idx, _)) in ext_expr_items.iter().enumerate() {
400 column_data[*item_idx][row_idx] = ext_result_values[eval_idx].clone();
401 }
402 }
403 }
404 }
405 }
406
407 self.append_hidden_window_order_columns(
408 stmt,
409 ctx,
410 base_rows,
411 base_columns,
412 &mut result_columns,
413 &mut column_data,
414 )?;
415
416 Ok(Box::new(ColumnarResult::new(result_columns, column_data)))
418 }
419
420 pub(super) fn append_hidden_window_order_columns(
425 &self,
426 stmt: &SelectStatement,
427 ctx: &ExecutionContext,
428 base_rows: &[(i64, Row)],
429 base_columns: &[String],
430 result_columns: &mut Vec<String>,
431 column_data: &mut Vec<Vec<Value>>,
432 ) -> Result<()> {
433 if stmt.order_by.is_empty() && stmt.distinct_on.is_empty() {
434 return Ok(());
435 }
436
437 let base_index = build_column_index_map(base_columns);
438 let mut append_expression = |expression: &Expression| -> Result<()> {
439 let selected = stmt.columns.iter().any(|selected| match selected {
442 Expression::Aliased(aliased) => {
443 aliased.expression.as_ref().to_string() == expression.to_string()
444 || matches!(expression, Expression::Identifier(id)
445 if aliased.alias.value_lower == id.value_lower)
446 }
447 other => other.to_string() == expression.to_string(),
448 });
449 if selected || matches!(expression, Expression::IntegerLiteral(_)) {
450 return Ok(());
451 }
452
453 let (column_name, values) = match expression {
454 Expression::Identifier(id) => {
455 let Some(&index) = base_index.get(id.value_lower.as_str()) else {
456 if result_columns
458 .iter()
459 .any(|name| name.eq_ignore_ascii_case(id.value_lower.as_str()))
460 {
461 return Ok(());
462 }
463 return Err(Error::ColumnNotFound(id.value.to_string()));
464 };
465 let name = base_columns[index].clone();
466 let values = base_rows
467 .iter()
468 .map(|(_, row)| row.get(index).cloned().unwrap_or(NULL_VALUE))
469 .collect();
470 (name, values)
471 }
472 Expression::QualifiedIdentifier(id) => {
473 let qualified = format!("{}.{}", id.qualifier.value_lower, id.name.value_lower);
474 let Some(&index) = base_index
475 .get(qualified.as_str())
476 .or_else(|| base_index.get(id.name.value_lower.as_str()))
477 else {
478 return Err(Error::ColumnNotFound(format!(
479 "{}.{}",
480 id.qualifier.value, id.name.value
481 )));
482 };
483 let name = base_columns[index].clone();
484 let values = base_rows
485 .iter()
486 .map(|(_, row)| row.get(index).cloned().unwrap_or(NULL_VALUE))
487 .collect();
488 (name, values)
489 }
490 _ => {
491 let name = expression.to_string();
492 if result_columns
493 .iter()
494 .any(|column| column.eq_ignore_ascii_case(&name))
495 {
496 return Ok(());
497 }
498 let mut evaluator =
499 ExpressionEval::compile(expression, base_columns)?.with_context(ctx);
500 let values = base_rows
501 .iter()
502 .map(|(_, row)| evaluator.eval(row))
503 .collect::<Result<Vec<_>>>()?;
504 (name, values)
505 }
506 };
507
508 if !result_columns
509 .iter()
510 .any(|name| name.eq_ignore_ascii_case(&column_name))
511 {
512 result_columns.push(column_name);
513 column_data.push(values);
514 }
515 Ok(())
516 };
517
518 for order in &stmt.order_by {
519 append_expression(&order.expression)?;
520 }
521 for expression in &stmt.distinct_on {
522 append_expression(expression)?;
523 }
524 Ok(())
525 }
526
527 pub(super) fn execute_select_with_window_functions_streaming(
530 &self,
531 stmt: &SelectStatement,
532 ctx: &ExecutionContext,
533 base_rows: &[(i64, Row)],
534 base_columns: &[String],
535 window_functions: &[WindowFunctionInfo],
536 limit: usize,
537 ) -> Result<Box<dyn QueryResult>> {
538 let primary_wf = window_functions
540 .iter()
541 .find(|wf| !wf.partition_by_exprs.is_empty())
542 .unwrap(); let col_index_map = build_column_index_map(base_columns);
546
547 let partitions =
549 Self::build_partition_map(primary_wf, base_rows, base_columns, &col_index_map, ctx)?;
550
551 let select_items = self.parse_select_list_for_window(stmt, base_columns, window_functions);
553 let result_columns: Vec<String> =
554 select_items.iter().map(|i| i.output_name.clone()).collect();
555
556 let mut order_by_cache: Vec<(String, ColumnarOrderByValues)> = Vec::new();
558 for wf in window_functions {
559 if !wf.order_by.is_empty() {
560 let cache_key = Self::order_by_cache_key(&wf.order_by);
561 let already_cached = order_by_cache.iter().any(|(key, _)| key == &cache_key);
562 if !already_cached {
563 let precomputed = self.precompute_order_by_values(
564 &wf.order_by,
565 base_rows,
566 base_columns,
567 &col_index_map,
568 ctx,
569 )?;
570 order_by_cache.push((cache_key, precomputed));
571 }
572 }
573 }
574
575 let resolved_wfs: Vec<_> = window_functions
577 .iter()
578 .map(|wf| {
579 let is_agg = self.host.window_function_registry().is_aggregate(&wf.name);
580 let func = if is_agg {
581 None
582 } else {
583 self.host.window_function_registry().get_window(&wf.name)
584 };
585 (wf, func, is_agg)
586 })
587 .collect();
588
589 let mut precomputed_agg: StringMap<Vec<Value>> = StringMap::new();
591 for (wf, _, is_agg) in &resolved_wfs {
592 if *is_agg {
593 let cache_key = Self::order_by_cache_key(&wf.order_by);
594 let precomputed_order_by = order_by_cache
595 .iter()
596 .find(|(key, _)| key == &cache_key)
597 .map(|(_, v)| v);
598 let agg_results = self.compute_aggregate_window_function(
599 wf,
600 base_rows,
601 base_columns,
602 &col_index_map,
603 ctx,
604 None,
605 precomputed_order_by,
606 )?;
607 precomputed_agg.insert(wf.column_name.to_lowercase(), agg_results);
608 }
609 }
610
611 let mut result_rows = RowVec::with_capacity(limit);
613 let mut result_row_id = 0i64;
614
615 let partitions_vec: Vec<_> = partitions.into_iter().collect();
616
617 for (_partition_key, row_indices) in partitions_vec {
618 if result_rows.len() >= limit {
619 break;
620 }
621
622 let mut window_value_map: StringMap<Vec<Value>> = StringMap::new();
624
625 for (wf, win_func_opt, is_agg) in &resolved_wfs {
626 if *is_agg {
627 let key = wf.column_name.to_lowercase();
629 if let Some(all_results) = precomputed_agg.get(&key) {
630 let partition_vals: Vec<Value> = row_indices
631 .iter()
632 .map(|&i| all_results[i].clone())
633 .collect();
634 window_value_map.insert(key, partition_vals);
635 }
636 } else if let Some(win_func) = win_func_opt {
637 let cache_key = Self::order_by_cache_key(&wf.order_by);
638 let precomputed_order_by = order_by_cache
639 .iter()
640 .find(|(key, _)| key == &cache_key)
641 .map(|(_, v)| v);
642 let (sorted_values, sorted_indices) = self.compute_window_for_partition(
643 win_func.as_ref(),
644 wf,
645 base_rows,
646 row_indices.clone(),
647 precomputed_order_by,
648 base_columns,
649 &col_index_map,
650 ctx,
651 false,
652 )?;
653 let orig_to_local: FxHashMap<usize, usize> = row_indices
656 .iter()
657 .enumerate()
658 .map(|(local, &orig)| (orig, local))
659 .collect();
660 let mut by_orig = vec![NULL_VALUE; row_indices.len()];
661 for (pos, &orig_idx) in sorted_indices.iter().enumerate() {
662 if let Some(&local) = orig_to_local.get(&orig_idx) {
663 by_orig[local] = sorted_values[pos].clone();
664 }
665 }
666 window_value_map.insert(wf.column_name.to_lowercase(), by_orig);
667 }
668 }
669
670 enum CompiledItem<'a> {
672 BaseColumn(usize),
673 WindowFunction(&'a str),
674 Expression(ExpressionEval),
675 ExpressionWithWindow(ExpressionEval, Vec<&'a str>),
676 }
677 let num_items = select_items.len();
678 let mut compiled_items: Vec<CompiledItem<'_>> = Vec::with_capacity(num_items);
679 for item in &select_items {
680 compiled_items.push(match &item.source {
681 SelectItemSource::BaseColumn(idx) => CompiledItem::BaseColumn(*idx),
682 SelectItemSource::WindowFunction(name) => {
683 CompiledItem::WindowFunction(name.as_str())
684 }
685 SelectItemSource::Expression(expr) => {
686 CompiledItem::Expression(ExpressionEval::compile(expr, base_columns)?)
687 }
688 SelectItemSource::ExpressionWithWindow(expr, wf_names) => {
689 let mut counter = 0;
690 let transformed =
691 Self::replace_windows_with_identifiers(expr, wf_names, &mut counter);
692 let mut ext_columns = base_columns.to_vec();
693 for wf_name in wf_names {
694 ext_columns.push(wf_name.clone());
695 }
696 let eval = ExpressionEval::compile(&transformed, &ext_columns)?;
697 let name_refs: Vec<&str> = wf_names.iter().map(|s| s.as_str()).collect();
698 CompiledItem::ExpressionWithWindow(eval, name_refs)
699 }
700 });
701 }
702
703 let ext_capacity = base_rows.first().map_or(0, |r| r.1.len()) + 1;
704 let mut ext_values: CompactVec<Value> = CompactVec::with_capacity(ext_capacity);
705
706 for (local_pos, &orig_idx) in row_indices.iter().enumerate() {
708 if result_rows.len() >= limit {
709 break;
710 }
711
712 let base_row = &base_rows[orig_idx].1;
713 let mut values: CompactVec<Value> = CompactVec::with_capacity(num_items);
714
715 for ci in &mut compiled_items {
716 let value = match ci {
717 CompiledItem::BaseColumn(col_idx) => {
718 base_row.get(*col_idx).cloned().unwrap_or(NULL_VALUE)
719 }
720 CompiledItem::WindowFunction(wf_name_lower) => window_value_map
721 .get(*wf_name_lower)
722 .and_then(|vals| vals.get(local_pos).cloned())
723 .unwrap_or(NULL_VALUE),
724 CompiledItem::Expression(eval) => eval.eval(base_row)?,
725 CompiledItem::ExpressionWithWindow(eval, wf_name_refs) => {
726 ext_values.clear();
727 ext_values.extend(base_row.iter().cloned());
728 for wf_name in wf_name_refs.iter() {
729 let wf_value = window_value_map
730 .get(*wf_name)
731 .and_then(|vals| vals.get(local_pos).cloned())
732 .unwrap_or(NULL_VALUE);
733 ext_values.push(wf_value);
734 }
735 let ext_row = Row::from_compact_vec(ext_values.clone());
736 eval.eval(&ext_row)?
737 }
738 };
739 values.push(value);
740 }
741 result_rows.push((result_row_id, Row::from_compact_vec(values)));
742 result_row_id += 1;
743 }
744 }
745
746 Ok(Box::new(ExecutorResult::new(result_columns, result_rows)))
747 }
748
749 pub fn execute_select_with_window_functions_lazy_partition(
753 &self,
754 stmt: &SelectStatement,
755 ctx: &ExecutionContext,
756 table: &dyn Table,
757 base_columns: &[String],
758 partition_col: &str,
759 limit: usize,
760 ) -> Result<Box<dyn QueryResult>> {
761 let window_functions = self.parse_window_functions(stmt, base_columns)?;
763 if window_functions.is_empty() {
764 return Err(Error::internal(
765 "No window functions found for lazy partition fetch",
766 ));
767 }
768
769 let col_index_map = build_column_index_map(base_columns);
771
772 let resolved_wfs: Vec<_> = window_functions
774 .iter()
775 .map(|wf| {
776 let is_agg = self.host.window_function_registry().is_aggregate(&wf.name);
777 let func = if is_agg {
778 None
779 } else {
780 self.host.window_function_registry().get_window(&wf.name)
781 };
782 (wf, func, is_agg)
783 })
784 .collect();
785
786 let select_items = self.parse_select_list_for_window(stmt, base_columns, &window_functions);
788 let result_columns: Vec<String> =
789 select_items.iter().map(|i| i.output_name.clone()).collect();
790
791 let partition_values = match table.get_partition_values(partition_col) {
793 Some(values) => values,
794 None => return Err(Error::internal("Failed to get partition values from index")),
795 };
796
797 let mut result_rows = RowVec::with_capacity(limit);
799 let mut result_row_id = 0i64;
800
801 for partition_value in partition_values {
802 if result_rows.len() >= limit {
803 break;
804 }
805
806 let partition_rows =
808 match table.get_rows_for_partition_value(partition_col, &partition_value) {
809 Some(rows) => rows,
810 None => continue,
811 };
812
813 if partition_rows.is_empty() {
814 continue;
815 }
816
817 let mut order_by_cache: Vec<(String, ColumnarOrderByValues)> = Vec::new();
819 for wf in &window_functions {
820 if !wf.order_by.is_empty() {
821 let cache_key = Self::order_by_cache_key(&wf.order_by);
822 let already_cached = order_by_cache.iter().any(|(key, _)| key == &cache_key);
823 if !already_cached {
824 let precomputed = self.precompute_order_by_values(
825 &wf.order_by,
826 &partition_rows,
827 base_columns,
828 &col_index_map,
829 ctx,
830 )?;
831 order_by_cache.push((cache_key, precomputed));
832 }
833 }
834 }
835
836 let row_indices: Vec<usize> = (0..partition_rows.len()).collect();
839 let mut window_value_map: StringMap<Vec<Value>> = StringMap::new();
840
841 for (wf, win_func_opt, is_agg) in &resolved_wfs {
842 let cache_key = Self::order_by_cache_key(&wf.order_by);
843 let precomputed_order_by = order_by_cache
844 .iter()
845 .find(|(key, _)| key == &cache_key)
846 .map(|(_, v)| v);
847
848 if *is_agg {
849 let agg_results = self.compute_aggregate_window_function(
850 wf,
851 &partition_rows,
852 base_columns,
853 &col_index_map,
854 ctx,
855 None,
856 precomputed_order_by,
857 )?;
858 window_value_map.insert(wf.column_name.to_lowercase(), agg_results);
860 } else if let Some(win_func) = win_func_opt {
861 let (sorted_values, sorted_indices) = self.compute_window_for_partition(
862 win_func.as_ref(),
863 wf,
864 &partition_rows,
865 row_indices.clone(),
866 precomputed_order_by,
867 base_columns,
868 &col_index_map,
869 ctx,
870 false,
871 )?;
872 let mut by_local = vec![NULL_VALUE; row_indices.len()];
874 for (pos, &local_idx) in sorted_indices.iter().enumerate() {
875 by_local[local_idx] = sorted_values[pos].clone();
876 }
877 window_value_map.insert(wf.column_name.to_lowercase(), by_local);
878 }
879 }
880
881 enum CompiledItemLazy<'a> {
883 BaseColumn(usize),
884 WindowFunction(&'a str),
885 Expression(ExpressionEval),
886 ExpressionWithWindow(ExpressionEval, Vec<&'a str>),
887 }
888 let num_items = select_items.len();
889 let mut compiled_items: Vec<CompiledItemLazy<'_>> = Vec::with_capacity(num_items);
890 for item in &select_items {
891 compiled_items.push(match &item.source {
892 SelectItemSource::BaseColumn(idx) => CompiledItemLazy::BaseColumn(*idx),
893 SelectItemSource::WindowFunction(name) => {
894 CompiledItemLazy::WindowFunction(name.as_str())
895 }
896 SelectItemSource::Expression(expr) => {
897 CompiledItemLazy::Expression(ExpressionEval::compile(expr, base_columns)?)
898 }
899 SelectItemSource::ExpressionWithWindow(expr, wf_names) => {
900 let mut counter = 0;
901 let transformed =
902 Self::replace_windows_with_identifiers(expr, wf_names, &mut counter);
903 let mut ext_columns = base_columns.to_vec();
904 for wf_name in wf_names {
905 ext_columns.push(wf_name.clone());
906 }
907 let eval = ExpressionEval::compile(&transformed, &ext_columns)?;
908 let name_refs: Vec<&str> = wf_names.iter().map(|s| s.as_str()).collect();
909 CompiledItemLazy::ExpressionWithWindow(eval, name_refs)
910 }
911 });
912 }
913
914 let mut ext_values: CompactVec<Value> =
915 CompactVec::with_capacity(partition_rows.first().map_or(0, |r| r.1.len()) + 1);
916
917 for (local_pos, &row_idx) in row_indices.iter().enumerate() {
919 if result_rows.len() >= limit {
920 break;
921 }
922
923 let (_, base_row) = &partition_rows[row_idx];
924 let mut values: CompactVec<Value> = CompactVec::with_capacity(num_items);
925
926 for ci in &mut compiled_items {
927 let val = match ci {
928 CompiledItemLazy::BaseColumn(col_idx) => {
929 base_row.get(*col_idx).cloned().unwrap_or(NULL_VALUE)
930 }
931 CompiledItemLazy::WindowFunction(wf_name_lower) => window_value_map
932 .get(*wf_name_lower)
933 .and_then(|vals| vals.get(local_pos).cloned())
934 .unwrap_or(NULL_VALUE),
935 CompiledItemLazy::Expression(eval) => eval.eval(base_row)?,
936 CompiledItemLazy::ExpressionWithWindow(eval, wf_name_refs) => {
937 ext_values.clear();
938 ext_values.extend(base_row.iter().cloned());
939 for wf_name in wf_name_refs.iter() {
940 let wf_value = window_value_map
941 .get(*wf_name)
942 .and_then(|vals| vals.get(local_pos).cloned())
943 .unwrap_or(NULL_VALUE);
944 ext_values.push(wf_value);
945 }
946 let ext_row = Row::from_compact_vec(ext_values.clone());
947 eval.eval(&ext_row)?
948 }
949 };
950 values.push(val);
951 }
952 result_rows.push((result_row_id, Row::from_compact_vec(values)));
953 result_row_id += 1;
954 }
955 }
956
957 Ok(Box::new(ExecutorResult::new(result_columns, result_rows)))
958 }
959}