sql_cli/sql/parser/
ast.rs

1//! Abstract Syntax Tree (AST) definitions for SQL queries
2//!
3//! This module contains all the data structures that represent
4//! the parsed SQL query structure.
5
6// ===== Expression Types =====
7
8#[derive(Debug, Clone)]
9pub enum SqlExpression {
10    Column(String),
11    StringLiteral(String),
12    NumberLiteral(String),
13    BooleanLiteral(bool),
14    Null, // NULL literal
15    DateTimeConstructor {
16        year: i32,
17        month: u32,
18        day: u32,
19        hour: Option<u32>,
20        minute: Option<u32>,
21        second: Option<u32>,
22    },
23    DateTimeToday {
24        hour: Option<u32>,
25        minute: Option<u32>,
26        second: Option<u32>,
27    },
28    MethodCall {
29        object: String,
30        method: String,
31        args: Vec<SqlExpression>,
32    },
33    ChainedMethodCall {
34        base: Box<SqlExpression>,
35        method: String,
36        args: Vec<SqlExpression>,
37    },
38    FunctionCall {
39        name: String,
40        args: Vec<SqlExpression>,
41        distinct: bool, // For COUNT(DISTINCT col), SUM(DISTINCT col), etc.
42    },
43    WindowFunction {
44        name: String,
45        args: Vec<SqlExpression>,
46        window_spec: WindowSpec,
47    },
48    BinaryOp {
49        left: Box<SqlExpression>,
50        op: String,
51        right: Box<SqlExpression>,
52    },
53    InList {
54        expr: Box<SqlExpression>,
55        values: Vec<SqlExpression>,
56    },
57    NotInList {
58        expr: Box<SqlExpression>,
59        values: Vec<SqlExpression>,
60    },
61    Between {
62        expr: Box<SqlExpression>,
63        lower: Box<SqlExpression>,
64        upper: Box<SqlExpression>,
65    },
66    Not {
67        expr: Box<SqlExpression>,
68    },
69    CaseExpression {
70        when_branches: Vec<WhenBranch>,
71        else_branch: Option<Box<SqlExpression>>,
72    },
73    SimpleCaseExpression {
74        expr: Box<SqlExpression>,
75        when_branches: Vec<SimpleWhenBranch>,
76        else_branch: Option<Box<SqlExpression>>,
77    },
78    /// Scalar subquery that returns a single value
79    /// Used in expressions like: WHERE col = (SELECT MAX(id) FROM table)
80    ScalarSubquery {
81        query: Box<SelectStatement>,
82    },
83    /// IN subquery that returns multiple values  
84    /// Used in expressions like: WHERE col IN (SELECT id FROM table WHERE ...)
85    InSubquery {
86        expr: Box<SqlExpression>,
87        subquery: Box<SelectStatement>,
88    },
89    /// NOT IN subquery
90    /// Used in expressions like: WHERE col NOT IN (SELECT id FROM table WHERE ...)
91    NotInSubquery {
92        expr: Box<SqlExpression>,
93        subquery: Box<SelectStatement>,
94    },
95}
96
97#[derive(Debug, Clone)]
98pub struct WhenBranch {
99    pub condition: Box<SqlExpression>,
100    pub result: Box<SqlExpression>,
101}
102
103#[derive(Debug, Clone)]
104pub struct SimpleWhenBranch {
105    pub value: Box<SqlExpression>,
106    pub result: Box<SqlExpression>,
107}
108
109// ===== WHERE Clause Types =====
110
111#[derive(Debug, Clone)]
112pub struct WhereClause {
113    pub conditions: Vec<Condition>,
114}
115
116#[derive(Debug, Clone)]
117pub struct Condition {
118    pub expr: SqlExpression,
119    pub connector: Option<LogicalOp>, // AND/OR connecting to next condition
120}
121
122#[derive(Debug, Clone)]
123pub enum LogicalOp {
124    And,
125    Or,
126}
127
128// ===== ORDER BY Types =====
129
130#[derive(Debug, Clone, PartialEq)]
131pub enum SortDirection {
132    Asc,
133    Desc,
134}
135
136#[derive(Debug, Clone)]
137pub struct OrderByColumn {
138    pub column: String,
139    pub direction: SortDirection,
140}
141
142// ===== Window Function Types =====
143
144/// Window frame bounds
145#[derive(Debug, Clone, PartialEq)]
146pub enum FrameBound {
147    UnboundedPreceding,
148    CurrentRow,
149    Preceding(i64),
150    Following(i64),
151    UnboundedFollowing,
152}
153
154/// Window frame unit (ROWS or RANGE)
155#[derive(Debug, Clone, PartialEq)]
156pub enum FrameUnit {
157    Rows,
158    Range,
159}
160
161/// Window frame specification
162#[derive(Debug, Clone)]
163pub struct WindowFrame {
164    pub unit: FrameUnit,
165    pub start: FrameBound,
166    pub end: Option<FrameBound>, // None means CURRENT ROW
167}
168
169#[derive(Debug, Clone)]
170pub struct WindowSpec {
171    pub partition_by: Vec<String>,
172    pub order_by: Vec<OrderByColumn>,
173    pub frame: Option<WindowFrame>, // Optional window frame
174}
175
176// ===== SELECT Statement Types =====
177
178/// Represents a SELECT item - either a simple column or a computed expression with alias
179#[derive(Debug, Clone)]
180pub enum SelectItem {
181    /// Simple column reference: "`column_name`"
182    Column(String),
183    /// Computed expression with alias: "expr AS alias"
184    Expression { expr: SqlExpression, alias: String },
185    /// Star selector: "*"
186    Star,
187}
188
189#[derive(Debug, Clone)]
190pub struct SelectStatement {
191    pub distinct: bool,                // SELECT DISTINCT flag
192    pub columns: Vec<String>,          // Keep for backward compatibility, will be deprecated
193    pub select_items: Vec<SelectItem>, // New field for computed expressions
194    pub from_table: Option<String>,
195    pub from_subquery: Option<Box<SelectStatement>>, // Subquery in FROM clause
196    pub from_function: Option<TableFunction>,        // Table function like RANGE() in FROM clause
197    pub from_alias: Option<String>,                  // Alias for subquery (AS name)
198    pub joins: Vec<JoinClause>,                      // JOIN clauses
199    pub where_clause: Option<WhereClause>,
200    pub order_by: Option<Vec<OrderByColumn>>,
201    pub group_by: Option<Vec<SqlExpression>>, // Changed from Vec<String> to support expressions
202    pub having: Option<SqlExpression>,        // HAVING clause for post-aggregation filtering
203    pub limit: Option<usize>,
204    pub offset: Option<usize>,
205    pub ctes: Vec<CTE>, // Common Table Expressions (WITH clause)
206}
207
208// ===== Table and Join Types =====
209
210/// Table function that generates virtual tables
211#[derive(Debug, Clone)]
212pub enum TableFunction {
213    Range {
214        start: SqlExpression,
215        end: SqlExpression,
216        step: Option<SqlExpression>,
217    },
218    Split {
219        text: SqlExpression,
220        delimiter: Option<SqlExpression>,
221    },
222    Generator {
223        name: String,
224        args: Vec<SqlExpression>,
225    },
226}
227
228/// Common Table Expression (CTE) structure
229#[derive(Debug, Clone)]
230pub struct CTE {
231    pub name: String,
232    pub column_list: Option<Vec<String>>, // Optional column list: WITH t(col1, col2) AS ...
233    pub cte_type: CTEType,
234}
235
236/// Type of CTE - standard SQL or WEB fetch
237#[derive(Debug, Clone)]
238pub enum CTEType {
239    Standard(SelectStatement),
240    Web(WebCTESpec),
241}
242
243/// Specification for WEB CTEs
244#[derive(Debug, Clone)]
245pub struct WebCTESpec {
246    pub url: String,
247    pub format: Option<DataFormat>,     // CSV, JSON, or auto-detect
248    pub headers: Vec<(String, String)>, // HTTP headers
249    pub cache_seconds: Option<u64>,     // Cache duration
250}
251
252/// Data format for WEB CTEs
253#[derive(Debug, Clone)]
254pub enum DataFormat {
255    CSV,
256    JSON,
257    Auto, // Auto-detect from Content-Type or extension
258}
259
260/// Table source - either a file/table name or a derived table (subquery/CTE)
261#[derive(Debug, Clone)]
262pub enum TableSource {
263    Table(String), // Regular table from CSV/JSON
264    DerivedTable {
265        // Both CTE and subquery
266        query: Box<SelectStatement>,
267        alias: String, // Required alias for subqueries
268    },
269}
270
271/// Join type enumeration
272#[derive(Debug, Clone, PartialEq)]
273pub enum JoinType {
274    Inner,
275    Left,
276    Right,
277    Full,
278    Cross,
279}
280
281/// Join operator for join conditions
282#[derive(Debug, Clone, PartialEq)]
283pub enum JoinOperator {
284    Equal,
285    NotEqual,
286    LessThan,
287    GreaterThan,
288    LessThanOrEqual,
289    GreaterThanOrEqual,
290}
291
292/// Join condition - initially just column equality
293#[derive(Debug, Clone)]
294pub struct JoinCondition {
295    pub left_column: String, // Column from left table (can include table prefix)
296    pub operator: JoinOperator, // Join operator (initially just Equal)
297    pub right_column: String, // Column from right table (can include table prefix)
298}
299
300/// Join clause structure
301#[derive(Debug, Clone)]
302pub struct JoinClause {
303    pub join_type: JoinType,
304    pub table: TableSource,       // The table being joined
305    pub alias: Option<String>,    // Optional alias for the joined table
306    pub condition: JoinCondition, // ON condition
307}