1use crate::{ColumnName, ParamName, PgType, TableName};
4
5#[derive(Debug, Clone, PartialEq)]
7pub enum Expr {
8 Param(ParamName),
10 Column(ColumnRef),
12 String(String),
14 Int(i64),
16 Bool(bool),
18 Null,
20 Now,
22 Default,
24 BinOp {
26 left: Box<Expr>,
27 op: BinOp,
28 right: Box<Expr>,
29 },
30 IsNull { expr: Box<Expr>, negated: bool },
32 Like { expr: Box<Expr>, pattern: Box<Expr> },
34 ILike { expr: Box<Expr>, pattern: Box<Expr> },
36 Any { expr: Box<Expr>, array: Box<Expr> },
38 JsonGet { expr: Box<Expr>, key: Box<Expr> },
40 JsonGetText { expr: Box<Expr>, key: Box<Expr> },
42 Contains { expr: Box<Expr>, value: Box<Expr> },
44 KeyExists { expr: Box<Expr>, key: Box<Expr> },
46 Cast { expr: Box<Expr>, pg_type: PgType },
48 Excluded(ColumnName),
50 FnCall { name: String, args: Vec<Expr> },
52 Count { table: TableName },
54 Raw(String),
56}
57
58#[derive(Debug, Clone, PartialEq)]
65pub struct ColumnRef {
66 pub table: Option<TableName>,
70
71 pub column: ColumnName,
75}
76
77impl ColumnRef {
78 pub fn new(column: ColumnName) -> Self {
79 Self {
80 table: None,
81 column,
82 }
83 }
84
85 pub fn qualified(table: TableName, column: ColumnName) -> Self {
86 Self {
87 table: Some(table),
88 column,
89 }
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95pub enum BinOp {
96 Eq,
98 Ne,
100 Lt,
102 Le,
104 Gt,
106 Ge,
108 And,
110 Or,
112}
113
114impl BinOp {
115 pub fn as_str(self) -> &'static str {
116 match self {
117 BinOp::Eq => "=",
118 BinOp::Ne => "<>",
119 BinOp::Lt => "<",
120 BinOp::Le => "<=",
121 BinOp::Gt => ">",
122 BinOp::Ge => ">=",
123 BinOp::And => "AND",
124 BinOp::Or => "OR",
125 }
126 }
127}
128
129impl Expr {
131 pub fn param(name: ParamName) -> Self {
132 Expr::Param(name)
133 }
134
135 pub fn column(name: ColumnName) -> Self {
136 Expr::Column(ColumnRef::new(name))
137 }
138
139 pub fn qualified_column(table: TableName, column: ColumnName) -> Self {
140 Expr::Column(ColumnRef::qualified(table, column))
141 }
142
143 pub fn string(s: impl Into<String>) -> Self {
144 Expr::String(s.into())
145 }
146
147 pub fn int(n: i64) -> Self {
148 Expr::Int(n)
149 }
150
151 pub fn bool(b: bool) -> Self {
152 Expr::Bool(b)
153 }
154
155 pub fn eq(self, other: Expr) -> Self {
157 Expr::BinOp {
158 left: Box::new(self),
159 op: BinOp::Eq,
160 right: Box::new(other),
161 }
162 }
163
164 pub fn and(self, other: Expr) -> Self {
166 Expr::BinOp {
167 left: Box::new(self),
168 op: BinOp::And,
169 right: Box::new(other),
170 }
171 }
172
173 pub fn or(self, other: Expr) -> Self {
175 Expr::BinOp {
176 left: Box::new(self),
177 op: BinOp::Or,
178 right: Box::new(other),
179 }
180 }
181
182 pub fn is_null(self) -> Self {
184 Expr::IsNull {
185 expr: Box::new(self),
186 negated: false,
187 }
188 }
189
190 pub fn is_not_null(self) -> Self {
192 Expr::IsNull {
193 expr: Box::new(self),
194 negated: true,
195 }
196 }
197
198 pub fn like(self, pattern: Expr) -> Self {
200 Expr::Like {
201 expr: Box::new(self),
202 pattern: Box::new(pattern),
203 }
204 }
205
206 pub fn ilike(self, pattern: Expr) -> Self {
208 Expr::ILike {
209 expr: Box::new(self),
210 pattern: Box::new(pattern),
211 }
212 }
213
214 pub fn any(self, array: Expr) -> Self {
216 Expr::Any {
217 expr: Box::new(self),
218 array: Box::new(array),
219 }
220 }
221
222 pub fn json_get(self, key: Expr) -> Self {
224 Expr::JsonGet {
225 expr: Box::new(self),
226 key: Box::new(key),
227 }
228 }
229
230 pub fn json_get_text(self, key: Expr) -> Self {
232 Expr::JsonGetText {
233 expr: Box::new(self),
234 key: Box::new(key),
235 }
236 }
237
238 pub fn contains(self, value: Expr) -> Self {
240 Expr::Contains {
241 expr: Box::new(self),
242 value: Box::new(value),
243 }
244 }
245
246 pub fn key_exists(self, key: Expr) -> Self {
248 Expr::KeyExists {
249 expr: Box::new(self),
250 key: Box::new(key),
251 }
252 }
253
254 pub fn cast(self, pg_type: PgType) -> Self {
256 Expr::Cast {
257 expr: Box::new(self),
258 pg_type,
259 }
260 }
261
262 pub fn excluded(column: ColumnName) -> Self {
264 Expr::Excluded(column)
265 }
266}