1use super::{
2 Delete, ExprSet, Limit, Node, OrderBy, Path, Returning, Select, Source, Statement, Update,
3 UpdateTarget, Values, Visit, VisitMut, With,
4};
5use crate::stmt::{self, ExprSetOp, Filter, SetOp};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct Query {
9 pub with: Option<With>,
11
12 pub body: ExprSet,
15
16 pub single: bool,
20
21 pub order_by: Option<OrderBy>,
23
24 pub limit: Option<Limit>,
26
27 pub locks: Vec<Lock>,
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum Lock {
33 Update,
34 Share,
35}
36
37#[derive(Debug)]
38pub struct QueryBuilder {
39 query: Query,
40}
41
42impl Query {
43 pub fn new(body: impl Into<ExprSet>) -> Self {
44 Self {
45 with: None,
46 body: body.into(),
47 single: false,
48 order_by: None,
49 limit: None,
50 locks: vec![],
51 }
52 }
53
54 pub fn new_single(body: impl Into<ExprSet>) -> Self {
55 Self {
56 with: None,
57 body: body.into(),
58 single: true,
59 order_by: None,
60 limit: None,
61 locks: vec![],
62 }
63 }
64
65 pub fn new_select(source: impl Into<Source>, filter: impl Into<Filter>) -> Self {
66 Self::builder(Select::new(source, filter)).build()
67 }
68
69 pub fn builder(body: impl Into<ExprSet>) -> QueryBuilder {
70 QueryBuilder {
71 query: Query::new(body),
72 }
73 }
74
75 pub fn unit() -> Self {
76 Query::new(Values::default())
77 }
78
79 pub fn values(values: impl Into<Values>) -> Self {
80 Self {
81 with: None,
82 body: ExprSet::Values(values.into()),
83 single: false,
84 order_by: None,
85 limit: None,
86 locks: vec![],
87 }
88 }
89
90 pub fn update(self) -> Update {
91 let ExprSet::Select(select) = &self.body else {
92 todo!("stmt={self:#?}");
93 };
94
95 assert!(select.source.is_model());
96
97 stmt::Update {
98 target: UpdateTarget::Query(Box::new(self)),
99 assignments: stmt::Assignments::default(),
100 filter: Filter::default(),
101 condition: stmt::Condition::default(),
102 returning: None,
103 }
104 }
105
106 pub fn delete(self) -> Delete {
107 match self.body {
108 ExprSet::Select(select) => Delete {
109 from: select.source,
110 filter: select.filter,
111 returning: None,
112 },
113 _ => todo!("{self:#?}"),
114 }
115 }
116
117 pub fn add_filter(&mut self, filter: impl Into<Filter>) {
118 self.body.as_select_mut_unwrap().add_filter(filter);
119 }
120
121 pub fn add_union(&mut self, other: impl Into<Self>) {
122 let rhs = other.into();
123
124 match (&mut self.body, rhs.body) {
125 (ExprSet::SetOp(_), ExprSet::SetOp(_)) => todo!(),
126 (ExprSet::SetOp(lhs), rhs) if lhs.is_union() => {
127 lhs.operands.push(rhs);
128 }
129 (_, ExprSet::SetOp(_)) => todo!(),
130 (me, rhs) => {
131 let lhs = std::mem::take(me);
132 *me = ExprSet::SetOp(ExprSetOp {
133 op: SetOp::Union,
134 operands: vec![lhs, rhs],
135 });
136 }
137 }
138 }
139
140 pub fn include(&mut self, path: impl Into<Path>) {
141 match &mut self.body {
142 ExprSet::Select(body) => body.include(path),
143 _ => todo!(),
144 }
145 }
146}
147
148impl Statement {
149 pub fn is_query(&self) -> bool {
150 matches!(self, Statement::Query(_))
151 }
152
153 pub fn as_query(&self) -> Option<&Query> {
159 match self {
160 Self::Query(query) => Some(query),
161 _ => None,
162 }
163 }
164
165 pub fn as_query_mut(&mut self) -> Option<&mut Query> {
171 match self {
172 Self::Query(query) => Some(query),
173 _ => None,
174 }
175 }
176
177 #[track_caller]
183 pub fn into_query(self) -> Query {
184 match self {
185 Self::Query(query) => query,
186 v => panic!("expected `Query`, found {v:#?}"),
187 }
188 }
189}
190
191impl From<Query> for Statement {
192 fn from(value: Query) -> Self {
193 Self::Query(value)
194 }
195}
196
197impl Node for Query {
198 fn visit<V: Visit>(&self, mut visit: V) {
199 visit.visit_stmt_query(self);
200 }
201
202 fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
203 visit.visit_stmt_query_mut(self);
204 }
205}
206
207impl QueryBuilder {
208 pub fn with(mut self, with: impl Into<With>) -> Self {
209 self.query.with = Some(with.into());
210 self
211 }
212
213 pub fn locks(mut self, locks: impl Into<Vec<Lock>>) -> Self {
214 self.query.locks = locks.into();
215 self
216 }
217
218 pub fn filter(mut self, filter: impl Into<Filter>) -> Self {
219 let filter = filter.into();
220
221 match &mut self.query.body {
222 ExprSet::Select(select) => {
223 select.filter = filter;
224 }
225 _ => todo!("query={self:#?}"),
226 }
227
228 self
229 }
230
231 pub fn returning(mut self, returning: impl Into<Returning>) -> Self {
232 let returning = returning.into();
233
234 match &mut self.query.body {
235 ExprSet::Select(select) => {
236 select.returning = returning;
237 }
238 _ => todo!(),
239 }
240
241 self
242 }
243
244 pub fn build(self) -> Query {
245 self.query
246 }
247}
248
249impl From<QueryBuilder> for Query {
250 fn from(value: QueryBuilder) -> Self {
251 value.build()
252 }
253}