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<Value>,
61 partition: Vec<String>,
62 order: Vec<Cage>,
63 frame: Option<WindowFrame>,
64 },
65 Case {
67 when_clauses: Vec<(Condition, Box<Expr>)>,
69 else_value: Option<Box<Expr>>,
71 alias: Option<String>,
73 },
74 JsonAccess {
76 column: String,
78 path_segments: Vec<(String, bool)>,
82 alias: Option<String>,
84 },
85 FunctionCall {
87 name: String,
89 args: Vec<Expr>,
91 alias: Option<String>,
93 },
94 SpecialFunction {
97 name: String,
99 args: Vec<(Option<String>, Box<Expr>)>,
102 alias: Option<String>,
104 },
105 Binary {
107 left: Box<Expr>,
108 op: BinaryOp,
109 right: Box<Expr>,
110 alias: Option<String>,
111 },
112 Literal(Value),
115}
116
117impl std::fmt::Display for Expr {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 match self {
120 Expr::Star => write!(f, "*"),
121 Expr::Named(name) => write!(f, "{}", name),
122 Expr::Aliased { name, alias } => write!(f, "{} AS {}", name, alias),
123 Expr::Aggregate {
124 col,
125 func,
126 distinct,
127 filter,
128 alias,
129 } => {
130 if *distinct {
131 write!(f, "{}(DISTINCT {})", func, col)?;
132 } else {
133 write!(f, "{}({})", func, col)?;
134 }
135 if let Some(conditions) = filter {
136 write!(
137 f,
138 " FILTER (WHERE {})",
139 conditions
140 .iter()
141 .map(|c| c.to_string())
142 .collect::<Vec<_>>()
143 .join(" AND ")
144 )?;
145 }
146 if let Some(a) = alias {
147 write!(f, " AS {}", a)?;
148 }
149 Ok(())
150 }
151 Expr::Cast {
152 expr,
153 target_type,
154 alias,
155 } => {
156 write!(f, "{}::{}", expr, target_type)?;
157 if let Some(a) = alias {
158 write!(f, " AS {}", a)?;
159 }
160 Ok(())
161 }
162 Expr::Def {
163 name,
164 data_type,
165 constraints,
166 } => {
167 write!(f, "{}:{}", name, data_type)?;
168 for c in constraints {
169 write!(f, "^{}", c)?;
170 }
171 Ok(())
172 }
173 Expr::Mod { kind, col } => match kind {
174 ModKind::Add => write!(f, "+{}", col),
175 ModKind::Drop => write!(f, "-{}", col),
176 },
177 Expr::Window {
178 name,
179 func,
180 params,
181 partition,
182 order,
183 frame,
184 } => {
185 write!(f, "{}:{}(", name, func)?;
186 for (i, p) in params.iter().enumerate() {
187 if i > 0 {
188 write!(f, ", ")?;
189 }
190 write!(f, "{}", p)?;
191 }
192 write!(f, ")")?;
193
194 if !partition.is_empty() {
196 write!(f, "{{Part=")?;
197 for (i, p) in partition.iter().enumerate() {
198 if i > 0 {
199 write!(f, ",")?;
200 }
201 write!(f, "{}", p)?;
202 }
203 if let Some(fr) = frame {
204 write!(f, ", Frame={:?}", fr)?; }
206 write!(f, "}}")?;
207 } else if frame.is_some() {
208 write!(f, "{{Frame={:?}}}", frame.as_ref().unwrap())?;
209 }
210
211 for _cage in order {
213 }
215 Ok(())
216 }
217 Expr::Case {
218 when_clauses,
219 else_value,
220 alias,
221 } => {
222 write!(f, "CASE")?;
223 for (cond, val) in when_clauses {
224 write!(f, " WHEN {} THEN {}", cond.left, val)?;
225 }
226 if let Some(e) = else_value {
227 write!(f, " ELSE {}", e)?;
228 }
229 write!(f, " END")?;
230 if let Some(a) = alias {
231 write!(f, " AS {}", a)?;
232 }
233 Ok(())
234 }
235 Expr::JsonAccess {
236 column,
237 path_segments,
238 alias,
239 } => {
240 write!(f, "{}", column)?;
241 for (path, as_text) in path_segments {
242 let op = if *as_text { "->>" } else { "->" };
243 if path.parse::<i64>().is_ok() {
246 write!(f, "{}{}", op, path)?;
247 } else {
248 write!(f, "{}'{}'", op, path)?;
249 }
250 }
251 if let Some(a) = alias {
252 write!(f, " AS {}", a)?;
253 }
254 Ok(())
255 }
256 Expr::FunctionCall { name, args, alias } => {
257 let args_str: Vec<String> = args.iter().map(|a| a.to_string()).collect();
258 write!(f, "{}({})", name.to_uppercase(), args_str.join(", "))?;
259 if let Some(a) = alias {
260 write!(f, " AS {}", a)?;
261 }
262 Ok(())
263 }
264 Expr::SpecialFunction { name, args, alias } => {
265 write!(f, "{}(", name.to_uppercase())?;
266 for (i, (keyword, expr)) in args.iter().enumerate() {
267 if i > 0 {
268 write!(f, " ")?;
269 }
270 if let Some(kw) = keyword {
271 write!(f, "{} ", kw)?;
272 }
273 write!(f, "{}", expr)?;
274 }
275 write!(f, ")")?;
276 if let Some(a) = alias {
277 write!(f, " AS {}", a)?;
278 }
279 Ok(())
280 }
281 Expr::Binary {
282 left,
283 op,
284 right,
285 alias,
286 } => {
287 write!(f, "({} {} {})", left, op, right)?;
288 if let Some(a) = alias {
289 write!(f, " AS {}", a)?;
290 }
291 Ok(())
292 }
293 Expr::Literal(value) => write!(f, "{}", value),
294 }
295 }
296}
297
298#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
299pub enum Constraint {
300 PrimaryKey,
301 Unique,
302 Nullable,
303 Default(String),
304 Check(Vec<String>),
305 Comment(String),
306 References(String),
307 Generated(ColumnGeneration),
308}
309
310#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
312pub enum ColumnGeneration {
313 Stored(String),
315 Virtual(String),
317}
318
319#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
321pub enum WindowFrame {
322 Rows { start: FrameBound, end: FrameBound },
324 Range { start: FrameBound, end: FrameBound },
326}
327
328#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
330pub enum FrameBound {
331 UnboundedPreceding,
332 Preceding(i32),
333 CurrentRow,
334 Following(i32),
335 UnboundedFollowing,
336}
337
338impl std::fmt::Display for Constraint {
339 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340 match self {
341 Constraint::PrimaryKey => write!(f, "pk"),
342 Constraint::Unique => write!(f, "uniq"),
343 Constraint::Nullable => write!(f, "?"),
344 Constraint::Default(val) => write!(f, "={}", val),
345 Constraint::Check(vals) => write!(f, "check({})", vals.join(",")),
346 Constraint::Comment(text) => write!(f, "comment(\"{}\")", text),
347 Constraint::References(target) => write!(f, "ref({})", target),
348 Constraint::Generated(generation) => match generation {
349 ColumnGeneration::Stored(expr) => write!(f, "gen({})", expr),
350 ColumnGeneration::Virtual(expr) => write!(f, "vgen({})", expr),
351 },
352 }
353 }
354}
355
356#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
358pub struct IndexDef {
359 pub name: String,
361 pub table: String,
363 pub columns: Vec<String>,
365 pub unique: bool,
366}
367
368#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
370pub enum TableConstraint {
371 Unique(Vec<String>),
372 PrimaryKey(Vec<String>),
373}
374
375impl From<&str> for Expr {
378 fn from(s: &str) -> Self {
381 Expr::Named(s.to_string())
382 }
383}
384
385impl From<String> for Expr {
386 fn from(s: String) -> Self {
387 Expr::Named(s)
388 }
389}
390
391impl From<&String> for Expr {
392 fn from(s: &String) -> Self {
393 Expr::Named(s.clone())
394 }
395}