qail_core/ast/cmd/
mod.rs

1use crate::ast::{
2    Action, Cage, CageKind, Condition, Expr, GroupByMode, IndexDef, Join, LockMode,
3    LogicalOp, Operator, OverridingKind, SampleMethod, SetOp, TableConstraint, Value,
4};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct Qail {
9    pub action: Action,
10    pub table: String,
11    pub columns: Vec<Expr>,
12    #[serde(default)]
13    pub joins: Vec<Join>,
14    pub cages: Vec<Cage>,
15    #[serde(default)]
16    pub distinct: bool,
17    #[serde(default)]
18    pub index_def: Option<IndexDef>,
19    #[serde(default)]
20    pub table_constraints: Vec<TableConstraint>,
21    #[serde(default)]
22    pub set_ops: Vec<(SetOp, Box<Qail>)>,
23    #[serde(default)]
24    pub having: Vec<Condition>,
25    #[serde(default)]
26    pub group_by_mode: GroupByMode,
27    #[serde(default)]
28    pub ctes: Vec<CTEDef>,
29    #[serde(default)]
30    pub distinct_on: Vec<Expr>,
31    #[serde(default)]
32    pub returning: Option<Vec<Expr>>,
33    #[serde(default)]
34    pub on_conflict: Option<OnConflict>,
35    #[serde(default)]
36    pub source_query: Option<Box<Qail>>,
37    #[serde(default)]
38    pub channel: Option<String>,
39    #[serde(default)]
40    pub payload: Option<String>,
41    #[serde(default)]
42    pub savepoint_name: Option<String>,
43    #[serde(default)]
44    pub from_tables: Vec<String>,
45    #[serde(default)]
46    pub using_tables: Vec<String>,
47    #[serde(default)]
48    pub lock_mode: Option<LockMode>,
49    #[serde(default)]
50    pub fetch: Option<(u64, bool)>,
51    #[serde(default)]
52    pub default_values: bool,
53    #[serde(default)]
54    pub overriding: Option<OverridingKind>,
55    #[serde(default)]
56    pub sample: Option<(SampleMethod, f64, Option<u64>)>,
57    #[serde(default)]
58    pub only_table: bool,
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62pub struct CTEDef {
63    pub name: String,
64    pub recursive: bool,
65    pub columns: Vec<String>,
66    pub base_query: Box<Qail>,
67    pub recursive_query: Option<Box<Qail>>,
68    pub source_table: Option<String>,
69}
70
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
72pub struct OnConflict {
73    pub columns: Vec<String>,
74    pub action: ConflictAction,
75}
76
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78pub enum ConflictAction {
79    DoNothing,
80    DoUpdate {
81        assignments: Vec<(String, Expr)>,
82    },
83}
84
85impl Default for OnConflict {
86    fn default() -> Self {
87        Self {
88            columns: vec![],
89            action: ConflictAction::DoNothing,
90        }
91    }
92}
93
94impl Default for Qail {
95    fn default() -> Self {
96        Self {
97            action: Action::Get,
98            table: String::new(),
99            columns: vec![],
100            joins: vec![],
101            cages: vec![],
102            distinct: false,
103            index_def: None,
104            table_constraints: vec![],
105            set_ops: vec![],
106            having: vec![],
107            group_by_mode: GroupByMode::Simple,
108            ctes: vec![],
109            distinct_on: vec![],
110            returning: None,
111            on_conflict: None,
112            source_query: None,
113            channel: None,
114            payload: None,
115            savepoint_name: None,
116            from_tables: vec![],
117            using_tables: vec![],
118            lock_mode: None,
119            fetch: None,
120            default_values: false,
121            overriding: None,
122            sample: None,
123            only_table: false,
124        }
125    }
126}
127
128// Submodules with builder methods
129mod advanced;
130mod constructors;
131mod cte;
132mod query;
133
134// Deprecated methods kept in main module for backward compatibility
135impl Qail {
136    #[deprecated(since = "0.11.0", note = "Use .columns([...]) instead")]
137    pub fn hook(mut self, cols: &[&str]) -> Self {
138        self.columns = cols.iter().map(|c| Expr::Named(c.to_string())).collect();
139        self
140    }
141
142    #[deprecated(since = "0.11.0", note = "Use .filter(column, Operator::Eq, value) or .where_eq(column, value) instead")]
143    pub fn cage(mut self, column: &str, value: impl Into<Value>) -> Self {
144        self.cages.push(Cage {
145            kind: CageKind::Filter,
146            conditions: vec![Condition {
147                left: Expr::Named(column.to_string()),
148                op: Operator::Eq,
149                value: value.into(),
150                is_array_unnest: false,
151            }],
152            logical_op: LogicalOp::And,
153        });
154        self
155    }
156}