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,
8 Add,
9 Sub,
10 Mul,
11 Div,
12 Rem,
14}
15
16impl std::fmt::Display for BinaryOp {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 BinaryOp::Concat => write!(f, "||"),
20 BinaryOp::Add => write!(f, "+"),
21 BinaryOp::Sub => write!(f, "-"),
22 BinaryOp::Mul => write!(f, "*"),
23 BinaryOp::Div => write!(f, "/"),
24 BinaryOp::Rem => write!(f, "%"),
25 }
26 }
27}
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29pub enum Expr {
30 Star,
32 Named(String),
33 Aliased { name: String, alias: String },
35 Aggregate {
37 col: String,
38 func: AggregateFunc,
39 distinct: bool,
40 filter: Option<Vec<Condition>>,
42 alias: Option<String>,
43 },
44 Cast {
46 expr: Box<Expr>,
47 target_type: String,
48 alias: Option<String>,
49 },
50 Def {
51 name: String,
52 data_type: String,
53 constraints: Vec<Constraint>,
54 },
55 Mod { kind: ModKind, col: Box<Expr> },
56 Window {
58 name: String,
59 func: String,
60 params: Vec<Expr>,
62 partition: Vec<String>,
63 order: Vec<Cage>,
64 frame: Option<WindowFrame>,
65 },
66 Case {
68 when_clauses: Vec<(Condition, Box<Expr>)>,
70 else_value: Option<Box<Expr>>,
72 alias: Option<String>,
74 },
75 JsonAccess {
77 column: String,
79 path_segments: Vec<(String, bool)>,
83 alias: Option<String>,
85 },
86 FunctionCall {
88 name: String,
90 args: Vec<Expr>,
92 alias: Option<String>,
94 },
95 SpecialFunction {
98 name: String,
100 args: Vec<(Option<String>, Box<Expr>)>,
103 alias: Option<String>,
105 },
106 Binary {
108 left: Box<Expr>,
109 op: BinaryOp,
110 right: Box<Expr>,
111 alias: Option<String>,
112 },
113 Literal(Value),
116 ArrayConstructor {
118 elements: Vec<Expr>,
119 alias: Option<String>,
120 },
121 RowConstructor {
123 elements: Vec<Expr>,
124 alias: Option<String>,
125 },
126 Subscript {
128 expr: Box<Expr>,
129 index: Box<Expr>,
130 alias: Option<String>,
131 },
132 Collate {
134 expr: Box<Expr>,
135 collation: String,
136 alias: Option<String>,
137 },
138 FieldAccess {
140 expr: Box<Expr>,
141 field: String,
142 alias: Option<String>,
143 },
144}
145
146impl std::fmt::Display for Expr {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 match self {
149 Expr::Star => write!(f, "*"),
150 Expr::Named(name) => write!(f, "{}", name),
151 Expr::Aliased { name, alias } => write!(f, "{} AS {}", name, alias),
152 Expr::Aggregate {
153 col,
154 func,
155 distinct,
156 filter,
157 alias,
158 } => {
159 if *distinct {
160 write!(f, "{}(DISTINCT {})", func, col)?;
161 } else {
162 write!(f, "{}({})", func, col)?;
163 }
164 if let Some(conditions) = filter {
165 write!(
166 f,
167 " FILTER (WHERE {})",
168 conditions
169 .iter()
170 .map(|c| c.to_string())
171 .collect::<Vec<_>>()
172 .join(" AND ")
173 )?;
174 }
175 if let Some(a) = alias {
176 write!(f, " AS {}", a)?;
177 }
178 Ok(())
179 }
180 Expr::Cast {
181 expr,
182 target_type,
183 alias,
184 } => {
185 write!(f, "{}::{}", expr, target_type)?;
186 if let Some(a) = alias {
187 write!(f, " AS {}", a)?;
188 }
189 Ok(())
190 }
191 Expr::Def {
192 name,
193 data_type,
194 constraints,
195 } => {
196 write!(f, "{}:{}", name, data_type)?;
197 for c in constraints {
198 write!(f, "^{}", c)?;
199 }
200 Ok(())
201 }
202 Expr::Mod { kind, col } => match kind {
203 ModKind::Add => write!(f, "+{}", col),
204 ModKind::Drop => write!(f, "-{}", col),
205 },
206 Expr::Window {
207 name,
208 func,
209 params,
210 partition,
211 order,
212 frame,
213 } => {
214 write!(f, "{}:{}(", name, func)?;
215 for (i, p) in params.iter().enumerate() {
216 if i > 0 {
217 write!(f, ", ")?;
218 }
219 write!(f, "{}", p)?;
220 }
221 write!(f, ")")?;
222
223 if !partition.is_empty() {
225 write!(f, "{{Part=")?;
226 for (i, p) in partition.iter().enumerate() {
227 if i > 0 {
228 write!(f, ",")?;
229 }
230 write!(f, "{}", p)?;
231 }
232 if let Some(fr) = frame {
233 write!(f, ", Frame={:?}", fr)?; }
235 write!(f, "}}")?;
236 } else if frame.is_some() {
237 write!(f, "{{Frame={:?}}}", frame.as_ref().unwrap())?;
238 }
239
240 for _cage in order {
242 }
244 Ok(())
245 }
246 Expr::Case {
247 when_clauses,
248 else_value,
249 alias,
250 } => {
251 write!(f, "CASE")?;
252 for (cond, val) in when_clauses {
253 write!(f, " WHEN {} THEN {}", cond.left, val)?;
254 }
255 if let Some(e) = else_value {
256 write!(f, " ELSE {}", e)?;
257 }
258 write!(f, " END")?;
259 if let Some(a) = alias {
260 write!(f, " AS {}", a)?;
261 }
262 Ok(())
263 }
264 Expr::JsonAccess {
265 column,
266 path_segments,
267 alias,
268 } => {
269 write!(f, "{}", column)?;
270 for (path, as_text) in path_segments {
271 let op = if *as_text { "->>" } else { "->" };
272 if path.parse::<i64>().is_ok() {
275 write!(f, "{}{}", op, path)?;
276 } else {
277 write!(f, "{}'{}'", op, path)?;
278 }
279 }
280 if let Some(a) = alias {
281 write!(f, " AS {}", a)?;
282 }
283 Ok(())
284 }
285 Expr::FunctionCall { name, args, alias } => {
286 let args_str: Vec<String> = args.iter().map(|a| a.to_string()).collect();
287 write!(f, "{}({})", name.to_uppercase(), args_str.join(", "))?;
288 if let Some(a) = alias {
289 write!(f, " AS {}", a)?;
290 }
291 Ok(())
292 }
293 Expr::SpecialFunction { name, args, alias } => {
294 write!(f, "{}(", name.to_uppercase())?;
295 for (i, (keyword, expr)) in args.iter().enumerate() {
296 if i > 0 {
297 write!(f, " ")?;
298 }
299 if let Some(kw) = keyword {
300 write!(f, "{} ", kw)?;
301 }
302 write!(f, "{}", expr)?;
303 }
304 write!(f, ")")?;
305 if let Some(a) = alias {
306 write!(f, " AS {}", a)?;
307 }
308 Ok(())
309 }
310 Expr::Binary {
311 left,
312 op,
313 right,
314 alias,
315 } => {
316 write!(f, "({} {} {})", left, op, right)?;
317 if let Some(a) = alias {
318 write!(f, " AS {}", a)?;
319 }
320 Ok(())
321 }
322 Expr::Literal(value) => write!(f, "{}", value),
323 Expr::ArrayConstructor { elements, alias } => {
324 write!(f, "ARRAY[")?;
325 for (i, elem) in elements.iter().enumerate() {
326 if i > 0 {
327 write!(f, ", ")?;
328 }
329 write!(f, "{}", elem)?;
330 }
331 write!(f, "]")?;
332 if let Some(a) = alias {
333 write!(f, " AS {}", a)?;
334 }
335 Ok(())
336 }
337 Expr::RowConstructor { elements, alias } => {
338 write!(f, "ROW(")?;
339 for (i, elem) in elements.iter().enumerate() {
340 if i > 0 {
341 write!(f, ", ")?;
342 }
343 write!(f, "{}", elem)?;
344 }
345 write!(f, ")")?;
346 if let Some(a) = alias {
347 write!(f, " AS {}", a)?;
348 }
349 Ok(())
350 }
351 Expr::Subscript { expr, index, alias } => {
352 write!(f, "{}[{}]", expr, index)?;
353 if let Some(a) = alias {
354 write!(f, " AS {}", a)?;
355 }
356 Ok(())
357 }
358 Expr::Collate { expr, collation, alias } => {
359 write!(f, "{} COLLATE \"{}\"", expr, collation)?;
360 if let Some(a) = alias {
361 write!(f, " AS {}", a)?;
362 }
363 Ok(())
364 }
365 Expr::FieldAccess { expr, field, alias } => {
366 write!(f, "({}).{}", expr, field)?;
367 if let Some(a) = alias {
368 write!(f, " AS {}", a)?;
369 }
370 Ok(())
371 }
372 }
373 }
374}
375
376#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
377pub enum Constraint {
378 PrimaryKey,
379 Unique,
380 Nullable,
381 Default(String),
382 Check(Vec<String>),
383 Comment(String),
384 References(String),
385 Generated(ColumnGeneration),
386}
387
388#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
390pub enum ColumnGeneration {
391 Stored(String),
393 Virtual(String),
395}
396
397#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
399pub enum WindowFrame {
400 Rows { start: FrameBound, end: FrameBound },
402 Range { start: FrameBound, end: FrameBound },
404}
405
406#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
408pub enum FrameBound {
409 UnboundedPreceding,
410 Preceding(i32),
411 CurrentRow,
412 Following(i32),
413 UnboundedFollowing,
414}
415
416impl std::fmt::Display for Constraint {
417 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
418 match self {
419 Constraint::PrimaryKey => write!(f, "pk"),
420 Constraint::Unique => write!(f, "uniq"),
421 Constraint::Nullable => write!(f, "?"),
422 Constraint::Default(val) => write!(f, "={}", val),
423 Constraint::Check(vals) => write!(f, "check({})", vals.join(",")),
424 Constraint::Comment(text) => write!(f, "comment(\"{}\")", text),
425 Constraint::References(target) => write!(f, "ref({})", target),
426 Constraint::Generated(generation) => match generation {
427 ColumnGeneration::Stored(expr) => write!(f, "gen({})", expr),
428 ColumnGeneration::Virtual(expr) => write!(f, "vgen({})", expr),
429 },
430 }
431 }
432}
433
434#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
436pub struct IndexDef {
437 pub name: String,
439 pub table: String,
441 pub columns: Vec<String>,
443 pub unique: bool,
444}
445
446#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
448pub enum TableConstraint {
449 Unique(Vec<String>),
450 PrimaryKey(Vec<String>),
451}
452
453impl From<&str> for Expr {
456 fn from(s: &str) -> Self {
459 Expr::Named(s.to_string())
460 }
461}
462
463impl From<String> for Expr {
464 fn from(s: String) -> Self {
465 Expr::Named(s)
466 }
467}
468
469impl From<&String> for Expr {
470 fn from(s: &String) -> Self {
471 Expr::Named(s.clone())
472 }
473}