1use rust_decimal::Decimal;
7use rustledger_core::NaiveDate;
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum Query {
12 Select(Box<SelectQuery>),
14 Journal(JournalQuery),
16 Balances(BalancesQuery),
18 Print(PrintQuery),
20}
21
22#[derive(Debug, Clone, PartialEq)]
24pub struct SelectQuery {
25 pub distinct: bool,
27 pub targets: Vec<Target>,
29 pub from: Option<FromClause>,
31 pub where_clause: Option<Expr>,
33 pub group_by: Option<Vec<Expr>>,
35 pub having: Option<Expr>,
37 pub pivot_by: Option<Vec<Expr>>,
39 pub order_by: Option<Vec<OrderSpec>>,
41 pub limit: Option<u64>,
43}
44
45#[derive(Debug, Clone, PartialEq)]
47pub struct Target {
48 pub expr: Expr,
50 pub alias: Option<String>,
52}
53
54#[derive(Debug, Clone, PartialEq)]
56pub struct FromClause {
57 pub open_on: Option<NaiveDate>,
59 pub close_on: Option<NaiveDate>,
61 pub clear: bool,
63 pub filter: Option<Expr>,
65 pub subquery: Option<Box<SelectQuery>>,
67}
68
69#[derive(Debug, Clone, PartialEq)]
71pub struct OrderSpec {
72 pub expr: Expr,
74 pub direction: SortDirection,
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
80pub enum SortDirection {
81 #[default]
83 Asc,
84 Desc,
86}
87
88#[derive(Debug, Clone, PartialEq)]
90pub struct JournalQuery {
91 pub account_pattern: String,
93 pub at_function: Option<String>,
95 pub from: Option<FromClause>,
97}
98
99#[derive(Debug, Clone, PartialEq)]
101pub struct BalancesQuery {
102 pub at_function: Option<String>,
104 pub from: Option<FromClause>,
106}
107
108#[derive(Debug, Clone, PartialEq)]
110pub struct PrintQuery {
111 pub from: Option<FromClause>,
113}
114
115#[derive(Debug, Clone, PartialEq)]
117pub enum Expr {
118 Wildcard,
120 Column(String),
122 Literal(Literal),
124 Function(FunctionCall),
126 Window(WindowFunction),
128 BinaryOp(Box<BinaryOp>),
130 UnaryOp(Box<UnaryOp>),
132 Paren(Box<Self>),
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
138pub enum Literal {
139 String(String),
141 Number(Decimal),
143 Integer(i64),
145 Date(NaiveDate),
147 Boolean(bool),
149 Null,
151}
152
153#[derive(Debug, Clone, PartialEq)]
155pub struct FunctionCall {
156 pub name: String,
158 pub args: Vec<Expr>,
160}
161
162#[derive(Debug, Clone, PartialEq)]
164pub struct WindowFunction {
165 pub name: String,
167 pub args: Vec<Expr>,
169 pub over: WindowSpec,
171}
172
173#[derive(Debug, Clone, PartialEq, Default)]
175pub struct WindowSpec {
176 pub partition_by: Option<Vec<Expr>>,
178 pub order_by: Option<Vec<OrderSpec>>,
180}
181
182#[derive(Debug, Clone, PartialEq)]
184pub struct BinaryOp {
185 pub left: Expr,
187 pub op: BinaryOperator,
189 pub right: Expr,
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
195pub enum BinaryOperator {
196 Eq,
199 Ne,
201 Lt,
203 Le,
205 Gt,
207 Ge,
209 Regex,
211 In,
213
214 And,
217 Or,
219
220 Add,
223 Sub,
225 Mul,
227 Div,
229}
230
231#[derive(Debug, Clone, PartialEq)]
233pub struct UnaryOp {
234 pub op: UnaryOperator,
236 pub operand: Expr,
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub enum UnaryOperator {
243 Not,
245 Neg,
247}
248
249impl SelectQuery {
250 pub const fn new(targets: Vec<Target>) -> Self {
252 Self {
253 distinct: false,
254 targets,
255 from: None,
256 where_clause: None,
257 group_by: None,
258 having: None,
259 pivot_by: None,
260 order_by: None,
261 limit: None,
262 }
263 }
264
265 pub const fn distinct(mut self) -> Self {
267 self.distinct = true;
268 self
269 }
270
271 pub fn from(mut self, from: FromClause) -> Self {
273 self.from = Some(from);
274 self
275 }
276
277 pub fn where_clause(mut self, expr: Expr) -> Self {
279 self.where_clause = Some(expr);
280 self
281 }
282
283 pub fn group_by(mut self, exprs: Vec<Expr>) -> Self {
285 self.group_by = Some(exprs);
286 self
287 }
288
289 pub fn having(mut self, expr: Expr) -> Self {
291 self.having = Some(expr);
292 self
293 }
294
295 pub fn pivot_by(mut self, exprs: Vec<Expr>) -> Self {
297 self.pivot_by = Some(exprs);
298 self
299 }
300
301 pub fn order_by(mut self, specs: Vec<OrderSpec>) -> Self {
303 self.order_by = Some(specs);
304 self
305 }
306
307 pub const fn limit(mut self, n: u64) -> Self {
309 self.limit = Some(n);
310 self
311 }
312}
313
314impl Target {
315 pub const fn new(expr: Expr) -> Self {
317 Self { expr, alias: None }
318 }
319
320 pub fn with_alias(expr: Expr, alias: impl Into<String>) -> Self {
322 Self {
323 expr,
324 alias: Some(alias.into()),
325 }
326 }
327}
328
329impl FromClause {
330 pub const fn new() -> Self {
332 Self {
333 open_on: None,
334 close_on: None,
335 clear: false,
336 filter: None,
337 subquery: None,
338 }
339 }
340
341 pub fn from_subquery(query: SelectQuery) -> Self {
343 Self {
344 open_on: None,
345 close_on: None,
346 clear: false,
347 filter: None,
348 subquery: Some(Box::new(query)),
349 }
350 }
351
352 pub const fn open_on(mut self, date: NaiveDate) -> Self {
354 self.open_on = Some(date);
355 self
356 }
357
358 pub const fn close_on(mut self, date: NaiveDate) -> Self {
360 self.close_on = Some(date);
361 self
362 }
363
364 pub const fn clear(mut self) -> Self {
366 self.clear = true;
367 self
368 }
369
370 pub fn filter(mut self, expr: Expr) -> Self {
372 self.filter = Some(expr);
373 self
374 }
375
376 pub fn subquery(mut self, query: SelectQuery) -> Self {
378 self.subquery = Some(Box::new(query));
379 self
380 }
381}
382
383impl Default for FromClause {
384 fn default() -> Self {
385 Self::new()
386 }
387}
388
389impl Expr {
390 pub fn column(name: impl Into<String>) -> Self {
392 Self::Column(name.into())
393 }
394
395 pub fn string(s: impl Into<String>) -> Self {
397 Self::Literal(Literal::String(s.into()))
398 }
399
400 pub const fn number(n: Decimal) -> Self {
402 Self::Literal(Literal::Number(n))
403 }
404
405 pub const fn integer(n: i64) -> Self {
407 Self::Literal(Literal::Integer(n))
408 }
409
410 pub const fn date(d: NaiveDate) -> Self {
412 Self::Literal(Literal::Date(d))
413 }
414
415 pub const fn boolean(b: bool) -> Self {
417 Self::Literal(Literal::Boolean(b))
418 }
419
420 pub const fn null() -> Self {
422 Self::Literal(Literal::Null)
423 }
424
425 pub fn function(name: impl Into<String>, args: Vec<Self>) -> Self {
427 Self::Function(FunctionCall {
428 name: name.into(),
429 args,
430 })
431 }
432
433 pub fn binary(left: Self, op: BinaryOperator, right: Self) -> Self {
435 Self::BinaryOp(Box::new(BinaryOp { left, op, right }))
436 }
437
438 pub fn unary(op: UnaryOperator, operand: Self) -> Self {
440 Self::UnaryOp(Box::new(UnaryOp { op, operand }))
441 }
442}
443
444impl OrderSpec {
445 pub const fn asc(expr: Expr) -> Self {
447 Self {
448 expr,
449 direction: SortDirection::Asc,
450 }
451 }
452
453 pub const fn desc(expr: Expr) -> Self {
455 Self {
456 expr,
457 direction: SortDirection::Desc,
458 }
459 }
460}