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