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