sqlmodel_query/
subquery.rs1use crate::clause::{Limit, Offset, OrderBy, Where};
4use crate::expr::Dialect;
5use crate::join::Join;
6use sqlmodel_core::Value;
7
8#[derive(Debug, Clone)]
12#[doc(hidden)]
13pub struct SelectQuery {
14 pub table: String,
16 pub columns: Vec<String>,
18 pub where_clause: Option<Where>,
20 pub order_by: Vec<OrderBy>,
22 pub joins: Vec<Join>,
24 pub limit: Option<Limit>,
26 pub offset: Option<Offset>,
28 pub group_by: Vec<String>,
30 pub having: Option<Where>,
32 pub distinct: bool,
34 pub for_update: bool,
36}
37
38impl SelectQuery {
39 pub fn build_with_dialect(&self, dialect: Dialect) -> (String, Vec<Value>) {
41 let mut sql = String::new();
42 let mut params = Vec::new();
43
44 sql.push_str("SELECT ");
46 if self.distinct {
47 sql.push_str("DISTINCT ");
48 }
49
50 if self.columns.is_empty() {
51 sql.push('*');
52 } else {
53 sql.push_str(&self.columns.join(", "));
54 }
55
56 sql.push_str(" FROM ");
58 sql.push_str(&self.table);
59
60 for join in &self.joins {
62 sql.push_str(&join.build_with_dialect(dialect, &mut params, 0));
63 }
64
65 if let Some(where_clause) = &self.where_clause {
67 let (where_sql, where_params) = where_clause.build_with_dialect(dialect, params.len());
68 sql.push_str(" WHERE ");
69 sql.push_str(&where_sql);
70 params.extend(where_params);
71 }
72
73 if !self.group_by.is_empty() {
75 sql.push_str(" GROUP BY ");
76 sql.push_str(&self.group_by.join(", "));
77 }
78
79 if let Some(having) = &self.having {
81 let (having_sql, having_params) = having.build_with_dialect(dialect, params.len());
82 sql.push_str(" HAVING ");
83 sql.push_str(&having_sql);
84 params.extend(having_params);
85 }
86
87 if !self.order_by.is_empty() {
89 sql.push_str(" ORDER BY ");
90 let order_strs: Vec<_> = self
91 .order_by
92 .iter()
93 .map(|o| o.build(dialect, &mut params, 0))
94 .collect();
95 sql.push_str(&order_strs.join(", "));
96 }
97
98 if let Some(Limit(n)) = self.limit {
100 sql.push_str(&format!(" LIMIT {}", n));
101 }
102
103 if let Some(Offset(n)) = self.offset {
105 sql.push_str(&format!(" OFFSET {}", n));
106 }
107
108 if self.for_update {
110 sql.push_str(" FOR UPDATE");
111 }
112
113 (sql, params)
114 }
115
116 pub fn build_exists_subquery_with_dialect(&self, dialect: Dialect) -> (String, Vec<Value>) {
118 let mut sql = String::new();
119 let mut params = Vec::new();
120
121 sql.push_str("SELECT 1 FROM ");
123 sql.push_str(&self.table);
124
125 for join in &self.joins {
127 sql.push_str(&join.build_with_dialect(dialect, &mut params, 0));
128 }
129
130 if let Some(where_clause) = &self.where_clause {
132 let (where_sql, where_params) = where_clause.build_with_dialect(dialect, params.len());
133 sql.push_str(" WHERE ");
134 sql.push_str(&where_sql);
135 params.extend(where_params);
136 }
137
138 if !self.group_by.is_empty() {
140 sql.push_str(" GROUP BY ");
141 sql.push_str(&self.group_by.join(", "));
142 }
143
144 if let Some(having) = &self.having {
146 let (having_sql, having_params) = having.build_with_dialect(dialect, params.len());
147 sql.push_str(" HAVING ");
148 sql.push_str(&having_sql);
149 params.extend(having_params);
150 }
151
152 (sql, params)
155 }
156}