1use crate::args::Args;
4use crate::cond::{ArgsRef, Cond};
5use crate::cte::CTEBuilder;
6use crate::flavor::Flavor;
7use crate::injection::{Injection, InjectionMarker};
8use crate::modifiers::{Arg, Builder};
9use crate::string_builder::StringBuilder;
10use crate::where_clause::{WhereClause, WhereClauseBuilder, WhereClauseRef};
11use std::cell::RefCell;
12use std::ops::Deref;
13use std::rc::Rc;
14
15const SELECT_MARKER_INIT: InjectionMarker = 0;
16const SELECT_MARKER_AFTER_WITH: InjectionMarker = 1;
17const SELECT_MARKER_AFTER_SELECT: InjectionMarker = 2;
18const SELECT_MARKER_AFTER_FROM: InjectionMarker = 3;
19const SELECT_MARKER_AFTER_JOIN: InjectionMarker = 4;
20const SELECT_MARKER_AFTER_WHERE: InjectionMarker = 5;
21const SELECT_MARKER_AFTER_GROUP_BY: InjectionMarker = 6;
22const SELECT_MARKER_AFTER_ORDER_BY: InjectionMarker = 7;
23const SELECT_MARKER_AFTER_LIMIT: InjectionMarker = 8;
24const SELECT_MARKER_AFTER_FOR: InjectionMarker = 9;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum JoinOption {
29 FullJoin,
30 FullOuterJoin,
31 InnerJoin,
32 LeftJoin,
33 LeftOuterJoin,
34 RightJoin,
35 RightOuterJoin,
36}
37
38impl JoinOption {
39 fn as_str(self) -> &'static str {
40 match self {
41 Self::FullJoin => "FULL",
42 Self::FullOuterJoin => "FULL OUTER",
43 Self::InnerJoin => "INNER",
44 Self::LeftJoin => "LEFT",
45 Self::LeftOuterJoin => "LEFT OUTER",
46 Self::RightJoin => "RIGHT",
47 Self::RightOuterJoin => "RIGHT OUTER",
48 }
49 }
50}
51
52#[derive(Debug)]
53pub struct SelectBuilder {
54 args: ArgsRef,
55 cond: Cond,
56
57 distinct: bool,
58 tables: Vec<String>,
59 select_cols: Vec<String>,
60
61 join_options: Vec<Option<JoinOption>>,
62 join_tables: Vec<String>,
63 join_exprs: Vec<Vec<String>>,
64
65 where_clause: Option<WhereClauseRef>,
66 where_var: Option<String>,
67 cte_var: Option<String>,
68 cte: Option<CTEBuilder>,
69
70 having_exprs: Vec<String>,
71 group_by_cols: Vec<String>,
72 order_by_cols: Vec<String>,
73 order: Option<&'static str>,
74 limit_var: Option<String>,
75 offset_var: Option<String>,
76 for_what: Option<&'static str>,
77
78 injection: Injection,
79 marker: InjectionMarker,
80}
81
82impl Deref for SelectBuilder {
83 type Target = Cond;
84 fn deref(&self) -> &Self::Target {
85 &self.cond
86 }
87}
88
89impl SelectBuilder {
90 pub fn new() -> Self {
91 let args = Rc::new(RefCell::new(Args::default()));
92 let cond = Cond::with_args(args.clone());
93 Self {
94 args,
95 cond,
96 distinct: false,
97 tables: Vec::new(),
98 select_cols: Vec::new(),
99 join_options: Vec::new(),
100 join_tables: Vec::new(),
101 join_exprs: Vec::new(),
102 where_clause: None,
103 where_var: None,
104 cte_var: None,
105 cte: None,
106 having_exprs: Vec::new(),
107 group_by_cols: Vec::new(),
108 order_by_cols: Vec::new(),
109 order: None,
110 limit_var: None,
111 offset_var: None,
112 for_what: None,
113 injection: Injection::new(),
114 marker: SELECT_MARKER_INIT,
115 }
116 }
117
118 pub fn set_flavor(&mut self, flavor: Flavor) -> Flavor {
119 let mut a = self.args.borrow_mut();
120 let old = a.flavor;
121 a.flavor = flavor;
122 old
123 }
124
125 pub fn flavor(&self) -> Flavor {
126 self.args.borrow().flavor
127 }
128
129 pub fn with(&mut self, cte: &CTEBuilder) -> &mut Self {
130 let placeholder_builder = cte.clone();
131 let ph = self.var(Arg::Builder(Box::new(cte.clone())));
132 self.cte = Some(placeholder_builder);
133 self.cte_var = Some(ph);
134 self.marker = SELECT_MARKER_AFTER_WITH;
135 self
136 }
137
138 fn table_names(&self) -> Vec<String> {
139 let cte_tables = self
140 .cte
141 .as_ref()
142 .map(|cte| cte.table_names_for_from())
143 .unwrap_or_default();
144
145 if self.tables.is_empty() {
146 return cte_tables;
147 }
148
149 if cte_tables.is_empty() {
150 return self.tables.clone();
151 }
152
153 let mut out = Vec::with_capacity(self.tables.len() + cte_tables.len());
154 out.extend(self.tables.clone());
155 out.extend(cte_tables);
156 out
157 }
158
159 pub fn where_clause(&self) -> Option<WhereClauseRef> {
161 self.where_clause.clone()
162 }
163
164 pub fn set_where_clause(&mut self, wc: Option<WhereClauseRef>) -> &mut Self {
169 match wc {
170 None => {
171 self.where_clause = None;
172 self.where_var = None;
173 }
174 Some(wc) => {
175 if let Some(ph) = &self.where_var {
176 self.args.borrow_mut().replace(
177 ph,
178 Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))),
179 );
180 } else {
181 let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
182 self.where_var = Some(ph);
183 }
184 self.where_clause = Some(wc);
185 }
186 }
187 self
188 }
189
190 pub fn clear_where_clause(&mut self) -> &mut Self {
191 self.set_where_clause(None)
192 }
193
194 pub fn add_where_expr(
196 &mut self,
197 args: ArgsRef,
198 exprs: impl IntoIterator<Item = impl Into<String>>,
199 ) -> &mut Self {
200 let exprs: Vec<String> = exprs.into_iter().map(Into::into).collect();
201 if exprs.is_empty() || exprs.iter().all(|s| s.is_empty()) {
202 return self;
203 }
204
205 if self.where_clause.is_none() {
206 let wc = WhereClause::new();
207 let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
208 self.where_clause = Some(wc);
209 self.where_var = Some(ph);
210 }
211 let wc = self.where_clause.as_ref().unwrap().clone();
212 wc.borrow_mut().add_where_expr(args, exprs);
213 self.marker = SELECT_MARKER_AFTER_WHERE;
214 self
215 }
216
217 pub fn clone_builder(&self) -> Self {
218 let old_args = self.args.borrow().clone();
219 let args = Rc::new(RefCell::new(old_args));
220 let cond = Cond::with_args(args.clone());
221
222 let mut cloned = Self {
223 args,
224 cond,
225 distinct: self.distinct,
226 tables: self.tables.clone(),
227 select_cols: self.select_cols.clone(),
228 join_options: self.join_options.clone(),
229 join_tables: self.join_tables.clone(),
230 join_exprs: self.join_exprs.clone(),
231 where_clause: self.where_clause.clone(),
232 where_var: self.where_var.clone(),
233 cte_var: self.cte_var.clone(),
234 cte: self.cte.clone(),
235 having_exprs: self.having_exprs.clone(),
236 group_by_cols: self.group_by_cols.clone(),
237 order_by_cols: self.order_by_cols.clone(),
238 order: self.order,
239 limit_var: self.limit_var.clone(),
240 offset_var: self.offset_var.clone(),
241 for_what: self.for_what,
242 injection: self.injection.clone(),
243 marker: self.marker,
244 };
245
246 if let (Some(wc), Some(ph)) = (&self.where_clause, &self.where_var) {
248 let new_wc = Rc::new(RefCell::new(wc.borrow().clone()));
249 cloned.where_clause = Some(new_wc.clone());
250 cloned
251 .args
252 .borrow_mut()
253 .replace(ph, Arg::Builder(Box::new(WhereClauseBuilder::new(new_wc))));
254 }
255
256 if let (Some(cte), Some(ph)) = (&self.cte, &self.cte_var) {
257 let new_cte = cte.clone();
258 let new_cte_for_field = new_cte.clone();
259 cloned.cte = Some(new_cte_for_field);
260 cloned
261 .args
262 .borrow_mut()
263 .replace(ph, Arg::Builder(Box::new(new_cte)));
264 }
265
266 cloned
267 }
268
269 fn var(&self, v: impl Into<Arg>) -> String {
270 self.args.borrow_mut().add(v)
271 }
272
273 pub fn select(&mut self, cols: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
274 self.select_cols = cols.into_iter().map(Into::into).collect();
275 self.marker = SELECT_MARKER_AFTER_SELECT;
276 self
277 }
278
279 pub fn select_more(&mut self, cols: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
280 self.select_cols.extend(cols.into_iter().map(Into::into));
281 self.marker = SELECT_MARKER_AFTER_SELECT;
282 self
283 }
284
285 pub fn distinct(&mut self) -> &mut Self {
286 self.distinct = true;
287 self.marker = SELECT_MARKER_AFTER_SELECT;
288 self
289 }
290
291 pub fn from(&mut self, tables: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
292 self.tables = tables.into_iter().map(Into::into).collect();
293 self.marker = SELECT_MARKER_AFTER_FROM;
294 self
295 }
296
297 pub fn join(
298 &mut self,
299 table: impl Into<String>,
300 on_expr: impl IntoIterator<Item = impl Into<String>>,
301 ) -> &mut Self {
302 self.join_with_option(None, table, on_expr)
303 }
304
305 pub fn join_with_option(
306 &mut self,
307 option: Option<JoinOption>,
308 table: impl Into<String>,
309 on_expr: impl IntoIterator<Item = impl Into<String>>,
310 ) -> &mut Self {
311 self.join_options.push(option);
312 self.join_tables.push(table.into());
313 self.join_exprs
314 .push(on_expr.into_iter().map(Into::into).collect());
315 self.marker = SELECT_MARKER_AFTER_JOIN;
316 self
317 }
318
319 pub fn where_(&mut self, and_expr: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
320 let exprs: Vec<String> = and_expr.into_iter().map(Into::into).collect();
321 if exprs.is_empty() || exprs.iter().all(|s| s.is_empty()) {
322 return self;
323 }
324
325 if self.where_clause.is_none() {
326 let wc = WhereClause::new();
327 let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
328 self.where_clause = Some(wc);
329 self.where_var = Some(ph);
330 }
331
332 let wc = self.where_clause.as_ref().unwrap().clone();
333 wc.borrow_mut().add_where_expr(self.args.clone(), exprs);
334 self.marker = SELECT_MARKER_AFTER_WHERE;
335 self
336 }
337
338 pub fn add_where_clause(&mut self, other: &WhereClause) -> &mut Self {
339 if self.where_clause.is_none() {
340 let wc = WhereClause::new();
341 let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
342 self.where_clause = Some(wc);
343 self.where_var = Some(ph);
344 }
345 self.where_clause
346 .as_ref()
347 .unwrap()
348 .borrow_mut()
349 .add_where_clause(other);
350 self
351 }
352
353 pub fn add_where_clause_ref(&mut self, other: &WhereClauseRef) -> &mut Self {
354 if self.where_clause.is_none() {
355 let wc = WhereClause::new();
356 let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
357 self.where_clause = Some(wc);
358 self.where_var = Some(ph);
359 }
360 self.where_clause
361 .as_ref()
362 .unwrap()
363 .borrow_mut()
364 .add_where_clause(&other.borrow());
365 self
366 }
367
368 pub fn having(&mut self, and_expr: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
369 self.having_exprs
370 .extend(and_expr.into_iter().map(Into::into));
371 self.marker = SELECT_MARKER_AFTER_GROUP_BY;
372 self
373 }
374
375 pub fn group_by(&mut self, cols: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
376 self.group_by_cols.extend(cols.into_iter().map(Into::into));
377 self.marker = SELECT_MARKER_AFTER_GROUP_BY;
378 self
379 }
380
381 pub fn order_by(&mut self, cols: impl IntoIterator<Item = impl Into<String>>) -> &mut Self {
382 self.order_by_cols.extend(cols.into_iter().map(Into::into));
383 self.marker = SELECT_MARKER_AFTER_ORDER_BY;
384 self
385 }
386
387 pub fn order_by_asc(&mut self, col: impl Into<String>) -> &mut Self {
388 self.order_by_cols.push(format!("{} ASC", col.into()));
389 self.marker = SELECT_MARKER_AFTER_ORDER_BY;
390 self
391 }
392
393 pub fn order_by_desc(&mut self, col: impl Into<String>) -> &mut Self {
394 self.order_by_cols.push(format!("{} DESC", col.into()));
395 self.marker = SELECT_MARKER_AFTER_ORDER_BY;
396 self
397 }
398
399 pub fn asc(&mut self) -> &mut Self {
400 self.order = Some("ASC");
401 self.marker = SELECT_MARKER_AFTER_ORDER_BY;
402 self
403 }
404
405 pub fn desc(&mut self) -> &mut Self {
406 self.order = Some("DESC");
407 self.marker = SELECT_MARKER_AFTER_ORDER_BY;
408 self
409 }
410
411 pub fn limit(&mut self, limit: i64) -> &mut Self {
412 if limit < 0 {
413 self.limit_var = None;
414 return self;
415 }
416 self.limit_var = Some(self.var(limit));
417 self.marker = SELECT_MARKER_AFTER_LIMIT;
418 self
419 }
420
421 pub fn offset(&mut self, offset: i64) -> &mut Self {
422 if offset < 0 {
423 self.offset_var = None;
424 return self;
425 }
426 self.offset_var = Some(self.var(offset));
427 self.marker = SELECT_MARKER_AFTER_LIMIT;
428 self
429 }
430
431 pub fn for_update(&mut self) -> &mut Self {
432 self.for_what = Some("UPDATE");
433 self.marker = SELECT_MARKER_AFTER_FOR;
434 self
435 }
436
437 pub fn for_share(&mut self) -> &mut Self {
438 self.for_what = Some("SHARE");
439 self.marker = SELECT_MARKER_AFTER_FOR;
440 self
441 }
442
443 pub fn as_(&self, name: &str, alias: &str) -> String {
444 format!("{name} AS {alias}")
445 }
446
447 pub fn builder_as(&self, builder: impl Builder + 'static, alias: &str) -> String {
448 format!(
449 "({}) AS {}",
450 self.var(Arg::Builder(Box::new(builder))),
451 alias
452 )
453 }
454
455 pub fn sql(&mut self, sql: impl Into<String>) -> &mut Self {
456 self.injection.sql(self.marker, sql);
457 self
458 }
459}
460
461impl Clone for SelectBuilder {
462 fn clone(&self) -> Self {
463 self.clone_builder()
464 }
465}
466
467impl Default for SelectBuilder {
468 fn default() -> Self {
469 Self::new()
470 }
471}
472
473impl Builder for SelectBuilder {
474 fn build_with_flavor(&self, flavor: Flavor, initial_arg: &[Arg]) -> (String, Vec<Arg>) {
475 let mut buf = StringBuilder::new();
476 write_injection(&mut buf, &self.injection, SELECT_MARKER_INIT);
477
478 if let Some(ph) = &self.cte_var {
479 buf.write_leading(ph);
480 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_WITH);
481 }
482
483 if !self.select_cols.is_empty() {
484 buf.write_leading("SELECT");
485 if self.distinct {
486 buf.write_str(" DISTINCT");
487 }
488 buf.write_str(" ");
489 buf.write_str(&self.select_cols.join(", "));
490 }
491 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_SELECT);
492
493 let table_names = self.table_names();
494 if !table_names.is_empty() {
495 buf.write_leading("FROM");
496 buf.write_str(" ");
497 buf.write_str(&table_names.join(", "));
498 }
499 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_FROM);
500
501 for i in 0..self.join_tables.len() {
502 if let Some(opt) = self.join_options[i] {
503 buf.write_leading(opt.as_str());
504 }
505 buf.write_leading("JOIN");
506 buf.write_str(" ");
507 buf.write_str(&self.join_tables[i]);
508
509 let on = self.join_exprs[i]
510 .iter()
511 .filter(|s| !s.is_empty())
512 .cloned()
513 .collect::<Vec<_>>();
514 if !on.is_empty() {
515 buf.write_str(" ON ");
516 buf.write_str(&on.join(" AND "));
517 }
518 }
519 if !self.join_tables.is_empty() {
520 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_JOIN);
521 }
522
523 if let Some(ph) = &self.where_var {
524 buf.write_leading(ph);
525 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_WHERE);
526 }
527
528 if !self.group_by_cols.is_empty() {
529 buf.write_leading("GROUP BY");
530 buf.write_str(" ");
531 buf.write_str(&self.group_by_cols.join(", "));
532 let having = self
533 .having_exprs
534 .iter()
535 .filter(|s| !s.is_empty())
536 .cloned()
537 .collect::<Vec<_>>();
538 if !having.is_empty() {
539 buf.write_str(" HAVING ");
540 buf.write_str(&having.join(" AND "));
541 }
542 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_GROUP_BY);
543 }
544
545 if !self.order_by_cols.is_empty() {
546 buf.write_leading("ORDER BY");
547 buf.write_str(" ");
548 buf.write_str(&self.order_by_cols.join(", "));
549 if let Some(order) = self.order {
550 buf.write_str(" ");
551 buf.write_str(order);
552 }
553 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_ORDER_BY);
554 }
555
556 match flavor {
558 Flavor::MySQL | Flavor::SQLite | Flavor::ClickHouse => {
559 if let Some(lim) = &self.limit_var {
560 buf.write_leading("LIMIT");
561 buf.write_str(" ");
562 buf.write_str(lim);
563 if let Some(off) = &self.offset_var {
564 buf.write_leading("OFFSET");
565 buf.write_str(" ");
566 buf.write_str(off);
567 }
568 }
569 }
570 Flavor::CQL => {
571 if let Some(lim) = &self.limit_var {
572 buf.write_leading("LIMIT");
573 buf.write_str(" ");
574 buf.write_str(lim);
575 }
576 }
577 Flavor::PostgreSQL => {
578 if let Some(lim) = &self.limit_var {
579 buf.write_leading("LIMIT");
580 buf.write_str(" ");
581 buf.write_str(lim);
582 }
583 if let Some(off) = &self.offset_var {
584 buf.write_leading("OFFSET");
585 buf.write_str(" ");
586 buf.write_str(off);
587 }
588 }
589 Flavor::Presto => {
590 if let Some(off) = &self.offset_var {
591 buf.write_leading("OFFSET");
592 buf.write_str(" ");
593 buf.write_str(off);
594 }
595 if let Some(lim) = &self.limit_var {
596 buf.write_leading("LIMIT");
597 buf.write_str(" ");
598 buf.write_str(lim);
599 }
600 }
601 Flavor::SQLServer | Flavor::Oracle => {
602 if self.order_by_cols.is_empty()
603 && (self.limit_var.is_some() || self.offset_var.is_some())
604 && flavor == Flavor::SQLServer
605 {
606 buf.write_leading("ORDER BY 1");
607 }
608
609 if let Some(off) = &self.offset_var {
610 buf.write_leading("OFFSET");
611 buf.write_str(" ");
612 buf.write_str(off);
613 buf.write_str(" ROWS");
614 }
615
616 if let Some(lim) = &self.limit_var {
617 if self.offset_var.is_none() {
618 buf.write_leading("OFFSET 0 ROWS");
619 }
620 buf.write_leading("FETCH NEXT");
621 buf.write_str(" ");
622 buf.write_str(lim);
623 buf.write_str(" ROWS ONLY");
624 }
625 }
626 Flavor::Informix | Flavor::Doris => {
627 if let Some(lim) = &self.limit_var {
629 buf.write_leading("LIMIT");
630 buf.write_str(" ");
631 buf.write_str(lim);
632 if let Some(off) = &self.offset_var {
633 buf.write_leading("OFFSET");
634 buf.write_str(" ");
635 buf.write_str(off);
636 }
637 }
638 }
639 }
640
641 if self.limit_var.is_some() {
642 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_LIMIT);
643 }
644
645 if let Some(what) = self.for_what {
646 buf.write_leading("FOR");
647 buf.write_str(" ");
648 buf.write_str(what);
649 write_injection(&mut buf, &self.injection, SELECT_MARKER_AFTER_FOR);
650 }
651
652 self.args
653 .borrow()
654 .compile_with_flavor(&buf.into_string(), flavor, initial_arg)
655 }
656
657 fn flavor(&self) -> Flavor {
658 self.flavor()
659 }
660}
661
662fn write_injection(buf: &mut StringBuilder, inj: &Injection, marker: InjectionMarker) {
663 let sqls = inj.at(marker);
664 if sqls.is_empty() {
665 return;
666 }
667 buf.write_leading("");
668 buf.write_str(&sqls.join(" "));
669}