1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
mod display;
use super::*;

/// An SQL expression of any type.
///
/// The parser does not distinguish between expressions of different types
/// (e.g. boolean vs string), so the caller must handle expressions of
/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Expr {
    /// Identifier e.g. table name or column name
    Identifier(Ident),
    /// Unqualified wildcard (`*`). SQL allows this in limited contexts, such as:
    /// - right after `SELECT` (which is represented as a [SelectItem::Wildcard] instead)
    /// - or as part of an aggregate function, e.g. `COUNT(*)`,
    ///
    /// ...but we currently also accept it in contexts where it doesn't make
    /// sense, such as `* + *`
    Wildcard,
    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
    QualifiedWildcard(Vec<Ident>),
    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
    CompoundIdentifier(Vec<Ident>),
    /// `IS NULL` expression
    IsNull(Box<Expr>),
    /// `IS NOT NULL` expression
    IsNotNull(Box<Expr>),
    /// `[ NOT ] IN (val1, val2, ...)`
    InList(InList),
    /// `[ NOT ] IN (SELECT ...)`
    InSubquery(InSubquery),
    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
    Between(Between),
    /// Binary operation e.g. `1 + 1` or `foo > bar`
    BinaryOp(BinaryOp),
    /// Unary operation e.g. `NOT foo`
    UnaryOp(UnaryOp),
    /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
    Cast(Cast),
    /// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
    //  this differs from CAST in the choice of how to implement invalid conversions
    TryCast(TryCast),
    /// EXTRACT(DateTimeField FROM <expr>)
    Extract(Extract),
    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
    Substring(Substring),
    /// TRIM([BOTH | LEADING | TRAILING] <expr> [FROM <expr>])\
    /// Or\
    /// TRIM(<expr>)
    Trim(Trim),
    /// `expr COLLATE collation`
    Collate(Collate),
    /// Nested expression e.g. `(foo > bar)` or `(1)`
    Nested(Box<Expr>),
    /// A literal value, such as string, number, date or NULL
    Value(Value),
    /// A constant of form `<data_type> 'value'`.
    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
    /// as well as constants of other types (a non-standard PostgreSQL extension).
    TypedString(TypedString),
    MapAccess(MapAccess),
    /// Scalar function call e.g. `LEFT(foo, 5)`
    Function(Function),
    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
    ///
    /// Note we only recognize a complete single expression as `<condition>`,
    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
    Case(Case),
    /// An exists expression `EXISTS(SELECT ...)`, used in expressions like
    /// `WHERE EXISTS (SELECT ...)`.
    Exists(Box<Query>),
    /// A parenthesized subquery `(SELECT ...)`, used in expression like
    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
    Subquery(Box<Query>),
    /// The `LISTAGG` function `SELECT LISTAGG(...) WITHIN GROUP (ORDER BY ...)`
    ListAgg(ListAgg),
}

/// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
///
/// Note we only recognize a complete single expression as `<condition>`,
/// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
/// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Case {
    pub operand: Option<Box<Expr>>,
    pub conditions: Vec<Expr>,
    pub results: Vec<Expr>,
    pub else_result: Option<Box<Expr>>,
}

/// `[ NOT ] IN (val1, val2, ...)`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct InList {
    pub expr: Box<Expr>,
    pub list: Vec<Expr>,
    pub negated: bool,
}
/// `[ NOT ] IN (SELECT ...)`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct InSubquery {
    pub expr: Box<Expr>,
    pub subquery: Box<Query>,
    pub negated: bool,
}
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Between {
    pub expr: Box<Expr>,
    pub negated: bool,
    pub low: Box<Expr>,
    pub high: Box<Expr>,
}
/// Binary operation e.g. `1 + 1` or `foo > bar`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct BinaryOp {
    pub left: Box<Expr>,
    pub op: BinaryOperator,
    pub right: Box<Expr>,
}
/// Unary operation e.g. `NOT foo`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct UnaryOp {
    pub op: UnaryOperator,
    pub expr: Box<Expr>,
}
/// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Cast {
    pub expr: Box<Expr>,
    pub data_type: DataType,
}
/// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
//  this differs from CAST in the choice of how to implement invalid conversions
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct TryCast {
    pub expr: Box<Expr>,
    pub data_type: DataType,
}
/// EXTRACT(DateTimeField FROM <expr>)
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Extract {
    pub field: DateTimeField,
    pub expr: Box<Expr>,
}
/// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Substring {
    pub expr: Box<Expr>,
    pub substring_from: Option<Box<Expr>>,
    pub substring_for: Option<Box<Expr>>,
}
/// TRIM([BOTH | LEADING | TRAILING] <expr> [FROM <expr>])\
/// Or\
/// TRIM(<expr>)
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Trim {
    pub expr: Box<Expr>,
    // ([BOTH | LEADING | TRAILING], <expr>)
    pub trim_where: Option<(TrimWhereField, Box<Expr>)>,
}
/// `expr COLLATE collation`
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct Collate {
    pub expr: Box<Expr>,
    pub collation: ObjectName,
}

/// A constant of form `<data_type> 'value'`.
/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
/// as well as constants of other types (a non-standard PostgreSQL extension).
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct TypedString {
    pub data_type: DataType,
    pub value: String,
}
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct MapAccess {
    pub column: Box<Expr>,
    pub key: String,
}