Skip to main content

oxisql_parse/
plan.rs

1//! Logical plan type definitions for OxiSQL.
2//!
3//! This module defines the AST-level relational algebra types produced by the
4//! planner.  All types are re-exported from the crate root.
5
6use crate::optimizer::JoinAlgoHint;
7
8// ── Logical Plan ─────────────────────────────────────────────────────────────
9
10/// AST-level logical query plan produced by [`crate::plan_statement`].
11///
12/// Each variant represents a relational algebra operator.  The tree is
13/// built bottom-up: leaf nodes (e.g. `Scan`) are wrapped by operator nodes
14/// (`Filter`, `Project`, …) as query features are encountered.
15#[derive(Debug, Clone)]
16pub enum LogicalPlan {
17    /// Table scan.  `alias` is the `AS` alias, if any.
18    Scan {
19        /// The fully-qualified table name as it appears in the query.
20        table: String,
21        /// Optional alias (`AS x`).
22        alias: Option<String>,
23        /// Optional row-count cap injected by the optimizer's limit push-through
24        /// pass.  `None` means the scan is unbounded.
25        limit: Option<usize>,
26    },
27    /// Row filter (`WHERE`).
28    Filter {
29        /// The plan being filtered.
30        input: Box<LogicalPlan>,
31        /// The `WHERE` expression rendered as a string.
32        predicate: String,
33    },
34    /// Column projection (`SELECT col1, col2, …`).
35    Project {
36        /// The plan whose rows are projected.
37        input: Box<LogicalPlan>,
38        /// The projected column expressions as strings.
39        columns: Vec<String>,
40    },
41    /// Binary join of two inputs.
42    Join {
43        /// Left input.
44        left: Box<LogicalPlan>,
45        /// Right input.
46        right: Box<LogicalPlan>,
47        /// The `ON` expression rendered as a string.
48        on: String,
49        /// The join type (INNER, LEFT, RIGHT, FULL, CROSS).
50        join_type: JoinType,
51        /// Algorithm hint set by [`crate::optimizer::JoinAlgorithmPass`].
52        algo_hint: Option<JoinAlgoHint>,
53    },
54    /// Aggregation (`GROUP BY` / aggregate functions).
55    Aggregate {
56        /// The plan whose rows are aggregated.
57        input: Box<LogicalPlan>,
58        /// `GROUP BY` expressions rendered as strings.
59        group_by: Vec<String>,
60        /// Aggregate function expressions rendered as strings.
61        aggregates: Vec<String>,
62    },
63    /// Row ordering (`ORDER BY`).
64    Sort {
65        /// The plan whose rows are sorted.
66        input: Box<LogicalPlan>,
67        /// The sort key expressions.
68        order_by: Vec<SortExpr>,
69    },
70    /// Row count / offset restriction (`LIMIT … OFFSET …`).
71    Limit {
72        /// The plan being limited.
73        input: Box<LogicalPlan>,
74        /// Maximum number of rows, if specified.
75        count: Option<u64>,
76        /// Number of rows to skip, if specified.
77        offset: Option<u64>,
78    },
79    /// Constant row source (`INSERT … VALUES …`).
80    Values {
81        /// Column names from the INSERT column list.
82        columns: Vec<String>,
83        /// Number of value rows.
84        rows: usize,
85    },
86    /// Placeholder for statements that produce no relational plan.
87    Empty,
88    /// A SQL set operation: `UNION`, `INTERSECT`, or `EXCEPT`.
89    SetOp {
90        /// The set-operation kind.
91        op: SetOpType,
92        /// `true` for `UNION ALL` / `INTERSECT ALL` / `EXCEPT ALL`.
93        all: bool,
94        /// Left input plan.
95        left: Box<LogicalPlan>,
96        /// Right input plan.
97        right: Box<LogicalPlan>,
98    },
99    /// A CTE definition node.
100    ///
101    /// The `query` field is the plan for the CTE's own defining body (`AS (...)`).
102    /// The query that *uses* this CTE is built by the surrounding planner; this
103    /// variant retains only the CTE definition itself.
104    Cte {
105        /// The CTE name as introduced before the `AS` keyword.
106        name: String,
107        /// Plan for the CTE-defining sub-query (`AS ( ... )`).
108        query: Box<LogicalPlan>,
109        /// `true` when the entire `WITH` clause was `WITH RECURSIVE`.
110        recursive: bool,
111    },
112    /// Reference to a previously defined CTE by name.
113    CteRef {
114        /// The CTE name being referenced.
115        name: String,
116    },
117    /// Window-function layer sitting over a base plan.
118    Window {
119        /// The input plan over which windows are computed.
120        input: Box<LogicalPlan>,
121        /// The window functions defined in the SELECT projection.
122        functions: Vec<WindowFunctionDef>,
123    },
124    /// A scalar subquery that returns a single value (used in SELECT or WHERE).
125    Subquery {
126        /// The inner query plan.
127        query: Box<LogicalPlan>,
128        /// Optional alias applied to the subquery expression.
129        alias: Option<String>,
130    },
131    /// `EXISTS (subquery)` — used in WHERE predicates.
132    Exists {
133        /// The inner subquery plan.
134        subquery: Box<LogicalPlan>,
135        /// `true` when the expression is `NOT EXISTS`.
136        negated: bool,
137    },
138    /// `expr IN (subquery)` — used in WHERE predicates.
139    InSubquery {
140        /// The expression being tested (e.g. `"col1"`).
141        expr: String,
142        /// The inner subquery plan.
143        subquery: Box<LogicalPlan>,
144        /// `true` when the expression is `NOT IN`.
145        negated: bool,
146    },
147}
148
149/// Set-operation kind.
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum SetOpType {
152    /// `UNION`
153    Union,
154    /// `INTERSECT`
155    Intersect,
156    /// `EXCEPT` (or `MINUS`)
157    Except,
158}
159
160/// A single window-function definition extracted from a SELECT projection.
161#[derive(Debug, Clone, PartialEq)]
162pub struct WindowFunctionDef {
163    /// The function name (e.g. `ROW_NUMBER`, `RANK`).
164    pub name: String,
165    /// The function arguments rendered as strings.
166    pub args: Vec<String>,
167    /// `PARTITION BY` expressions rendered as strings.
168    pub partition_by: Vec<String>,
169    /// `ORDER BY` keys.
170    pub order_by: Vec<SortExpr>,
171    /// The alias applied to the expression in the projection.
172    pub alias: String,
173}
174
175/// Join algorithm / semantic type.
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub enum JoinType {
178    /// `INNER JOIN` — only matching rows.
179    Inner,
180    /// `LEFT [OUTER] JOIN` — all rows from the left side.
181    Left,
182    /// `RIGHT [OUTER] JOIN` — all rows from the right side.
183    Right,
184    /// `FULL [OUTER] JOIN` — all rows from both sides.
185    Full,
186    /// `CROSS JOIN` — cartesian product.
187    Cross,
188}
189
190/// A single `ORDER BY` sort key.
191#[derive(Debug, Clone, PartialEq)]
192pub struct SortExpr {
193    /// The column / expression being sorted.
194    pub column: String,
195    /// `true` for ascending (`ASC`), `false` for descending (`DESC`).
196    pub ascending: bool,
197}