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    /// Scalar subquery that returns a single value
74    /// Used in expressions like: WHERE col = (SELECT MAX(id) FROM table)
75    ScalarSubquery {
76        query: Box<SelectStatement>,
77    },
78    /// IN subquery that returns multiple values  
79    /// Used in expressions like: WHERE col IN (SELECT id FROM table WHERE ...)
80    InSubquery {
81        expr: Box<SqlExpression>,
82        subquery: Box<SelectStatement>,
83    },
84    /// NOT IN subquery
85    /// Used in expressions like: WHERE col NOT IN (SELECT id FROM table WHERE ...)
86    NotInSubquery {
87        expr: Box<SqlExpression>,
88        subquery: Box<SelectStatement>,
89    },
90}
91
92#[derive(Debug, Clone)]
93pub struct WhenBranch {
94    pub condition: Box<SqlExpression>,
95    pub result: Box<SqlExpression>,
96}
97
98// ===== WHERE Clause Types =====
99
100#[derive(Debug, Clone)]
101pub struct WhereClause {
102    pub conditions: Vec<Condition>,
103}
104
105#[derive(Debug, Clone)]
106pub struct Condition {
107    pub expr: SqlExpression,
108    pub connector: Option<LogicalOp>, // AND/OR connecting to next condition
109}
110
111#[derive(Debug, Clone)]
112pub enum LogicalOp {
113    And,
114    Or,
115}
116
117// ===== ORDER BY Types =====
118
119#[derive(Debug, Clone, PartialEq)]
120pub enum SortDirection {
121    Asc,
122    Desc,
123}
124
125#[derive(Debug, Clone)]
126pub struct OrderByColumn {
127    pub column: String,
128    pub direction: SortDirection,
129}
130
131// ===== Window Function Types =====
132
133/// Window frame bounds
134#[derive(Debug, Clone, PartialEq)]
135pub enum FrameBound {
136    UnboundedPreceding,
137    CurrentRow,
138    Preceding(i64),
139    Following(i64),
140    UnboundedFollowing,
141}
142
143/// Window frame unit (ROWS or RANGE)
144#[derive(Debug, Clone, PartialEq)]
145pub enum FrameUnit {
146    Rows,
147    Range,
148}
149
150/// Window frame specification
151#[derive(Debug, Clone)]
152pub struct WindowFrame {
153    pub unit: FrameUnit,
154    pub start: FrameBound,
155    pub end: Option<FrameBound>, // None means CURRENT ROW
156}
157
158#[derive(Debug, Clone)]
159pub struct WindowSpec {
160    pub partition_by: Vec<String>,
161    pub order_by: Vec<OrderByColumn>,
162    pub frame: Option<WindowFrame>, // Optional window frame
163}
164
165// ===== SELECT Statement Types =====
166
167/// Represents a SELECT item - either a simple column or a computed expression with alias
168#[derive(Debug, Clone)]
169pub enum SelectItem {
170    /// Simple column reference: "`column_name`"
171    Column(String),
172    /// Computed expression with alias: "expr AS alias"
173    Expression { expr: SqlExpression, alias: String },
174    /// Star selector: "*"
175    Star,
176}
177
178#[derive(Debug, Clone)]
179pub struct SelectStatement {
180    pub distinct: bool,                // SELECT DISTINCT flag
181    pub columns: Vec<String>,          // Keep for backward compatibility, will be deprecated
182    pub select_items: Vec<SelectItem>, // New field for computed expressions
183    pub from_table: Option<String>,
184    pub from_subquery: Option<Box<SelectStatement>>, // Subquery in FROM clause
185    pub from_function: Option<TableFunction>,        // Table function like RANGE() in FROM clause
186    pub from_alias: Option<String>,                  // Alias for subquery (AS name)
187    pub joins: Vec<JoinClause>,                      // JOIN clauses
188    pub where_clause: Option<WhereClause>,
189    pub order_by: Option<Vec<OrderByColumn>>,
190    pub group_by: Option<Vec<SqlExpression>>, // Changed from Vec<String> to support expressions
191    pub having: Option<SqlExpression>,        // HAVING clause for post-aggregation filtering
192    pub limit: Option<usize>,
193    pub offset: Option<usize>,
194    pub ctes: Vec<CTE>, // Common Table Expressions (WITH clause)
195}
196
197// ===== Table and Join Types =====
198
199/// Table function that generates virtual tables
200#[derive(Debug, Clone)]
201pub enum TableFunction {
202    Range {
203        start: SqlExpression,
204        end: SqlExpression,
205        step: Option<SqlExpression>,
206    },
207}
208
209/// Common Table Expression (CTE) structure
210#[derive(Debug, Clone)]
211pub struct CTE {
212    pub name: String,
213    pub column_list: Option<Vec<String>>, // Optional column list: WITH t(col1, col2) AS ...
214    pub cte_type: CTEType,
215}
216
217/// Type of CTE - standard SQL or WEB fetch
218#[derive(Debug, Clone)]
219pub enum CTEType {
220    Standard(SelectStatement),
221    Web(WebCTESpec),
222}
223
224/// Specification for WEB CTEs
225#[derive(Debug, Clone)]
226pub struct WebCTESpec {
227    pub url: String,
228    pub format: Option<DataFormat>,     // CSV, JSON, or auto-detect
229    pub headers: Vec<(String, String)>, // HTTP headers
230    pub cache_seconds: Option<u64>,     // Cache duration
231}
232
233/// Data format for WEB CTEs
234#[derive(Debug, Clone)]
235pub enum DataFormat {
236    CSV,
237    JSON,
238    Auto, // Auto-detect from Content-Type or extension
239}
240
241/// Table source - either a file/table name or a derived table (subquery/CTE)
242#[derive(Debug, Clone)]
243pub enum TableSource {
244    Table(String), // Regular table from CSV/JSON
245    DerivedTable {
246        // Both CTE and subquery
247        query: Box<SelectStatement>,
248        alias: String, // Required alias for subqueries
249    },
250}
251
252/// Join type enumeration
253#[derive(Debug, Clone, PartialEq)]
254pub enum JoinType {
255    Inner,
256    Left,
257    Right,
258    Full,
259    Cross,
260}
261
262/// Join operator for join conditions
263#[derive(Debug, Clone, PartialEq)]
264pub enum JoinOperator {
265    Equal,
266    NotEqual,
267    LessThan,
268    GreaterThan,
269    LessThanOrEqual,
270    GreaterThanOrEqual,
271}
272
273/// Join condition - initially just column equality
274#[derive(Debug, Clone)]
275pub struct JoinCondition {
276    pub left_column: String, // Column from left table (can include table prefix)
277    pub operator: JoinOperator, // Join operator (initially just Equal)
278    pub right_column: String, // Column from right table (can include table prefix)
279}
280
281/// Join clause structure
282#[derive(Debug, Clone)]
283pub struct JoinClause {
284    pub join_type: JoinType,
285    pub table: TableSource,       // The table being joined
286    pub alias: Option<String>,    // Optional alias for the joined table
287    pub condition: JoinCondition, // ON condition
288}