Skip to main content

ngb_sqlbuilder/
column.rs

1#![allow(clippy::wrong_self_convention)]
2
3use crate::{Clause, Column, Condition, SqlClause};
4use tokio_postgres::types::ToSql;
5
6impl<'q> Clause<'q, Column> {
7    /// Add alias to column
8    ///
9    /// # Arguments
10    ///
11    /// * `value`: alias name
12    ///
13    /// returns: Clause<Column>
14    ///
15    /// # Examples
16    ///
17    /// ```
18    /// use ngb_sqlbuilder::col;
19    ///
20    /// col("t.ColName").alias("col_name")
21    /// // SQL: t."ColName" as "col_name"
22    /// ```
23    pub fn alias(mut self, value: &str) -> Self {
24        let mut sql = if self.sql.contains("SELECT ") {
25            let len = self.sql.len() + value.len() + 8;
26            let mut nested = String::with_capacity(len);
27            nested.push('(');
28            nested.push_str(&self.sql);
29            nested.push(')');
30            nested
31        } else {
32            self.sql
33        };
34
35        // if self.sql.contains(" as ") && !self.sql.ends_with(')') {
36        //     return self;
37        // }
38        sql.push_str(" as \"");
39        sql.push_str(value);
40        sql.push('"');
41        self.sql = sql;
42        self
43    }
44    /// Add cast statement
45    ///
46    /// # Arguments
47    ///
48    /// * `sql_type`: SQL type
49    ///
50    /// returns: Clause<Column>
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// use ngb_sqlbuilder::col;
56    ///
57    /// col("t.ColName").cast("text")
58    /// // SQL: t."ColName"::text
59    /// ```
60    pub fn cast(mut self, sql_type: &str) -> Self {
61        if self.sql.contains(' ') || self.sql.contains("::") {
62            self.sql = format!("({})::{}", self.sql, sql_type);
63        } else {
64            self.sql.push_str(&format!("::{}", sql_type));
65        }
66        self
67    }
68    /// Add equal `column = value` comparison
69    ///
70    /// # Arguments
71    ///
72    /// * `value`: value to compare. Will be parameterized to `$n`.
73    ///
74    /// returns: Clause<Condition>
75    ///
76    /// # Examples
77    ///
78    /// ```
79    ///
80    /// ```
81    pub fn eq<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
82        self.op("=", value)
83    }
84    /// Add not equal `column != value` comparison
85    ///
86    /// # Arguments
87    ///
88    /// * `value`: value to compare, will be parameterized to `$n`
89    ///
90    /// returns: Clause<Condition>
91    ///
92    /// # Examples
93    ///
94    /// ```
95    ///
96    /// ```
97    pub fn neq<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
98        self.op("!=", value)
99    }
100    /// Compare `column < value`
101    ///
102    /// # Arguments
103    ///
104    /// * `value`: value to compare, will be parameterized to `$n`
105    ///
106    /// returns: Clause<Condition>
107    ///
108    /// # Examples
109    ///
110    /// ```
111    ///
112    /// ```
113    pub fn lt<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
114        self.op("<", value)
115    }
116    /// Compare `column > value`
117    ///
118    /// # Arguments
119    ///
120    /// * `value`: value to compare, will be parameterized to `$n`
121    ///
122    /// returns: Clause<Condition>
123    ///
124    /// # Examples
125    ///
126    /// ```
127    ///
128    /// ```
129    pub fn gt<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
130        self.op(">", value)
131    }
132    /// Compare `column <= value`
133    ///
134    /// # Arguments
135    ///
136    /// * `value`: value to compare, will be parameterized to `$n`
137    ///
138    /// returns: Clause<Condition>
139    ///
140    /// # Examples
141    ///
142    /// ```
143    ///
144    /// ```
145    pub fn lte<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
146        self.op("<=", value)
147    }
148    /// Compare `column >= value`
149    ///
150    /// # Arguments
151    ///
152    /// * `value`: value to compare, will be parameterized to `$n`
153    ///
154    /// returns: Clause<Condition>
155    ///
156    /// # Examples
157    ///
158    /// ```
159    ///
160    /// ```
161    pub fn gte<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
162        self.op(">=", value)
163    }
164    /// Compare `column like value`
165    ///
166    /// # Arguments
167    ///
168    /// * `value`: value to compare, will be parameterized to `$n`
169    ///
170    /// returns: Clause<Condition>
171    ///
172    /// # Examples
173    ///
174    /// ```
175    ///
176    /// ```
177    pub fn like<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
178        self.op("like", value)
179    }
180    /// Compare `column ilike value`
181    ///
182    /// # Arguments
183    ///
184    /// * `value`: value to compare, will be parameterized to `$n`
185    ///
186    /// returns: Clause<Condition>
187    ///
188    /// # Examples
189    ///
190    /// ```
191    ///
192    /// ```
193    pub fn ilike<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
194        self.op("ilike", value)
195    }
196    /// Compare `column between low and high`
197    ///
198    /// # Arguments
199    ///
200    /// * `low`: bottom limit, will be parameterized to `$n`
201    /// * `high`: top limit, will be parameterized to `$n`
202    ///
203    /// returns: Clause<Condition>
204    ///
205    /// # Examples
206    ///
207    /// ```
208    ///
209    /// ```
210    pub fn between<T: ToSql + Sync + 'q>(self, low: &'q T, high: &'q T) -> Clause<'q, Condition> {
211        let (mut sql, mut params) = self.unwrap();
212        sql.push_str(" between $ and $");
213        params.push(low);
214        params.push(high);
215        Clause::<Condition>::new(sql, params)
216    }
217    /// Custom operator comparison `column op value`
218    ///
219    /// # Arguments
220    ///
221    /// * `op`: operator
222    /// * `value`: value to compare, will be parameterized to `$n`
223    ///
224    /// returns: Clause<Condition>
225    ///
226    /// # Examples
227    ///
228    /// ```
229    ///
230    /// ```
231    pub fn op<T: ToSql + Sync + 'q>(self, op: &str, value: &'q T) -> Clause<'q, Condition> {
232        let (mut sql, mut params) = self.unwrap();
233        sql.push_str(&format!(" {op} $"));
234        params.push(value);
235        Clause::<Condition>::new(sql, params)
236    }
237    pub fn is_true(self) -> Clause<'q, Condition> {
238        self.into()
239    }
240    pub fn is_false(self) -> Clause<'q, Condition> {
241        Clause::new(format!("not {}", &self.sql), self.params)
242    }
243    pub fn is_null(self) -> Clause<'q, Condition> {
244        Clause::new(format!("{} is null", &self.sql), self.params)
245    }
246    pub fn is_not_null(self) -> Clause<'q, Condition> {
247        Clause::new(format!("{} is not null", &self.sql), self.params)
248    }
249
250    /// Add raw, unchecked statement.
251    ///
252    /// # Arguments
253    ///
254    /// * `raw_sql`: SQL statement
255    ///
256    /// returns: Clause<T>
257    ///
258    /// # Examples
259    ///
260    /// ```
261    /// use ngb_sqlbuilder::col;
262    ///
263    /// col("t.ColName").raw("is not null")
264    /// // SQL: t."ColName" is not null
265    /// ```
266    pub fn raw(self, raw_sql: &str) -> Clause<'q, Column> {
267        let (mut sql, params) = self.unwrap();
268        sql.push(' ');
269        sql.push_str(&raw_sql.trim());
270        Clause::new(sql, params)
271    }
272
273    /// Set default value if `null`
274    ///
275    /// # Arguments
276    ///
277    /// * `value`: default value, will be rendered directly, no filter.
278    ///
279    /// returns: Clause<Column>
280    ///
281    /// # Examples
282    ///
283    /// ```
284    /// use ngb_sqlbuilder::col;
285    ///
286    /// col("t.ColName").coalesce_raw("0")
287    /// // SQL: coalesce(t."ColName", 0)
288    ///
289    /// col("t.TextValue").coalesce_raw("'empty'")
290    /// // SQL: coalesce(t."ColName", 'empty')
291    /// ```
292    pub fn coalesce_raw(self, value: &str) -> Self {
293        let (sql, params) = self.unwrap();
294        // let (c_sql, c_params) = value.to_clause::<Column>().unwrap();
295        Clause::new(format!("coalesce({},{})", sql, value), params)
296    }
297    /// Set default value if `null`
298    ///
299    /// # Arguments
300    ///
301    /// * `value`: default value, will be parameterized to `$n`
302    ///
303    /// returns: Clause<Condition>
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// use ngb_sqlbuilder::col;
309    ///
310    /// col("t.ColName").coalesce(0)
311    /// // SQL: coalesce(t."ColName", $n)
312    /// ```
313    pub fn coalesce<T: ToSql + Sync + 'q>(self, value: &'q T) -> Clause<'q, Condition> {
314        let (sql, mut params) = self.unwrap();
315        params.push(value);
316        Clause::new(format!("coalesce({},$)", sql), params)
317    }
318}