1use crate::ast::{AggregateFunc, Cage, Condition, ModKind, Value};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6pub enum BinaryOp {
7 Concat,
9 Add,
10 Sub,
11 Mul,
12 Div,
13 Rem,
15 And,
17 Or,
18 Eq,
20 Ne,
21 Gt,
22 Gte,
23 Lt,
24 Lte,
25 IsNull,
27 IsNotNull,
28}
29
30impl std::fmt::Display for BinaryOp {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 BinaryOp::Concat => write!(f, "||"),
34 BinaryOp::Add => write!(f, "+"),
35 BinaryOp::Sub => write!(f, "-"),
36 BinaryOp::Mul => write!(f, "*"),
37 BinaryOp::Div => write!(f, "/"),
38 BinaryOp::Rem => write!(f, "%"),
39 BinaryOp::And => write!(f, "AND"),
40 BinaryOp::Or => write!(f, "OR"),
41 BinaryOp::Eq => write!(f, "="),
42 BinaryOp::Ne => write!(f, "<>"),
43 BinaryOp::Gt => write!(f, ">"),
44 BinaryOp::Gte => write!(f, ">="),
45 BinaryOp::Lt => write!(f, "<"),
46 BinaryOp::Lte => write!(f, "<="),
47 BinaryOp::IsNull => write!(f, "IS NULL"),
48 BinaryOp::IsNotNull => write!(f, "IS NOT NULL"),
49 }
50 }
51}
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub enum Expr {
54 Star,
56 Named(String),
57 Aliased { name: String, alias: String },
59 Aggregate {
61 col: String,
62 func: AggregateFunc,
63 distinct: bool,
64 filter: Option<Vec<Condition>>,
66 alias: Option<String>,
67 },
68 Cast {
70 expr: Box<Expr>,
71 target_type: String,
72 alias: Option<String>,
73 },
74 Def {
75 name: String,
76 data_type: String,
77 constraints: Vec<Constraint>,
78 },
79 Mod { kind: ModKind, col: Box<Expr> },
80 Window {
82 name: String,
83 func: String,
84 params: Vec<Expr>,
86 partition: Vec<String>,
87 order: Vec<Cage>,
88 frame: Option<WindowFrame>,
89 },
90 Case {
92 when_clauses: Vec<(Condition, Box<Expr>)>,
94 else_value: Option<Box<Expr>>,
96 alias: Option<String>,
98 },
99 JsonAccess {
101 column: String,
103 path_segments: Vec<(String, bool)>,
107 alias: Option<String>,
109 },
110 FunctionCall {
112 name: String,
114 args: Vec<Expr>,
116 alias: Option<String>,
118 },
119 SpecialFunction {
122 name: String,
124 args: Vec<(Option<String>, Box<Expr>)>,
127 alias: Option<String>,
129 },
130 Binary {
132 left: Box<Expr>,
133 op: BinaryOp,
134 right: Box<Expr>,
135 alias: Option<String>,
136 },
137 Literal(Value),
140 ArrayConstructor {
142 elements: Vec<Expr>,
143 alias: Option<String>,
144 },
145 RowConstructor {
147 elements: Vec<Expr>,
148 alias: Option<String>,
149 },
150 Subscript {
152 expr: Box<Expr>,
153 index: Box<Expr>,
154 alias: Option<String>,
155 },
156 Collate {
158 expr: Box<Expr>,
159 collation: String,
160 alias: Option<String>,
161 },
162 FieldAccess {
164 expr: Box<Expr>,
165 field: String,
166 alias: Option<String>,
167 },
168 Subquery {
171 query: Box<super::Qail>,
172 alias: Option<String>,
173 },
174 Exists {
176 query: Box<super::Qail>,
177 negated: bool, alias: Option<String>,
179 },
180 Raw(String),
184}
185
186impl std::fmt::Display for Expr {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 match self {
189 Expr::Star => write!(f, "*"),
190 Expr::Named(name) => write!(f, "{}", name),
191 Expr::Aliased { name, alias } => write!(f, "{} AS {}", name, alias),
192 Expr::Aggregate {
193 col,
194 func,
195 distinct,
196 filter,
197 alias,
198 } => {
199 if *distinct {
200 write!(f, "{}(DISTINCT {})", func, col)?;
201 } else {
202 write!(f, "{}({})", func, col)?;
203 }
204 if let Some(conditions) = filter {
205 write!(
206 f,
207 " FILTER (WHERE {})",
208 conditions
209 .iter()
210 .map(|c| c.to_string())
211 .collect::<Vec<_>>()
212 .join(" AND ")
213 )?;
214 }
215 if let Some(a) = alias {
216 write!(f, " AS {}", a)?;
217 }
218 Ok(())
219 }
220 Expr::Cast {
221 expr,
222 target_type,
223 alias,
224 } => {
225 write!(f, "{}::{}", expr, target_type)?;
226 if let Some(a) = alias {
227 write!(f, " AS {}", a)?;
228 }
229 Ok(())
230 }
231 Expr::Def {
232 name,
233 data_type,
234 constraints,
235 } => {
236 write!(f, "{}:{}", name, data_type)?;
237 for c in constraints {
238 write!(f, "^{}", c)?;
239 }
240 Ok(())
241 }
242 Expr::Mod { kind, col } => match kind {
243 ModKind::Add => write!(f, "+{}", col),
244 ModKind::Drop => write!(f, "-{}", col),
245 },
246 Expr::Window {
247 name,
248 func,
249 params,
250 partition,
251 order,
252 frame,
253 } => {
254 write!(f, "{}:{}(", name, func)?;
255 for (i, p) in params.iter().enumerate() {
256 if i > 0 {
257 write!(f, ", ")?;
258 }
259 write!(f, "{}", p)?;
260 }
261 write!(f, ")")?;
262
263 if !partition.is_empty() {
265 write!(f, "{{Part=")?;
266 for (i, p) in partition.iter().enumerate() {
267 if i > 0 {
268 write!(f, ",")?;
269 }
270 write!(f, "{}", p)?;
271 }
272 if let Some(fr) = frame {
273 write!(f, ", Frame={:?}", fr)?; }
275 write!(f, "}}")?;
276 } else if frame.is_some() {
277 write!(f, "{{Frame={:?}}}", frame.as_ref().unwrap())?;
278 }
279
280 for _cage in order {
282 }
284 Ok(())
285 }
286 Expr::Case {
287 when_clauses,
288 else_value,
289 alias,
290 } => {
291 write!(f, "CASE")?;
292 for (cond, val) in when_clauses {
293 write!(f, " WHEN {} THEN {}", cond.left, val)?;
294 }
295 if let Some(e) = else_value {
296 write!(f, " ELSE {}", e)?;
297 }
298 write!(f, " END")?;
299 if let Some(a) = alias {
300 write!(f, " AS {}", a)?;
301 }
302 Ok(())
303 }
304 Expr::JsonAccess {
305 column,
306 path_segments,
307 alias,
308 } => {
309 write!(f, "{}", column)?;
310 for (path, as_text) in path_segments {
311 let op = if *as_text { "->>" } else { "->" };
312 if path.parse::<i64>().is_ok() {
315 write!(f, "{}{}", op, path)?;
316 } else {
317 write!(f, "{}'{}'", op, path)?;
318 }
319 }
320 if let Some(a) = alias {
321 write!(f, " AS {}", a)?;
322 }
323 Ok(())
324 }
325 Expr::FunctionCall { name, args, alias } => {
326 let args_str: Vec<String> = args.iter().map(|a| a.to_string()).collect();
327 write!(f, "{}({})", name.to_uppercase(), args_str.join(", "))?;
328 if let Some(a) = alias {
329 write!(f, " AS {}", a)?;
330 }
331 Ok(())
332 }
333 Expr::SpecialFunction { name, args, alias } => {
334 write!(f, "{}(", name.to_uppercase())?;
335 for (i, (keyword, expr)) in args.iter().enumerate() {
336 if i > 0 {
337 write!(f, " ")?;
338 }
339 if let Some(kw) = keyword {
340 write!(f, "{} ", kw)?;
341 }
342 write!(f, "{}", expr)?;
343 }
344 write!(f, ")")?;
345 if let Some(a) = alias {
346 write!(f, " AS {}", a)?;
347 }
348 Ok(())
349 }
350 Expr::Binary {
351 left,
352 op,
353 right,
354 alias,
355 } => {
356 write!(f, "({} {} {})", left, op, right)?;
357 if let Some(a) = alias {
358 write!(f, " AS {}", a)?;
359 }
360 Ok(())
361 }
362 Expr::Literal(value) => write!(f, "{}", value),
363 Expr::ArrayConstructor { elements, alias } => {
364 write!(f, "ARRAY[")?;
365 for (i, elem) in elements.iter().enumerate() {
366 if i > 0 {
367 write!(f, ", ")?;
368 }
369 write!(f, "{}", elem)?;
370 }
371 write!(f, "]")?;
372 if let Some(a) = alias {
373 write!(f, " AS {}", a)?;
374 }
375 Ok(())
376 }
377 Expr::RowConstructor { elements, alias } => {
378 write!(f, "ROW(")?;
379 for (i, elem) in elements.iter().enumerate() {
380 if i > 0 {
381 write!(f, ", ")?;
382 }
383 write!(f, "{}", elem)?;
384 }
385 write!(f, ")")?;
386 if let Some(a) = alias {
387 write!(f, " AS {}", a)?;
388 }
389 Ok(())
390 }
391 Expr::Subscript { expr, index, alias } => {
392 write!(f, "{}[{}]", expr, index)?;
393 if let Some(a) = alias {
394 write!(f, " AS {}", a)?;
395 }
396 Ok(())
397 }
398 Expr::Collate { expr, collation, alias } => {
399 write!(f, "{} COLLATE \"{}\"", expr, collation)?;
400 if let Some(a) = alias {
401 write!(f, " AS {}", a)?;
402 }
403 Ok(())
404 }
405 Expr::FieldAccess { expr, field, alias } => {
406 write!(f, "({}).{}", expr, field)?;
407 if let Some(a) = alias {
408 write!(f, " AS {}", a)?;
409 }
410 Ok(())
411 }
412 Expr::Subquery { query, alias } => {
413 write!(f, "({})", query)?;
414 if let Some(a) = alias {
415 write!(f, " AS {}", a)?;
416 }
417 Ok(())
418 }
419 Expr::Exists { query, negated, alias } => {
420 if *negated {
421 write!(f, "NOT ")?;
422 }
423 write!(f, "EXISTS ({})", query)?;
424 if let Some(a) = alias {
425 write!(f, " AS {}", a)?;
426 }
427 Ok(())
428 }
429 Expr::Raw(sql) => write!(f, "{}", sql),
430 }
431 }
432}
433
434#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
435pub enum Constraint {
436 PrimaryKey,
437 Unique,
438 Nullable,
439 Default(String),
440 Check(Vec<String>),
441 Comment(String),
442 References(String),
443 Generated(ColumnGeneration),
444}
445
446#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
448pub enum ColumnGeneration {
449 Stored(String),
451 Virtual(String),
453}
454
455#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
457pub enum WindowFrame {
458 Rows { start: FrameBound, end: FrameBound },
460 Range { start: FrameBound, end: FrameBound },
462}
463
464#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
466pub enum FrameBound {
467 UnboundedPreceding,
468 Preceding(i32),
469 CurrentRow,
470 Following(i32),
471 UnboundedFollowing,
472}
473
474impl std::fmt::Display for Constraint {
475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
476 match self {
477 Constraint::PrimaryKey => write!(f, "pk"),
478 Constraint::Unique => write!(f, "uniq"),
479 Constraint::Nullable => write!(f, "?"),
480 Constraint::Default(val) => write!(f, "={}", val),
481 Constraint::Check(vals) => write!(f, "check({})", vals.join(",")),
482 Constraint::Comment(text) => write!(f, "comment(\"{}\")", text),
483 Constraint::References(target) => write!(f, "ref({})", target),
484 Constraint::Generated(generation) => match generation {
485 ColumnGeneration::Stored(expr) => write!(f, "gen({})", expr),
486 ColumnGeneration::Virtual(expr) => write!(f, "vgen({})", expr),
487 },
488 }
489 }
490}
491
492#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
494pub struct IndexDef {
495 pub name: String,
497 pub table: String,
499 pub columns: Vec<String>,
501 pub unique: bool,
502 #[serde(default)]
504 pub index_type: Option<String>,
505}
506
507#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
509pub enum TableConstraint {
510 Unique(Vec<String>),
511 PrimaryKey(Vec<String>),
512}
513
514impl From<&str> for Expr {
517 fn from(s: &str) -> Self {
520 Expr::Named(s.to_string())
521 }
522}
523
524impl From<String> for Expr {
525 fn from(s: String) -> Self {
526 Expr::Named(s)
527 }
528}
529
530impl From<&String> for Expr {
531 fn from(s: &String) -> Self {
532 Expr::Named(s.clone())
533 }
534}
535
536#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
540pub struct FunctionDef {
541 pub name: String,
542 pub returns: String, pub body: String, pub language: Option<String>, }
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
549pub enum TriggerTiming {
550 Before,
551 After,
552 InsteadOf,
553}
554
555#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
557pub enum TriggerEvent {
558 Insert,
559 Update,
560 Delete,
561 Truncate,
562}
563
564#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
566pub struct TriggerDef {
567 pub name: String,
568 pub table: String,
569 pub timing: TriggerTiming,
570 pub events: Vec<TriggerEvent>,
571 pub for_each_row: bool,
572 pub execute_function: String,
573}
574