Generate a sort key for a given window expr's partition_by and order_by expr
(
partition_by: &[Expr],
order_by: &[Sort],
)
| 516 | |
| 517 | /// Generate a sort key for a given window expr's partition_by and order_by expr |
| 518 | pub fn generate_sort_key( |
| 519 | partition_by: &[Expr], |
| 520 | order_by: &[Sort], |
| 521 | ) -> Result<WindowSortKey> { |
| 522 | let normalized_order_by_keys = order_by |
| 523 | .iter() |
| 524 | .map(|e| { |
| 525 | let Sort { expr, .. } = e; |
| 526 | Sort::new(expr.clone(), true, false) |
| 527 | }) |
| 528 | .collect::<Vec<_>>(); |
| 529 | |
| 530 | let mut final_sort_keys = vec![]; |
| 531 | let mut is_partition_flag = vec![]; |
| 532 | partition_by.iter().for_each(|e| { |
| 533 | // By default, create sort key with ASC is true and NULLS LAST to be consistent with |
| 534 | // PostgreSQL's rule: https://www.postgresql.org/docs/current/queries-order.html |
| 535 | let e = e.clone().sort(true, false); |
| 536 | if let Some(pos) = normalized_order_by_keys.iter().position(|key| key.eq(&e)) { |
| 537 | let order_by_key = &order_by[pos]; |
| 538 | if !final_sort_keys.contains(order_by_key) { |
| 539 | final_sort_keys.push(order_by_key.clone()); |
| 540 | is_partition_flag.push(true); |
| 541 | } |
| 542 | } else if !final_sort_keys.contains(&e) { |
| 543 | final_sort_keys.push(e); |
| 544 | is_partition_flag.push(true); |
| 545 | } |
| 546 | }); |
| 547 | |
| 548 | order_by.iter().for_each(|e| { |
| 549 | if !final_sort_keys.contains(e) { |
| 550 | final_sort_keys.push(e.clone()); |
| 551 | is_partition_flag.push(false); |
| 552 | } |
| 553 | }); |
| 554 | let res = final_sort_keys |
| 555 | .into_iter() |
| 556 | .zip(is_partition_flag) |
| 557 | .collect::<Vec<_>>(); |
| 558 | Ok(res) |
| 559 | } |
| 560 | |
| 561 | /// Compare the sort expr as PostgreSQL's common_prefix_cmp(): |
| 562 | /// <https://github.com/postgres/postgres/blob/master/src/backend/optimizer/plan/planner.c> |
searching dependent graphs…