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}
181
182impl std::fmt::Display for Expr {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 match self {
185 Expr::Star => write!(f, "*"),
186 Expr::Named(name) => write!(f, "{}", name),
187 Expr::Aliased { name, alias } => write!(f, "{} AS {}", name, alias),
188 Expr::Aggregate {
189 col,
190 func,
191 distinct,
192 filter,
193 alias,
194 } => {
195 if *distinct {
196 write!(f, "{}(DISTINCT {})", func, col)?;
197 } else {
198 write!(f, "{}({})", func, col)?;
199 }
200 if let Some(conditions) = filter {
201 write!(
202 f,
203 " FILTER (WHERE {})",
204 conditions
205 .iter()
206 .map(|c| c.to_string())
207 .collect::<Vec<_>>()
208 .join(" AND ")
209 )?;
210 }
211 if let Some(a) = alias {
212 write!(f, " AS {}", a)?;
213 }
214 Ok(())
215 }
216 Expr::Cast {
217 expr,
218 target_type,
219 alias,
220 } => {
221 write!(f, "{}::{}", expr, target_type)?;
222 if let Some(a) = alias {
223 write!(f, " AS {}", a)?;
224 }
225 Ok(())
226 }
227 Expr::Def {
228 name,
229 data_type,
230 constraints,
231 } => {
232 write!(f, "{}:{}", name, data_type)?;
233 for c in constraints {
234 write!(f, "^{}", c)?;
235 }
236 Ok(())
237 }
238 Expr::Mod { kind, col } => match kind {
239 ModKind::Add => write!(f, "+{}", col),
240 ModKind::Drop => write!(f, "-{}", col),
241 },
242 Expr::Window {
243 name,
244 func,
245 params,
246 partition,
247 order,
248 frame,
249 } => {
250 write!(f, "{}:{}(", name, func)?;
251 for (i, p) in params.iter().enumerate() {
252 if i > 0 {
253 write!(f, ", ")?;
254 }
255 write!(f, "{}", p)?;
256 }
257 write!(f, ")")?;
258
259 if !partition.is_empty() {
261 write!(f, "{{Part=")?;
262 for (i, p) in partition.iter().enumerate() {
263 if i > 0 {
264 write!(f, ",")?;
265 }
266 write!(f, "{}", p)?;
267 }
268 if let Some(fr) = frame {
269 write!(f, ", Frame={:?}", fr)?; }
271 write!(f, "}}")?;
272 } else if frame.is_some() {
273 write!(f, "{{Frame={:?}}}", frame.as_ref().unwrap())?;
274 }
275
276 for _cage in order {
278 }
280 Ok(())
281 }
282 Expr::Case {
283 when_clauses,
284 else_value,
285 alias,
286 } => {
287 write!(f, "CASE")?;
288 for (cond, val) in when_clauses {
289 write!(f, " WHEN {} THEN {}", cond.left, val)?;
290 }
291 if let Some(e) = else_value {
292 write!(f, " ELSE {}", e)?;
293 }
294 write!(f, " END")?;
295 if let Some(a) = alias {
296 write!(f, " AS {}", a)?;
297 }
298 Ok(())
299 }
300 Expr::JsonAccess {
301 column,
302 path_segments,
303 alias,
304 } => {
305 write!(f, "{}", column)?;
306 for (path, as_text) in path_segments {
307 let op = if *as_text { "->>" } else { "->" };
308 if path.parse::<i64>().is_ok() {
311 write!(f, "{}{}", op, path)?;
312 } else {
313 write!(f, "{}'{}'", op, path)?;
314 }
315 }
316 if let Some(a) = alias {
317 write!(f, " AS {}", a)?;
318 }
319 Ok(())
320 }
321 Expr::FunctionCall { name, args, alias } => {
322 let args_str: Vec<String> = args.iter().map(|a| a.to_string()).collect();
323 write!(f, "{}({})", name.to_uppercase(), args_str.join(", "))?;
324 if let Some(a) = alias {
325 write!(f, " AS {}", a)?;
326 }
327 Ok(())
328 }
329 Expr::SpecialFunction { name, args, alias } => {
330 write!(f, "{}(", name.to_uppercase())?;
331 for (i, (keyword, expr)) in args.iter().enumerate() {
332 if i > 0 {
333 write!(f, " ")?;
334 }
335 if let Some(kw) = keyword {
336 write!(f, "{} ", kw)?;
337 }
338 write!(f, "{}", expr)?;
339 }
340 write!(f, ")")?;
341 if let Some(a) = alias {
342 write!(f, " AS {}", a)?;
343 }
344 Ok(())
345 }
346 Expr::Binary {
347 left,
348 op,
349 right,
350 alias,
351 } => {
352 write!(f, "({} {} {})", left, op, right)?;
353 if let Some(a) = alias {
354 write!(f, " AS {}", a)?;
355 }
356 Ok(())
357 }
358 Expr::Literal(value) => write!(f, "{}", value),
359 Expr::ArrayConstructor { elements, alias } => {
360 write!(f, "ARRAY[")?;
361 for (i, elem) in elements.iter().enumerate() {
362 if i > 0 {
363 write!(f, ", ")?;
364 }
365 write!(f, "{}", elem)?;
366 }
367 write!(f, "]")?;
368 if let Some(a) = alias {
369 write!(f, " AS {}", a)?;
370 }
371 Ok(())
372 }
373 Expr::RowConstructor { elements, alias } => {
374 write!(f, "ROW(")?;
375 for (i, elem) in elements.iter().enumerate() {
376 if i > 0 {
377 write!(f, ", ")?;
378 }
379 write!(f, "{}", elem)?;
380 }
381 write!(f, ")")?;
382 if let Some(a) = alias {
383 write!(f, " AS {}", a)?;
384 }
385 Ok(())
386 }
387 Expr::Subscript { expr, index, alias } => {
388 write!(f, "{}[{}]", expr, index)?;
389 if let Some(a) = alias {
390 write!(f, " AS {}", a)?;
391 }
392 Ok(())
393 }
394 Expr::Collate { expr, collation, alias } => {
395 write!(f, "{} COLLATE \"{}\"", expr, collation)?;
396 if let Some(a) = alias {
397 write!(f, " AS {}", a)?;
398 }
399 Ok(())
400 }
401 Expr::FieldAccess { expr, field, alias } => {
402 write!(f, "({}).{}", expr, field)?;
403 if let Some(a) = alias {
404 write!(f, " AS {}", a)?;
405 }
406 Ok(())
407 }
408 Expr::Subquery { query, alias } => {
409 write!(f, "({})", query)?;
410 if let Some(a) = alias {
411 write!(f, " AS {}", a)?;
412 }
413 Ok(())
414 }
415 Expr::Exists { query, negated, alias } => {
416 if *negated {
417 write!(f, "NOT ")?;
418 }
419 write!(f, "EXISTS ({})", query)?;
420 if let Some(a) = alias {
421 write!(f, " AS {}", a)?;
422 }
423 Ok(())
424 }
425 }
426 }
427}
428
429#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub enum Constraint {
431 PrimaryKey,
432 Unique,
433 Nullable,
434 Default(String),
435 Check(Vec<String>),
436 Comment(String),
437 References(String),
438 Generated(ColumnGeneration),
439}
440
441#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
443pub enum ColumnGeneration {
444 Stored(String),
446 Virtual(String),
448}
449
450#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
452pub enum WindowFrame {
453 Rows { start: FrameBound, end: FrameBound },
455 Range { start: FrameBound, end: FrameBound },
457}
458
459#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
461pub enum FrameBound {
462 UnboundedPreceding,
463 Preceding(i32),
464 CurrentRow,
465 Following(i32),
466 UnboundedFollowing,
467}
468
469impl std::fmt::Display for Constraint {
470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 match self {
472 Constraint::PrimaryKey => write!(f, "pk"),
473 Constraint::Unique => write!(f, "uniq"),
474 Constraint::Nullable => write!(f, "?"),
475 Constraint::Default(val) => write!(f, "={}", val),
476 Constraint::Check(vals) => write!(f, "check({})", vals.join(",")),
477 Constraint::Comment(text) => write!(f, "comment(\"{}\")", text),
478 Constraint::References(target) => write!(f, "ref({})", target),
479 Constraint::Generated(generation) => match generation {
480 ColumnGeneration::Stored(expr) => write!(f, "gen({})", expr),
481 ColumnGeneration::Virtual(expr) => write!(f, "vgen({})", expr),
482 },
483 }
484 }
485}
486
487#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
489pub struct IndexDef {
490 pub name: String,
492 pub table: String,
494 pub columns: Vec<String>,
496 pub unique: bool,
497 #[serde(default)]
499 pub index_type: Option<String>,
500}
501
502#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
504pub enum TableConstraint {
505 Unique(Vec<String>),
506 PrimaryKey(Vec<String>),
507}
508
509impl From<&str> for Expr {
512 fn from(s: &str) -> Self {
515 Expr::Named(s.to_string())
516 }
517}
518
519impl From<String> for Expr {
520 fn from(s: String) -> Self {
521 Expr::Named(s)
522 }
523}
524
525impl From<&String> for Expr {
526 fn from(s: &String) -> Self {
527 Expr::Named(s.clone())
528 }
529}
530
531#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
535pub struct FunctionDef {
536 pub name: String,
537 pub returns: String, pub body: String, pub language: Option<String>, }
541
542#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
544pub enum TriggerTiming {
545 Before,
546 After,
547 InsteadOf,
548}
549
550#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
552pub enum TriggerEvent {
553 Insert,
554 Update,
555 Delete,
556 Truncate,
557}
558
559#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
561pub struct TriggerDef {
562 pub name: String,
563 pub table: String,
564 pub timing: TriggerTiming,
565 pub events: Vec<TriggerEvent>,
566 pub for_each_row: bool,
567 pub execute_function: String,
568}
569