MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / convert_window_frame

Function convert_window_frame

nodedb-sql/src/planner/window/frame.rs:22–66  ·  view source on GitHub ↗

Convert a sqlparser `WindowFrame` to the executor's `WindowFrame`. `order_by` is needed for semantic validation: - GROUPS without ORDER BY is invalid (PostgreSQL parity). - RANGE with numeric offsets (Preceding(N)/Following(N)) requires a single numeric ORDER BY column; without one the semantics are undefined and we reject at plan time.

(
    frame: &ast::WindowFrame,
    order_by: &[SortKey],
)

Source from the content-addressed store, hash-verified

20/// numeric ORDER BY column; without one the semantics are undefined and we
21/// reject at plan time.
22pub(super) fn convert_window_frame(
23 frame: &ast::WindowFrame,
24 order_by: &[SortKey],
25) -> Result<WindowFrame> {
26 let mode = match frame.units {
27 ast::WindowFrameUnits::Rows => "rows",
28 ast::WindowFrameUnits::Range => "range",
29 ast::WindowFrameUnits::Groups => {
30 if order_by.is_empty() {
31 return Err(SqlError::InvalidWindowFrame {
32 detail: "GROUPS mode requires an ORDER BY clause in the window specification"
33 .into(),
34 });
35 }
36 "groups"
37 }
38 };
39
40 let start = convert_window_frame_bound(&frame.start_bound)?;
41 let end = match &frame.end_bound {
42 Some(b) => convert_window_frame_bound(b)?,
43 None => FrameBound::CurrentRow,
44 };
45
46 // RANGE with numeric offsets requires a single-column ORDER BY so we can
47 // compare values. Reject if ORDER BY is absent or has more than one key
48 // (multi-key RANGE offsets are undefined in SQL standards).
49 if mode == "range" {
50 let needs_order = matches!(start, FrameBound::Preceding(n) if n > 0)
51 || matches!(start, FrameBound::Following(n) if n > 0)
52 || matches!(end, FrameBound::Preceding(n) if n > 0)
53 || matches!(end, FrameBound::Following(n) if n > 0);
54 if needs_order && order_by.len() != 1 {
55 return Err(SqlError::InvalidWindowFrame {
56 detail: "RANGE with numeric PRECEDING/FOLLOWING offset requires exactly one ORDER BY column".into(),
57 });
58 }
59 }
60
61 Ok(WindowFrame {
62 mode: mode.into(),
63 start,
64 end,
65 })
66}
67
68fn convert_window_frame_bound(bound: &ast::WindowFrameBound) -> Result<FrameBound> {
69 match bound {

Callers 1

convert_window_specFunction · 0.85

Calls 3

is_emptyMethod · 0.45
lenMethod · 0.45

Tested by

no test coverage detected