qail_core/ast/
operators.rs

1use serde::{Deserialize, Serialize};
2
3/// The action type (SQL operation).
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5pub enum Action {
6    /// SELECT query
7    Get,
8    /// UPDATE query  
9    Set,
10    Del,
11    /// INSERT query
12    Add,
13    Gen,
14    Make,
15    Drop,
16    Mod,
17    Over,
18    With,
19    Index,
20    DropIndex,
21    Alter,
22    /// ALTER TABLE DROP COLUMN
23    AlterDrop,
24    /// ALTER TABLE ALTER COLUMN TYPE
25    AlterType,
26    // Transactions
27    TxnStart,
28    TxnCommit,
29    TxnRollback,
30    Put,
31    DropCol,
32    RenameCol,
33    // Additional clauses
34    /// JSON_TABLE - convert JSON to relational rows
35    JsonTable,
36    /// COPY TO STDOUT - bulk export data (AST-native)
37    Export,
38    /// TRUNCATE TABLE - fast delete all rows
39    Truncate,
40    /// EXPLAIN - query plan analysis
41    Explain,
42    /// EXPLAIN ANALYZE - execute and analyze query plan
43    ExplainAnalyze,
44    /// LOCK TABLE - explicit table locking
45    Lock,
46    CreateMaterializedView,
47    RefreshMaterializedView,
48    DropMaterializedView,
49    // Pub/Sub (LISTEN/NOTIFY)
50    /// LISTEN channel - subscribe to notifications
51    Listen,
52    /// NOTIFY channel, 'payload' - send notification
53    Notify,
54    /// UNLISTEN channel - unsubscribe from notifications
55    Unlisten,
56    // Savepoints
57    Savepoint,
58    ReleaseSavepoint,
59    RollbackToSavepoint,
60}
61
62impl std::fmt::Display for Action {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        match self {
65            Action::Get => write!(f, "GET"),
66            Action::Set => write!(f, "SET"),
67            Action::Del => write!(f, "DEL"),
68            Action::Add => write!(f, "ADD"),
69            Action::Gen => write!(f, "GEN"),
70            Action::Make => write!(f, "MAKE"),
71            Action::Drop => write!(f, "DROP"),
72            Action::Mod => write!(f, "MOD"),
73            Action::Over => write!(f, "OVER"),
74            Action::With => write!(f, "WITH"),
75            Action::Index => write!(f, "INDEX"),
76            Action::DropIndex => write!(f, "DROP_INDEX"),
77            Action::Alter => write!(f, "ALTER"),
78            Action::AlterDrop => write!(f, "ALTER_DROP"),
79            Action::AlterType => write!(f, "ALTER_TYPE"),
80            Action::TxnStart => write!(f, "TXN_START"),
81            Action::TxnCommit => write!(f, "TXN_COMMIT"),
82            Action::TxnRollback => write!(f, "TXN_ROLLBACK"),
83            Action::Put => write!(f, "PUT"),
84            Action::DropCol => write!(f, "DROP_COL"),
85            Action::RenameCol => write!(f, "RENAME_COL"),
86            Action::JsonTable => write!(f, "JSON_TABLE"),
87            Action::Export => write!(f, "EXPORT"),
88            Action::Truncate => write!(f, "TRUNCATE"),
89            Action::Explain => write!(f, "EXPLAIN"),
90            Action::ExplainAnalyze => write!(f, "EXPLAIN_ANALYZE"),
91            Action::Lock => write!(f, "LOCK"),
92            Action::CreateMaterializedView => write!(f, "CREATE_MATERIALIZED_VIEW"),
93            Action::RefreshMaterializedView => write!(f, "REFRESH_MATERIALIZED_VIEW"),
94            Action::DropMaterializedView => write!(f, "DROP_MATERIALIZED_VIEW"),
95            Action::Listen => write!(f, "LISTEN"),
96            Action::Notify => write!(f, "NOTIFY"),
97            Action::Unlisten => write!(f, "UNLISTEN"),
98            Action::Savepoint => write!(f, "SAVEPOINT"),
99            Action::ReleaseSavepoint => write!(f, "RELEASE_SAVEPOINT"),
100            Action::RollbackToSavepoint => write!(f, "ROLLBACK_TO_SAVEPOINT"),
101        }
102    }
103}
104
105/// Logical operator between conditions.
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
107pub enum LogicalOp {
108    #[default]
109    And,
110    Or,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
114pub enum SortOrder {
115    Asc,
116    Desc,
117    AscNullsFirst,
118    AscNullsLast,
119    DescNullsFirst,
120    DescNullsLast,
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
124pub enum Operator {
125    Eq,
126    /// Not equal (!=, <>)
127    Ne,
128    /// Greater than (>)
129    Gt,
130    /// Greater than or equal (>=)
131    Gte,
132    /// Less than (<)
133    Lt,
134    /// Less than or equal (<=)  
135    Lte,
136    Fuzzy,
137    In,
138    NotIn,
139    IsNull,
140    IsNotNull,
141    Contains,
142    KeyExists,
143    /// JSON_EXISTS - check if path exists (Postgres 17+)
144    JsonExists,
145    /// JSON_QUERY - extract JSON object/array at path (Postgres 17+)
146    JsonQuery,
147    /// JSON_VALUE - extract scalar value at path (Postgres 17+)
148    JsonValue,
149    Like,
150    NotLike,
151    /// ILIKE case-insensitive pattern match (Postgres)
152    ILike,
153    /// NOT ILIKE case-insensitive pattern match (Postgres)
154    NotILike,
155    /// BETWEEN x AND y - range check (value stored as Value::Array with 2 elements)
156    Between,
157    NotBetween,
158    /// EXISTS (subquery) - check if subquery returns any rows
159    Exists,
160    NotExists,
161    /// Regular expression match (~ in Postgres)
162    Regex,
163    /// Case-insensitive regex (~* in Postgres)
164    RegexI,
165    SimilarTo,
166    ContainedBy,
167    /// Array overlap (&&)
168    Overlaps,
169}
170
171impl Operator {
172    /// For simple operators, returns the symbol directly.
173    /// For complex operators (BETWEEN, EXISTS), returns the keyword.
174    pub fn sql_symbol(&self) -> &'static str {
175        match self {
176            Operator::Eq => "=",
177            Operator::Ne => "!=",
178            Operator::Gt => ">",
179            Operator::Gte => ">=",
180            Operator::Lt => "<",
181            Operator::Lte => "<=",
182            Operator::Fuzzy => "ILIKE",
183            Operator::In => "IN",
184            Operator::NotIn => "NOT IN",
185            Operator::IsNull => "IS NULL",
186            Operator::IsNotNull => "IS NOT NULL",
187            Operator::Contains => "@>",
188            Operator::KeyExists => "?",
189            Operator::JsonExists => "JSON_EXISTS",
190            Operator::JsonQuery => "JSON_QUERY",
191            Operator::JsonValue => "JSON_VALUE",
192            Operator::Like => "LIKE",
193            Operator::NotLike => "NOT LIKE",
194            Operator::ILike => "ILIKE",
195            Operator::NotILike => "NOT ILIKE",
196            Operator::Between => "BETWEEN",
197            Operator::NotBetween => "NOT BETWEEN",
198            Operator::Exists => "EXISTS",
199            Operator::NotExists => "NOT EXISTS",
200            Operator::Regex => "~",
201            Operator::RegexI => "~*",
202            Operator::SimilarTo => "SIMILAR TO",
203            Operator::ContainedBy => "<@",
204            Operator::Overlaps => "&&",
205        }
206    }
207
208    /// IS NULL, IS NOT NULL, EXISTS, NOT EXISTS don't need values.
209    pub fn needs_value(&self) -> bool {
210        !matches!(
211            self,
212            Operator::IsNull | Operator::IsNotNull | Operator::Exists | Operator::NotExists
213        )
214    }
215
216    pub fn is_simple_binary(&self) -> bool {
217        matches!(
218            self,
219            Operator::Eq
220                | Operator::Ne
221                | Operator::Gt
222                | Operator::Gte
223                | Operator::Lt
224                | Operator::Lte
225                | Operator::Like
226                | Operator::NotLike
227                | Operator::ILike
228                | Operator::NotILike
229        )
230    }
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
234pub enum AggregateFunc {
235    Count,
236    Sum,
237    Avg,
238    Min,
239    Max,
240    /// ARRAY_AGG - collect values into array
241    ArrayAgg,
242    /// STRING_AGG - concatenate strings with delimiter
243    StringAgg,
244    /// JSON_AGG - aggregate values as JSON array
245    JsonAgg,
246    /// JSONB_AGG - aggregate values as JSONB array
247    JsonbAgg,
248    /// BOOL_AND - logical AND of all values
249    BoolAnd,
250    /// BOOL_OR - logical OR of all values
251    BoolOr,
252}
253
254impl std::fmt::Display for AggregateFunc {
255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        match self {
257            AggregateFunc::Count => write!(f, "COUNT"),
258            AggregateFunc::Sum => write!(f, "SUM"),
259            AggregateFunc::Avg => write!(f, "AVG"),
260            AggregateFunc::Min => write!(f, "MIN"),
261            AggregateFunc::Max => write!(f, "MAX"),
262            AggregateFunc::ArrayAgg => write!(f, "ARRAY_AGG"),
263            AggregateFunc::StringAgg => write!(f, "STRING_AGG"),
264            AggregateFunc::JsonAgg => write!(f, "JSON_AGG"),
265            AggregateFunc::JsonbAgg => write!(f, "JSONB_AGG"),
266            AggregateFunc::BoolAnd => write!(f, "BOOL_AND"),
267            AggregateFunc::BoolOr => write!(f, "BOOL_OR"),
268        }
269    }
270}
271
272/// Join Type
273#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
274pub enum JoinKind {
275    Inner,
276    Left,
277    Right,
278    Lateral,
279    Full,
280    Cross,
281}
282
283/// Set operation type for combining queries
284#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
285pub enum SetOp {
286    Union,
287    UnionAll,
288    Intersect,
289    Except,
290}
291
292#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
293pub enum ModKind {
294    Add,
295    Drop,
296}
297
298/// GROUP BY mode for advanced aggregations
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
300pub enum GroupByMode {
301    /// Standard GROUP BY
302    #[default]
303    Simple,
304    /// ROLLUP - hierarchical subtotals
305    Rollup,
306    /// CUBE - all combinations of subtotals
307    Cube,
308}
309
310/// Row locking mode for SELECT...FOR UPDATE/SHARE
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
312pub enum LockMode {
313    /// FOR UPDATE - exclusive lock
314    Update,
315    /// FOR NO KEY UPDATE - weaker exclusive lock
316    NoKeyUpdate,
317    /// FOR SHARE - shared lock
318    Share,
319    /// FOR KEY SHARE - weakest shared lock
320    KeyShare,
321}
322
323/// OVERRIDING clause for INSERT with GENERATED columns
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
325pub enum OverridingKind {
326    /// OVERRIDING SYSTEM VALUE - override GENERATED ALWAYS columns
327    SystemValue,
328    /// OVERRIDING USER VALUE - override GENERATED BY DEFAULT columns
329    UserValue,
330}
331
332/// TABLESAMPLE sampling method
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
334pub enum SampleMethod {
335    /// BERNOULLI - each row has independent probability
336    Bernoulli,
337    /// SYSTEM - faster but less random (block-level sampling)
338    System,
339}