1use crate::ast::{
2 Action, Cage, CageKind, Condition, Distance, 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 #[serde(default, skip_serializing_if = "Vec::is_empty")]
12 pub columns: Vec<Expr>,
13 #[serde(default, skip_serializing_if = "Vec::is_empty")]
14 pub joins: Vec<Join>,
15 #[serde(default, skip_serializing_if = "Vec::is_empty")]
16 pub cages: Vec<Cage>,
17 #[serde(default, skip_serializing_if = "is_false")]
18 pub distinct: bool,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub index_def: Option<IndexDef>,
21 #[serde(default, skip_serializing_if = "Vec::is_empty")]
22 pub table_constraints: Vec<TableConstraint>,
23 #[serde(default, skip_serializing_if = "Vec::is_empty")]
24 pub set_ops: Vec<(SetOp, Box<Qail>)>,
25 #[serde(default, skip_serializing_if = "Vec::is_empty")]
26 pub having: Vec<Condition>,
27 #[serde(default, skip_serializing_if = "GroupByMode::is_simple")]
28 pub group_by_mode: GroupByMode,
29 #[serde(default, skip_serializing_if = "Vec::is_empty")]
30 pub ctes: Vec<CTEDef>,
31 #[serde(default, skip_serializing_if = "Vec::is_empty")]
32 pub distinct_on: Vec<Expr>,
33 #[serde(default, skip_serializing_if = "Option::is_none")]
34 pub returning: Option<Vec<Expr>>,
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub on_conflict: Option<OnConflict>,
37 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub source_query: Option<Box<Qail>>,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub channel: Option<String>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub payload: Option<String>,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
44 pub savepoint_name: Option<String>,
45 #[serde(default, skip_serializing_if = "Vec::is_empty")]
46 pub from_tables: Vec<String>,
47 #[serde(default, skip_serializing_if = "Vec::is_empty")]
48 pub using_tables: Vec<String>,
49 #[serde(default, skip_serializing_if = "Option::is_none")]
50 pub lock_mode: Option<LockMode>,
51 #[serde(default, skip_serializing_if = "Option::is_none")]
52 pub fetch: Option<(u64, bool)>,
53 #[serde(default, skip_serializing_if = "is_false")]
54 pub default_values: bool,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
56 pub overriding: Option<OverridingKind>,
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 pub sample: Option<(SampleMethod, f64, Option<u64>)>,
59 #[serde(default, skip_serializing_if = "is_false")]
60 pub only_table: bool,
61 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub vector: Option<Vec<f32>>,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub score_threshold: Option<f32>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub vector_name: Option<String>,
68 #[serde(default, skip_serializing_if = "is_false")]
69 pub with_vector: bool,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub vector_size: Option<u64>,
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 pub distance: Option<Distance>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub on_disk: Option<bool>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub function_def: Option<crate::ast::FunctionDef>,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub trigger_def: Option<crate::ast::TriggerDef>,
81 #[serde(default, skip_serializing_if = "Option::is_none")]
83 pub raw_value: Option<Vec<u8>>,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub redis_ttl: Option<i64>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub redis_set_condition: Option<String>,
88}
89
90fn is_false(b: &bool) -> bool {
92 !*b
93}
94
95#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
96pub struct CTEDef {
97 pub name: String,
98 pub recursive: bool,
99 pub columns: Vec<String>,
100 pub base_query: Box<Qail>,
101 pub recursive_query: Option<Box<Qail>>,
102 pub source_table: Option<String>,
103}
104
105#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub struct OnConflict {
107 pub columns: Vec<String>,
108 pub action: ConflictAction,
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112pub enum ConflictAction {
113 DoNothing,
114 DoUpdate {
115 assignments: Vec<(String, Expr)>,
116 },
117}
118
119impl Default for OnConflict {
120 fn default() -> Self {
121 Self {
122 columns: vec![],
123 action: ConflictAction::DoNothing,
124 }
125 }
126}
127
128impl Default for Qail {
129 fn default() -> Self {
130 Self {
131 action: Action::Get,
132 table: String::new(),
133 columns: vec![],
134 joins: vec![],
135 cages: vec![],
136 distinct: false,
137 index_def: None,
138 table_constraints: vec![],
139 set_ops: vec![],
140 having: vec![],
141 group_by_mode: GroupByMode::Simple,
142 ctes: vec![],
143 distinct_on: vec![],
144 returning: None,
145 on_conflict: None,
146 source_query: None,
147 channel: None,
148 payload: None,
149 savepoint_name: None,
150 from_tables: vec![],
151 using_tables: vec![],
152 lock_mode: None,
153 fetch: None,
154 default_values: false,
155 overriding: None,
156 sample: None,
157 only_table: false,
158 vector: None,
160 score_threshold: None,
161 vector_name: None,
162 with_vector: false,
163 vector_size: None,
164 distance: None,
165 on_disk: None,
166 function_def: None,
168 trigger_def: None,
169 raw_value: None,
171 redis_ttl: None,
172 redis_set_condition: None,
173 }
174 }
175}
176
177mod advanced;
179mod constructors;
180mod cte;
181mod query;
182mod rls;
183mod vector;
184
185impl Qail {
187 #[deprecated(since = "0.11.0", note = "Use .columns([...]) instead")]
188 pub fn hook(mut self, cols: &[&str]) -> Self {
189 self.columns = cols.iter().map(|c| Expr::Named(c.to_string())).collect();
190 self
191 }
192
193 #[deprecated(since = "0.11.0", note = "Use .filter(column, Operator::Eq, value) or .where_eq(column, value) instead")]
194 pub fn cage(mut self, column: &str, value: impl Into<Value>) -> Self {
195 self.cages.push(Cage {
196 kind: CageKind::Filter,
197 conditions: vec![Condition {
198 left: Expr::Named(column.to_string()),
199 op: Operator::Eq,
200 value: value.into(),
201 is_array_unnest: false,
202 }],
203 logical_op: LogicalOp::And,
204 });
205 self
206 }
207}
208
209impl std::fmt::Display for Qail {
210 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211 use crate::fmt::Formatter;
213 match Formatter::new().format(self) {
214 Ok(s) => write!(f, "{}", s),
215 Err(_) => write!(f, "{:?}", self), }
217 }
218}