Skip to main content

partiql_ast/ast/
mod.rs

1//! A `PartiQL` abstract syntax tree (AST).
2//!
3//! This module contains the structures for the language AST.
4//! Two main entities in the module are [`Item`] and [`AstNode`]. `AstNode` represents an AST node
5//! and `Item` represents a `PartiQL` statement type, e.g. query, data definition language (DDL)
6//! data manipulation language (DML).
7
8// As more changes to this AST are expected, unless explicitly advised, using the structures exposed
9// in this crate directly is not recommended.
10
11use rust_decimal::Decimal as RustDecimal;
12
13use partiql_ast_macros::Visit;
14use partiql_common::node::{IdAnnotated, NodeId};
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17use std::fmt;
18use std::ops::Deref;
19
20mod graph;
21pub use graph::*;
22
23/// Represents an AST node.
24#[derive(Clone, Debug, Eq, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct AstNode<T> {
27    pub id: NodeId,
28    pub node: T,
29}
30
31impl<T> Deref for AstNode<T> {
32    type Target = T;
33
34    fn deref(&self) -> &T {
35        &self.node
36    }
37}
38
39impl<T> IdAnnotated<NodeId> for AstNode<T> {
40    fn id(&self) -> NodeId {
41        self.id
42    }
43}
44
45#[derive(Visit, Clone, Debug, PartialEq)]
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47#[non_exhaustive]
48pub enum Item {
49    // Data Definition Language statements
50    Ddl(Ddl),
51    // Data Modification Language statements
52    Dml(Dml),
53    // Data retrieval statements
54    Query(Query),
55}
56
57impl fmt::Display for Item {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        // Use Debug formatting for now
60        write!(f, "{self:?}")
61    }
62}
63
64#[derive(Visit, Clone, Debug, PartialEq)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66pub struct Ddl {
67    pub op: DdlOp,
68}
69
70#[derive(Visit, Clone, Debug, PartialEq)]
71#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
72#[non_exhaustive]
73pub enum DdlOp {
74    /// `CREATE TABLE <symbol>`
75    CreateTable(CreateTable),
76    /// `DROP TABLE <Ident>`
77    DropTable(DropTable),
78    /// `CREATE INDEX ON <Ident> (<expr> [, <expr>]...)`
79    CreateIndex(CreateIndex),
80    /// DROP INDEX <Ident> ON <Ident>
81    /// In Statement, first <Ident> represents keys, second represents table
82    DropIndex(DropIndex),
83}
84
85#[derive(Visit, Clone, Debug, PartialEq, Eq)]
86#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
87pub struct CreateTable {
88    #[visit(skip)]
89    pub table_name: SymbolPrimitive,
90}
91
92#[derive(Visit, Clone, Debug, PartialEq, Eq)]
93#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
94pub struct DropTable {
95    #[visit(skip)]
96    pub table_name: SymbolPrimitive,
97}
98
99#[derive(Visit, Clone, Debug, PartialEq)]
100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
101pub struct CreateIndex {
102    #[visit(skip)]
103    pub index_name: SymbolPrimitive,
104    pub fields: Vec<Box<Expr>>,
105}
106
107#[derive(Visit, Clone, Debug, PartialEq, Eq)]
108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
109pub struct DropIndex {
110    #[visit(skip)]
111    pub table: SymbolPrimitive,
112    #[visit(skip)]
113    pub keys: SymbolPrimitive,
114}
115
116#[derive(Visit, Clone, Debug, PartialEq)]
117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
118pub struct Dml {
119    pub op: DmlOp,
120    pub from_clause: Option<FromClause>,
121    pub where_clause: Option<Box<Expr>>,
122    pub returning: Option<ReturningExpr>,
123}
124
125#[derive(Visit, Clone, Debug, PartialEq)]
126#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
127#[non_exhaustive]
128pub enum DmlOp {
129    /// `INSERT INTO <expr> <expr>`
130    Insert(Insert),
131    /// `INSERT INTO <expr> VALUE <expr> [AT <expr>]` [ON CONFLICT WHERE <expr> DO NOTHING]`
132    InsertValue(InsertValue),
133    /// `SET <assignment>...`
134    Set(Set),
135    /// `REMOVE <expr>`
136    Remove(Remove),
137    /// DELETE
138    Delete(Delete),
139}
140
141/// `RETURNING (<returning_elem> [, <returning_elem>]...)`
142#[derive(Visit, Clone, Debug, PartialEq)]
143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
144pub struct ReturningExpr {
145    pub elems: Vec<ReturningElem>,
146}
147
148/// `<returning mapping> (<expr> [, <expr>]...)`
149#[derive(Visit, Clone, Debug, PartialEq)]
150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
151pub struct ReturningElem {
152    #[visit(skip)]
153    pub mapping: ReturningMapping,
154    #[visit(skip)]
155    pub column: ColumnComponent,
156}
157
158#[derive(Clone, Debug, PartialEq)]
159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
160#[non_exhaustive]
161pub enum ColumnComponent {
162    ReturningWildcard,
163    ReturningColumn(ReturningColumn),
164}
165
166#[derive(Clone, Debug, PartialEq)]
167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
168pub struct ReturningColumn {
169    pub expr: Box<Expr>,
170}
171
172/// ( MODIFIED | ALL ) ( NEW | OLD )
173#[derive(Clone, Debug, PartialEq, Eq)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175#[non_exhaustive]
176pub enum ReturningMapping {
177    ModifiedNew,
178    ModifiedOld,
179    AllNew,
180    AllOld,
181}
182
183#[derive(Visit, Clone, Debug, PartialEq)]
184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
185pub struct Insert {
186    pub target: Box<Expr>,
187    pub values: Box<Expr>,
188}
189
190#[derive(Visit, Clone, Debug, PartialEq)]
191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
192pub struct InsertValue {
193    pub target: Box<Expr>,
194    pub value: Box<Expr>,
195    pub index: Option<Box<Expr>>,
196    pub on_conflict: Option<OnConflict>,
197}
198
199#[derive(Visit, Clone, Debug, PartialEq)]
200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
201pub struct Set {
202    pub assignment: Assignment,
203}
204
205/// Represents `<expr> = <expr>` in a DML SET operation.  Note that in this case, `=` is representing
206/// an assignment operation and *not* the equality operator.
207#[derive(Visit, Clone, Debug, PartialEq)]
208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
209pub struct Assignment {
210    pub target: Box<Expr>,
211    pub value: Box<Expr>,
212}
213
214#[derive(Visit, Clone, Debug, PartialEq)]
215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
216pub struct Remove {
217    pub target: Box<Expr>,
218}
219
220#[derive(Visit, Clone, Debug, PartialEq, Eq)]
221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
222pub struct Delete {}
223
224/// `ON CONFLICT <expr> <conflict_action>`
225#[derive(Visit, Clone, Debug, PartialEq)]
226#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
227pub struct OnConflict {
228    pub expr: Box<Expr>,
229    #[visit(skip)]
230    pub conflict_action: ConflictAction,
231}
232
233/// `CONFLICT_ACTION <action>`
234#[derive(Clone, Debug, PartialEq, Eq)]
235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
236#[non_exhaustive]
237pub enum ConflictAction {
238    DoNothing,
239}
240
241// Evaluation order
242// WITH,
243// FROM,
244// LET,
245// WHERE,
246// GROUP BY,
247// HAVING,
248// LETTING (which is special to PartiQL),
249// ORDER BY,
250// LIMIT / OFFSET
251// SELECT (or SELECT VALUE or PIVOT, which are both special to ion PartiQL).
252
253#[derive(Visit, Clone, Debug, PartialEq)]
254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
255pub struct TopLevelQuery {
256    pub with: Option<AstNode<WithClause>>,
257    pub query: AstNode<Query>,
258}
259
260#[derive(Visit, Clone, Debug, PartialEq)]
261#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
262pub struct Query {
263    pub set: AstNode<QuerySet>,
264    pub order_by: Option<Box<AstNode<OrderByExpr>>>,
265    pub limit_offset: Option<Box<AstNode<LimitOffsetClause>>>,
266}
267
268#[derive(Visit, Clone, Debug, PartialEq)]
269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
270pub struct WithClause {
271    #[visit(skip)]
272    pub recursive: bool,
273    pub withs: Vec<AstNode<WithElement>>,
274}
275
276#[derive(Visit, Clone, Debug, PartialEq)]
277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
278pub struct WithElement {
279    #[visit(skip)]
280    pub query_name: SymbolPrimitive,
281    #[visit(skip)]
282    pub columns: Option<Vec<SymbolPrimitive>>,
283    pub subquery: AstNode<Expr>,
284}
285
286#[derive(Visit, Clone, Debug, PartialEq)]
287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
288#[non_exhaustive]
289pub enum QuerySet {
290    BagOp(Box<AstNode<BagOpExpr>>),
291    Select(Box<AstNode<Select>>),
292    Expr(Box<Expr>),
293    Values(Vec<Box<Expr>>),
294    Table(QueryTable),
295}
296
297#[derive(Visit, Clone, Debug, PartialEq)]
298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
299pub struct BagOpExpr {
300    #[visit(skip)]
301    pub bag_op: BagOperator,
302    #[visit(skip)]
303    pub setq: Option<SetQuantifier>,
304    pub lhs: Box<AstNode<Query>>,
305    pub rhs: Box<AstNode<Query>>,
306}
307
308#[derive(Clone, Debug, PartialEq, Eq)]
309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
310#[non_exhaustive]
311pub enum BagOperator {
312    Union,
313    Except,
314    Intersect,
315    OuterUnion,
316    OuterExcept,
317    OuterIntersect,
318}
319
320/// Indicates if a set should be reduced to its distinct elements or not.
321#[derive(Clone, Debug, PartialEq, Eq)]
322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
323#[non_exhaustive]
324pub enum SetQuantifier {
325    All,
326    Distinct,
327}
328
329#[derive(Visit, Clone, Debug, PartialEq)]
330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
331pub struct Select {
332    pub project: AstNode<Projection>,
333    pub exclude: Option<AstNode<Exclusion>>,
334    pub from: Option<AstNode<FromClause>>,
335    pub from_let: Option<AstNode<Let>>,
336    pub where_clause: Option<Box<AstNode<WhereClause>>>,
337    pub group_by: Option<Box<AstNode<GroupByExpr>>>,
338    pub having: Option<Box<AstNode<HavingClause>>>,
339}
340
341#[derive(Visit, Clone, Debug, PartialEq, Eq)]
342#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
343pub struct QueryTable {
344    #[visit(skip)]
345    pub table_name: SymbolPrimitive,
346}
347
348#[derive(Visit, Clone, Debug, PartialEq)]
349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
350pub struct Projection {
351    pub kind: ProjectionKind,
352    #[visit(skip)]
353    pub setq: Option<SetQuantifier>,
354}
355
356/// Indicates the type of projection in a SFW query.
357#[derive(Visit, Clone, Debug, PartialEq)]
358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
359#[non_exhaustive]
360pub enum ProjectionKind {
361    #[visit(skip)]
362    ProjectStar,
363    ProjectList(Vec<AstNode<ProjectItem>>),
364    ProjectPivot(ProjectPivot),
365    ProjectValue(Box<Expr>),
366}
367
368/// An item to be projected in a `SELECT`-list.
369#[derive(Visit, Clone, Debug, PartialEq)]
370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
371#[non_exhaustive]
372pub enum ProjectItem {
373    /// For `.*` in SELECT list
374    ProjectAll(ProjectAll), // TODO remove this?
375    /// For `<expr> [AS <id>]`
376    ProjectExpr(ProjectExpr),
377}
378
379#[derive(Visit, Clone, Debug, PartialEq)]
380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
381pub struct ProjectPivot {
382    pub key: Box<Expr>,
383    pub value: Box<Expr>,
384}
385
386#[derive(Visit, Clone, Debug, PartialEq)]
387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
388pub struct ProjectAll {
389    pub expr: Box<Expr>,
390}
391
392#[derive(Visit, Clone, Debug, PartialEq)]
393#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
394pub struct ProjectExpr {
395    pub expr: Box<Expr>,
396    #[visit(skip)]
397    pub as_alias: Option<SymbolPrimitive>,
398}
399
400#[derive(Visit, Clone, Debug, PartialEq)]
401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
402pub struct Exclusion {
403    pub items: Vec<AstNode<ExcludePath>>,
404}
405
406/// The expressions that can result in values.
407#[derive(Visit, Clone, Debug, PartialEq)]
408#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
409#[non_exhaustive]
410pub enum Expr {
411    Lit(AstNode<Lit>),
412    /// Variable reference
413    VarRef(AstNode<VarRef>),
414    /// Binary operator
415    BinOp(AstNode<BinOp>),
416    /// Unary operators
417    UniOp(AstNode<UniOp>),
418    /// Comparison operators
419    Like(AstNode<Like>),
420    Between(AstNode<Between>),
421    In(AstNode<In>),
422    Case(AstNode<Case>),
423    /// Constructors
424    Struct(AstNode<Struct>),
425    Bag(AstNode<Bag>),
426    List(AstNode<List>),
427    /// Other expression types
428    Path(AstNode<Path>),
429    Call(AstNode<Call>),
430    CallAgg(AstNode<CallAgg>),
431    /// <expr> MATCH <graph_pattern>
432    GraphMatch(Box<AstNode<GraphMatch>>),
433
434    /// Query, e.g. `UNION` | `EXCEPT` | `INTERSECT` | `SELECT` and their parts.
435    Query(AstNode<Query>),
436
437    /// Indicates an error occurred during query processing; The exact error details are out of band of the AST
438    #[visit(skip)]
439    Error,
440}
441
442impl IdAnnotated<NodeId> for Expr {
443    fn id(&self) -> NodeId {
444        match self {
445            Expr::Lit(l) => l.id(),
446            Expr::VarRef(v) => v.id(),
447            Expr::BinOp(b) => b.id(),
448            Expr::UniOp(u) => u.id(),
449            Expr::Like(l) => l.id(),
450            Expr::Between(l) => l.id(),
451            Expr::In(l) => l.id(),
452            Expr::Case(c) => c.id(),
453            Expr::Struct(s) => s.id(),
454            Expr::Bag(b) => b.id(),
455            Expr::List(l) => l.id(),
456            Expr::Path(p) => p.id(),
457            Expr::Call(c) => c.id(),
458            Expr::CallAgg(c) => c.id(),
459            Expr::GraphMatch(g) => g.id(),
460            Expr::Query(q) => q.id(),
461            Expr::Error => unreachable!(),
462        }
463    }
464}
465
466/// `Lit` is mostly inspired by SQL-92 Literals standard and `PartiQL` specification.
467/// See section 5.3 in the following:
468/// <https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt>
469/// and Section 2 of the following (Figure 1: BNF Grammar for `PartiQL` Values):
470/// <https://partiql.org/assets/PartiQL-Specification.pdf>
471#[derive(Visit, Clone, Debug, PartialEq)]
472#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
473#[visit(skip_recurse)]
474#[non_exhaustive]
475pub enum Lit {
476    #[visit(skip)]
477    Null,
478    #[visit(skip)]
479    Missing,
480    #[visit(skip)]
481    Int8Lit(i8),
482    #[visit(skip)]
483    Int16Lit(i16),
484    #[visit(skip)]
485    Int32Lit(i32),
486    #[visit(skip)]
487    Int64Lit(i64),
488    #[visit(skip)]
489    DecimalLit(RustDecimal),
490    #[visit(skip)]
491    NumericLit(RustDecimal),
492    #[visit(skip)]
493    RealLit(f32),
494    #[visit(skip)]
495    FloatLit(f32),
496    #[visit(skip)]
497    DoubleLit(f64),
498    #[visit(skip)]
499    BoolLit(bool),
500    #[visit(skip)]
501    EmbeddedDocLit(String, Type),
502    #[visit(skip)]
503    CharStringLit(String),
504    #[visit(skip)]
505    NationalCharStringLit(String),
506    #[visit(skip)]
507    BitStringLit(String),
508    #[visit(skip)]
509    HexStringLit(String),
510    #[visit(skip)]
511    StructLit(AstNode<StructLit>),
512    #[visit(skip)]
513    BagLit(AstNode<BagLit>),
514    #[visit(skip)]
515    ListLit(AstNode<ListLit>),
516    /// E.g. `TIME WITH TIME ZONE` in `SELECT TIME WITH TIME ZONE '12:00' FROM ...`
517    #[visit(skip)]
518    TypedLit(String, Type),
519}
520
521#[derive(Clone, Debug, PartialEq)]
522#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
523pub struct LitField {
524    pub first: String,
525    pub second: AstNode<Lit>,
526}
527
528#[derive(Clone, Debug, PartialEq)]
529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
530pub struct StructLit {
531    pub fields: Vec<LitField>,
532}
533
534#[derive(Clone, Debug, PartialEq)]
535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
536pub struct BagLit {
537    pub values: Vec<Lit>,
538}
539
540#[derive(Clone, Debug, PartialEq)]
541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
542pub struct ListLit {
543    pub values: Vec<Lit>,
544}
545
546#[derive(Visit, Clone, Debug, PartialEq, Eq)]
547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
548pub struct VarRef {
549    #[visit(skip)]
550    pub name: SymbolPrimitive,
551    #[visit(skip)]
552    pub qualifier: ScopeQualifier,
553}
554
555/// Indicates scope search order when resolving variables.
556/// Has no effect except within `FROM` sources.
557#[derive(Clone, Debug, PartialEq, Eq)]
558#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
559#[non_exhaustive]
560pub enum ScopeQualifier {
561    /// The variable was *NOT* prefixed with `@`.
562    /// Resolve the variable by looking first in the database environment, then in the 'lexical' scope.
563    Unqualified,
564    /// The variable *WAS* prefixed with `@`.
565    /// Resolve the variable by looking first in the 'lexical' scope, then in the database environment.
566    Qualified,
567}
568
569#[derive(Visit, Clone, Debug, PartialEq)]
570#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
571pub struct BinOp {
572    #[visit(skip)]
573    pub kind: BinOpKind,
574    pub lhs: Box<Expr>,
575    pub rhs: Box<Expr>,
576}
577
578#[derive(Clone, Debug, PartialEq, Eq)]
579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
580#[non_exhaustive]
581pub enum BinOpKind {
582    // Arithmetic
583    Add,
584    Div,
585    Exp,
586    Mod,
587    Mul,
588    Sub,
589    // Logical
590    And,
591    Or,
592    // String
593    Concat,
594    // Comparison
595    Eq,
596    Gt,
597    Gte,
598    Lt,
599    Lte,
600    Ne,
601    Is,
602}
603
604#[derive(Visit, Clone, Debug, PartialEq)]
605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
606pub struct UniOp {
607    #[visit(skip)]
608    pub kind: UniOpKind,
609    pub expr: Box<Expr>,
610}
611
612#[derive(Clone, Debug, PartialEq, Eq)]
613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
614#[non_exhaustive]
615pub enum UniOpKind {
616    Pos,
617    Neg,
618    Not,
619}
620
621#[derive(Visit, Clone, Debug, PartialEq)]
622#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
623pub struct Like {
624    pub value: Box<Expr>,
625    pub pattern: Box<Expr>,
626    pub escape: Option<Box<Expr>>,
627}
628
629#[derive(Visit, Clone, Debug, PartialEq)]
630#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
631pub struct Between {
632    pub value: Box<Expr>,
633    pub from: Box<Expr>,
634    pub to: Box<Expr>,
635}
636
637#[derive(Visit, Clone, Debug, PartialEq)]
638#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
639pub struct In {
640    pub lhs: Box<Expr>,
641    pub rhs: Box<Expr>,
642}
643
644#[derive(Visit, Clone, Debug, PartialEq)]
645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
646#[non_exhaustive]
647pub enum Case {
648    /// CASE <expr> [ WHEN <expr> THEN <expr> ]... [ ELSE <expr> ] END
649    SimpleCase(SimpleCase),
650    /// CASE [ WHEN <expr> THEN <expr> ]... [ ELSE <expr> ] END
651    SearchedCase(SearchedCase),
652}
653
654#[derive(Visit, Clone, Debug, PartialEq)]
655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
656pub struct SimpleCase {
657    pub expr: Box<Expr>,
658    pub cases: Vec<ExprPair>,
659    pub default: Option<Box<Expr>>,
660}
661
662#[derive(Visit, Clone, Debug, PartialEq)]
663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
664pub struct SearchedCase {
665    pub cases: Vec<ExprPair>,
666    pub default: Option<Box<Expr>>,
667}
668
669/// A generic pair of expressions. Used in the `pub struct`, `searched_case`
670/// and `simple_case` expr variants above.
671#[derive(Visit, Clone, Debug, PartialEq)]
672#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
673pub struct ExprPair {
674    pub first: Box<Expr>,
675    pub second: Box<Expr>,
676}
677
678#[derive(Visit, Clone, Debug, PartialEq)]
679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
680pub struct Struct {
681    pub fields: Vec<ExprPair>,
682}
683
684#[derive(Visit, Clone, Debug, PartialEq)]
685#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
686pub struct Bag {
687    pub values: Vec<Box<Expr>>,
688}
689
690#[derive(Visit, Clone, Debug, PartialEq)]
691#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
692pub struct List {
693    pub values: Vec<Box<Expr>>,
694}
695
696#[derive(Visit, Clone, Debug, PartialEq)]
697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
698pub struct CallAgg {
699    #[visit(skip)]
700    pub func_name: SymbolPrimitive,
701    pub args: Vec<AstNode<CallArg>>,
702}
703
704#[derive(Visit, Clone, Debug, PartialEq)]
705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
706pub struct Call {
707    #[visit(skip)]
708    pub func_name: SymbolPrimitive,
709    pub args: Vec<AstNode<CallArg>>,
710}
711
712#[derive(Visit, Clone, Debug, PartialEq)]
713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
714#[non_exhaustive]
715pub enum CallArg {
716    /// `*` used as an argument to a function call (e.g., in `count(*)`)
717    #[visit(skip)]
718    Star(),
719    /// positional argument to a function call (e.g., all arguments in `foo(1, 'a', 3)`)
720    Positional(Box<Expr>),
721    /// E.g. `INT` in `foo(INT)`
722    #[visit(skip)]
723    PositionalType(Type),
724    /// named argument to a function call (e.g., the `"from" : 2` in `substring(a, "from":2)`
725    Named(CallArgNamed),
726    /// E.g. `AS: VARCHAR` in `CAST('abc' AS VARCHAR)`
727    NamedType(CallArgNamedType),
728}
729
730#[derive(Visit, Clone, Debug, PartialEq)]
731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
732pub struct CallArgNamed {
733    #[visit(skip)]
734    pub name: SymbolPrimitive,
735    pub value: Box<Expr>,
736}
737
738#[derive(Visit, Clone, Debug, PartialEq)]
739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
740pub struct CallArgNamedType {
741    #[visit(skip)]
742    pub name: SymbolPrimitive,
743    #[visit(skip)]
744    pub ty: Type,
745}
746
747#[derive(Visit, Clone, Debug, PartialEq)]
748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
749pub struct Path {
750    pub root: Box<Expr>,
751    pub steps: Vec<PathStep>,
752}
753
754/// A "step" within a path expression; that is the components of the expression following the root.
755#[derive(Visit, Clone, Debug, PartialEq)]
756#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
757#[non_exhaustive]
758pub enum PathStep {
759    PathProject(PathExpr),
760    PathIndex(PathExpr),
761    #[visit(skip)]
762    PathForEach,
763    #[visit(skip)]
764    PathUnpivot,
765}
766
767#[derive(Visit, Clone, Debug, PartialEq)]
768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
769pub struct PathExpr {
770    pub index: Box<Expr>,
771}
772
773#[derive(Visit, Clone, Debug, PartialEq)]
774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
775pub struct ExcludePath {
776    pub root: AstNode<VarRef>,
777    pub steps: Vec<ExcludePathStep>,
778}
779
780/// A "step" within an exclude path; that is the components of the exclude path following the root.
781#[derive(Visit, Clone, Debug, PartialEq)]
782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
783#[non_exhaustive]
784pub enum ExcludePathStep {
785    #[visit(skip)]
786    PathProject(AstNode<SymbolPrimitive>),
787    #[visit(skip)]
788    PathIndex(AstNode<Lit>),
789    #[visit(skip)]
790    PathForEach,
791    #[visit(skip)]
792    PathUnpivot,
793}
794
795#[derive(Visit, Clone, Debug, PartialEq)]
796#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
797pub struct Let {
798    /// A list of LET bindings
799    pub let_bindings: Vec<LetBinding>,
800}
801
802#[derive(Visit, Clone, Debug, PartialEq)]
803#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
804pub struct LetBinding {
805    pub expr: Box<Expr>,
806    #[visit(skip)]
807    pub as_alias: SymbolPrimitive,
808}
809
810/// FROM clause of an SFW query
811#[derive(Visit, Clone, Debug, PartialEq)]
812#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
813pub struct FromClause {
814    pub source: FromSource,
815}
816
817#[derive(Visit, Clone, Debug, PartialEq)]
818#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
819#[non_exhaustive]
820pub enum FromSource {
821    FromLet(AstNode<FromLet>),
822    /// <from_source> JOIN \[INNER | LEFT | RIGHT | FULL\] <from_source> ON <expr>
823    Join(AstNode<Join>),
824}
825
826impl IdAnnotated<NodeId> for FromSource {
827    fn id(&self) -> NodeId {
828        match self {
829            Self::FromLet(node) => node.id,
830            Self::Join(node) => node.id,
831        }
832    }
833}
834
835#[derive(Visit, Clone, Debug, PartialEq)]
836#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
837pub struct WhereClause {
838    pub expr: Box<Expr>,
839}
840
841#[derive(Visit, Clone, Debug, PartialEq)]
842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
843pub struct HavingClause {
844    pub expr: Box<Expr>,
845}
846
847#[derive(Visit, Clone, Debug, PartialEq)]
848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
849pub struct FromLet {
850    pub expr: Box<Expr>,
851    #[visit(skip)]
852    pub kind: FromLetKind,
853    #[visit(skip)]
854    pub as_alias: Option<SymbolPrimitive>,
855    #[visit(skip)]
856    pub at_alias: Option<SymbolPrimitive>,
857    #[visit(skip)]
858    pub by_alias: Option<SymbolPrimitive>,
859}
860
861/// Indicates the type of `FromLet`, see the following for more details:
862/// https:///github.com/partiql/partiql-lang-kotlin/issues/242
863#[derive(Clone, Debug, PartialEq, Eq)]
864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
865#[non_exhaustive]
866pub enum FromLetKind {
867    Scan,
868    Unpivot,
869    GraphTable,
870}
871
872#[derive(Visit, Clone, Debug, PartialEq)]
873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
874pub struct Join {
875    #[visit(skip)]
876    pub kind: JoinKind,
877    pub left: Box<FromSource>,
878    pub right: Box<FromSource>,
879    pub predicate: Option<AstNode<JoinSpec>>,
880}
881
882/// Indicates the logical type of join.
883#[derive(Clone, Debug, PartialEq, Eq)]
884#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
885#[non_exhaustive]
886pub enum JoinKind {
887    Inner,
888    Left,
889    Right,
890    Full,
891    Cross,
892}
893
894#[derive(Visit, Clone, Debug, PartialEq)]
895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
896#[non_exhaustive]
897pub enum JoinSpec {
898    On(Box<Expr>),
899    Using(Vec<Path>),
900    #[visit(skip)]
901    Natural,
902}
903
904/// GROUP BY <`grouping_strategy`> <`group_key`>[, <`group_key`>]... \[AS <symbol>\]
905#[derive(Visit, Clone, Debug, PartialEq)]
906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
907pub struct GroupByExpr {
908    #[visit(skip)]
909    pub strategy: Option<GroupingStrategy>,
910    pub keys: Vec<AstNode<GroupKey>>,
911    #[visit(skip)]
912    pub group_as_alias: Option<SymbolPrimitive>,
913}
914
915/// Desired grouping qualifier:  ALL or PARTIAL.  Note: the `group_` prefix is
916/// needed to avoid naming clashes.
917#[derive(Clone, Debug, PartialEq, Eq)]
918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
919#[non_exhaustive]
920pub enum GroupingStrategy {
921    GroupFull,
922    GroupPartial,
923}
924
925/// <expr> [AS <symbol>]
926#[derive(Visit, Clone, Debug, PartialEq)]
927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
928pub struct GroupKey {
929    pub expr: Box<Expr>,
930    #[visit(skip)]
931    pub as_alias: Option<SymbolPrimitive>,
932}
933
934/// ORDER BY <`sort_spec`>...
935#[derive(Visit, Clone, Debug, PartialEq)]
936#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
937pub struct OrderByExpr {
938    pub sort_specs: Vec<AstNode<SortSpec>>,
939}
940
941#[derive(Visit, Clone, Debug, PartialEq)]
942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
943pub struct LimitOffsetClause {
944    pub limit: Option<Box<Expr>>,
945    pub offset: Option<Box<Expr>>,
946}
947
948/// <expr> [ASC | DESC] ?
949#[derive(Visit, Clone, Debug, PartialEq)]
950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
951pub struct SortSpec {
952    pub expr: Box<Expr>,
953    #[visit(skip)]
954    pub ordering_spec: Option<OrderingSpec>,
955    #[visit(skip)]
956    pub null_ordering_spec: Option<NullOrderingSpec>,
957}
958
959#[derive(Clone, Debug, PartialEq, Eq)]
960#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
961#[non_exhaustive]
962pub enum OrderingSpec {
963    Asc,
964    Desc,
965}
966
967#[derive(Clone, Debug, PartialEq, Eq)]
968#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
969#[non_exhaustive]
970pub enum NullOrderingSpec {
971    First,
972    Last,
973}
974
975/// Represents all possible `PartiQL` data types.
976#[derive(Clone, Debug, PartialEq)]
977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
978#[non_exhaustive]
979pub enum Type {
980    NullType,
981    BooleanType,
982    Integer2Type,
983    Integer4Type,
984    Integer8Type,
985    DecimalType,
986    NumericType,
987    RealType,
988    DoublePrecisionType,
989    TimestampType,
990    CharacterType,
991    CharacterVaryingType,
992    MissingType,
993    StringType,
994    SymbolType,
995    BlobType,
996    ClobType,
997    DateType,
998    TimeType,
999    ZonedTimestampType,
1000    StructType,
1001    TupleType,
1002    ListType,
1003    BagType,
1004    AnyType,
1005
1006    CustomType(CustomType),
1007}
1008
1009#[derive(Clone, Debug, PartialEq)]
1010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1011#[non_exhaustive]
1012pub enum CustomTypeParam {
1013    /// E.g. `2` in `VARCHAR(2)`
1014    Lit(Lit),
1015    /// E.g. `INT` in `FooType(INT)`
1016    Type(Type),
1017}
1018
1019#[derive(Clone, Debug, PartialEq)]
1020#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1021#[non_exhaustive]
1022pub enum CustomTypePart {
1023    /// E.g. any of `WITH`, `TIME`, and`ZONE` in `TIME(20) WITH TIME ZONE`
1024    Name(SymbolPrimitive),
1025    /// E.g. `TIME(20) in `TIME(20) WITH TIME ZONE`
1026    Parameterized(SymbolPrimitive, Vec<CustomTypeParam>),
1027}
1028
1029#[derive(Visit, Clone, Debug, PartialEq)]
1030#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1031pub struct CustomType {
1032    #[visit(skip)]
1033    pub parts: Vec<CustomTypePart>,
1034}
1035
1036#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1038pub struct SymbolPrimitive {
1039    pub value: String,
1040    pub case: CaseSensitivity,
1041}
1042
1043/// Is used to determine if variable lookup should be case-sensitive or not.
1044#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1046#[non_exhaustive]
1047pub enum CaseSensitivity {
1048    CaseSensitive,
1049    CaseInsensitive,
1050}