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,
11 Sub,
13 Mul,
15 Div,
17 Rem,
19}
20
21impl std::fmt::Display for BinaryOp {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 BinaryOp::Concat => write!(f, "||"),
25 BinaryOp::Add => write!(f, "+"),
26 BinaryOp::Sub => write!(f, "-"),
27 BinaryOp::Mul => write!(f, "*"),
28 BinaryOp::Div => write!(f, "/"),
29 BinaryOp::Rem => write!(f, "%"),
30 }
31 }
32}
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub enum Expr {
37 Star,
39 Named(String),
41 Aliased { name: String, alias: String },
43 Aggregate {
45 col: String,
46 func: AggregateFunc,
47 distinct: bool,
49 filter: Option<Vec<Condition>>,
51 alias: Option<String>,
52 },
53 Cast {
55 expr: Box<Expr>,
56 target_type: String,
57 alias: Option<String>,
58 },
59 Def {
61 name: String,
62 data_type: String,
63 constraints: Vec<Constraint>,
64 },
65 Mod { kind: ModKind, col: Box<Expr> },
67 Window {
69 name: String,
70 func: String,
71 params: Vec<Value>,
72 partition: Vec<String>,
73 order: Vec<Cage>,
74 frame: Option<WindowFrame>,
75 },
76 Case {
78 when_clauses: Vec<(Condition, Box<Expr>)>,
80 else_value: Option<Box<Expr>>,
82 alias: Option<String>,
84 },
85 JsonAccess {
87 column: String,
89 path_segments: Vec<(String, bool)>,
93 alias: Option<String>,
95 },
96 FunctionCall {
98 name: String,
100 args: Vec<Expr>,
102 alias: Option<String>,
104 },
105 SpecialFunction {
108 name: String,
110 args: Vec<(Option<String>, Box<Expr>)>,
113 alias: Option<String>,
115 },
116 Binary {
118 left: Box<Expr>,
119 op: BinaryOp,
120 right: Box<Expr>,
121 alias: Option<String>,
122 },
123 Literal(Value),
126}
127
128impl std::fmt::Display for Expr {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 match self {
131 Expr::Star => write!(f, "*"),
132 Expr::Named(name) => write!(f, "{}", name),
133 Expr::Aliased { name, alias } => write!(f, "{} AS {}", name, alias),
134 Expr::Aggregate {
135 col,
136 func,
137 distinct,
138 filter,
139 alias,
140 } => {
141 if *distinct {
142 write!(f, "{}(DISTINCT {})", func, col)?;
143 } else {
144 write!(f, "{}({})", func, col)?;
145 }
146 if let Some(conditions) = filter {
147 write!(
148 f,
149 " FILTER (WHERE {})",
150 conditions
151 .iter()
152 .map(|c| c.to_string())
153 .collect::<Vec<_>>()
154 .join(" AND ")
155 )?;
156 }
157 if let Some(a) = alias {
158 write!(f, " AS {}", a)?;
159 }
160 Ok(())
161 }
162 Expr::Cast {
163 expr,
164 target_type,
165 alias,
166 } => {
167 write!(f, "{}::{}", expr, target_type)?;
168 if let Some(a) = alias {
169 write!(f, " AS {}", a)?;
170 }
171 Ok(())
172 }
173 Expr::Def {
174 name,
175 data_type,
176 constraints,
177 } => {
178 write!(f, "{}:{}", name, data_type)?;
179 for c in constraints {
180 write!(f, "^{}", c)?;
181 }
182 Ok(())
183 }
184 Expr::Mod { kind, col } => match kind {
185 ModKind::Add => write!(f, "+{}", col),
186 ModKind::Drop => write!(f, "-{}", col),
187 },
188 Expr::Window {
189 name,
190 func,
191 params,
192 partition,
193 order,
194 frame,
195 } => {
196 write!(f, "{}:{}(", name, func)?;
197 for (i, p) in params.iter().enumerate() {
198 if i > 0 {
199 write!(f, ", ")?;
200 }
201 write!(f, "{}", p)?;
202 }
203 write!(f, ")")?;
204
205 if !partition.is_empty() {
207 write!(f, "{{Part=")?;
208 for (i, p) in partition.iter().enumerate() {
209 if i > 0 {
210 write!(f, ",")?;
211 }
212 write!(f, "{}", p)?;
213 }
214 if let Some(fr) = frame {
215 write!(f, ", Frame={:?}", fr)?; }
217 write!(f, "}}")?;
218 } else if frame.is_some() {
219 write!(f, "{{Frame={:?}}}", frame.as_ref().unwrap())?;
220 }
221
222 for _cage in order {
224 }
226 Ok(())
227 }
228 Expr::Case {
229 when_clauses,
230 else_value,
231 alias,
232 } => {
233 write!(f, "CASE")?;
234 for (cond, val) in when_clauses {
235 write!(f, " WHEN {} THEN {}", cond.left, val)?;
236 }
237 if let Some(e) = else_value {
238 write!(f, " ELSE {}", e)?;
239 }
240 write!(f, " END")?;
241 if let Some(a) = alias {
242 write!(f, " AS {}", a)?;
243 }
244 Ok(())
245 }
246 Expr::JsonAccess {
247 column,
248 path_segments,
249 alias,
250 } => {
251 write!(f, "{}", column)?;
252 for (path, as_text) in path_segments {
253 let op = if *as_text { "->>" } else { "->" };
254 if path.parse::<i64>().is_ok() {
257 write!(f, "{}{}", op, path)?;
258 } else {
259 write!(f, "{}'{}'", op, path)?;
260 }
261 }
262 if let Some(a) = alias {
263 write!(f, " AS {}", a)?;
264 }
265 Ok(())
266 }
267 Expr::FunctionCall { name, args, alias } => {
268 let args_str: Vec<String> = args.iter().map(|a| a.to_string()).collect();
269 write!(f, "{}({})", name.to_uppercase(), args_str.join(", "))?;
270 if let Some(a) = alias {
271 write!(f, " AS {}", a)?;
272 }
273 Ok(())
274 }
275 Expr::SpecialFunction { name, args, alias } => {
276 write!(f, "{}(", name.to_uppercase())?;
277 for (i, (keyword, expr)) in args.iter().enumerate() {
278 if i > 0 {
279 write!(f, " ")?;
280 }
281 if let Some(kw) = keyword {
282 write!(f, "{} ", kw)?;
283 }
284 write!(f, "{}", expr)?;
285 }
286 write!(f, ")")?;
287 if let Some(a) = alias {
288 write!(f, " AS {}", a)?;
289 }
290 Ok(())
291 }
292 Expr::Binary {
293 left,
294 op,
295 right,
296 alias,
297 } => {
298 write!(f, "({} {} {})", left, op, right)?;
299 if let Some(a) = alias {
300 write!(f, " AS {}", a)?;
301 }
302 Ok(())
303 }
304 Expr::Literal(value) => write!(f, "{}", value),
305 }
306 }
307}
308
309#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
311pub enum Constraint {
312 PrimaryKey,
313 Unique,
314 Nullable,
315 Default(String),
317 Check(Vec<String>),
319 Comment(String),
321 References(String),
323 Generated(ColumnGeneration),
325}
326
327#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
329pub enum ColumnGeneration {
330 Stored(String),
332 Virtual(String),
334}
335
336#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
338pub enum WindowFrame {
339 Rows { start: FrameBound, end: FrameBound },
341 Range { start: FrameBound, end: FrameBound },
343}
344
345#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
347pub enum FrameBound {
348 UnboundedPreceding,
349 Preceding(i32),
350 CurrentRow,
351 Following(i32),
352 UnboundedFollowing,
353}
354
355impl std::fmt::Display for Constraint {
356 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
357 match self {
358 Constraint::PrimaryKey => write!(f, "pk"),
359 Constraint::Unique => write!(f, "uniq"),
360 Constraint::Nullable => write!(f, "?"),
361 Constraint::Default(val) => write!(f, "={}", val),
362 Constraint::Check(vals) => write!(f, "check({})", vals.join(",")),
363 Constraint::Comment(text) => write!(f, "comment(\"{}\")", text),
364 Constraint::References(target) => write!(f, "ref({})", target),
365 Constraint::Generated(generation) => match generation {
366 ColumnGeneration::Stored(expr) => write!(f, "gen({})", expr),
367 ColumnGeneration::Virtual(expr) => write!(f, "vgen({})", expr),
368 },
369 }
370 }
371}
372
373#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
375pub struct IndexDef {
376 pub name: String,
378 pub table: String,
380 pub columns: Vec<String>,
382 pub unique: bool,
384}
385
386#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
388pub enum TableConstraint {
389 Unique(Vec<String>),
391 PrimaryKey(Vec<String>),
393}
394
395impl From<&str> for Expr {
398 fn from(s: &str) -> Self {
401 Expr::Named(s.to_string())
402 }
403}
404
405impl From<String> for Expr {
406 fn from(s: String) -> Self {
407 Expr::Named(s)
408 }
409}
410
411impl From<&String> for Expr {
412 fn from(s: &String) -> Self {
413 Expr::Named(s.clone())
414 }
415}