sea_query/extension/postgres/
func.rs

1//! For calling built-in Postgres SQL functions.
2
3use crate::{PgDateTruncUnit, expr::*, func::*};
4
5pub mod json_exists;
6pub mod json_fn;
7pub mod json_query;
8pub mod json_table;
9pub mod json_value;
10
11/// Known Postgres-specific functions.
12///
13/// For all supported functions (including the standard ones), see [`Function`].
14///
15/// If something is not supported, you can use [`Function::Custom`].
16#[derive(Debug, Clone, PartialEq)]
17#[non_exhaustive]
18pub enum PgFunc {
19    ToTsquery,
20    ToTsvector,
21    PhrasetoTsquery,
22    PlaintoTsquery,
23    WebsearchToTsquery,
24    TsRank,
25    TsRankCd,
26    StartsWith,
27    GenRandomUUID,
28    JsonBuildObject,
29    JsonAgg,
30    ArrayAgg,
31    DateTrunc,
32    #[cfg(feature = "postgres-array")]
33    Any,
34    #[cfg(feature = "postgres-array")]
35    Some,
36    #[cfg(feature = "postgres-array")]
37    All,
38}
39
40/// Type alias of [`PgFunc`] for compatibility.
41/// Previously, [`PgFunc`] is a namespace for building [`FunctionCall`].
42#[deprecated(since = "1.0.0", note = "use `PgFunc` instead")]
43pub type PgFunction = PgFunc;
44
45impl PgFunc {
46    /// Call `TO_TSQUERY` function. Postgres only.
47    ///
48    /// The parameter `regconfig` represents the OID of the text search configuration.
49    /// If the value is `None` the argument is omitted from the query, and hence the database default used.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use sea_query::{tests_cfg::*, *};
55    ///
56    /// let query = Query::select()
57    ///     .expr(PgFunc::to_tsquery("a & b", None))
58    ///     .to_owned();
59    ///
60    /// assert_eq!(
61    ///     query.to_string(PostgresQueryBuilder),
62    ///     r#"SELECT TO_TSQUERY('a & b')"#
63    /// );
64    /// ```
65    pub fn to_tsquery<T>(expr: T, regconfig: Option<u32>) -> FunctionCall
66    where
67        T: Into<Expr>,
68    {
69        match regconfig {
70            Some(config) => {
71                let config = Expr::Value(config.into());
72                FunctionCall::new(Func::PgFunction(PgFunc::ToTsquery)).args([config, expr.into()])
73            }
74            None => FunctionCall::new(Func::PgFunction(PgFunc::ToTsquery)).arg(expr),
75        }
76    }
77
78    /// Call `TO_TSVECTOR` function. Postgres only.
79    ///
80    /// The parameter `regconfig` represents the OID of the text search configuration.
81    /// If the value is `None` the argument is omitted from the query, and hence the database default used.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// use sea_query::{tests_cfg::*, *};
87    ///
88    /// let query = Query::select()
89    ///     .expr(PgFunc::to_tsvector("a b", None))
90    ///     .to_owned();
91    ///
92    /// assert_eq!(
93    ///     query.to_string(PostgresQueryBuilder),
94    ///     r#"SELECT TO_TSVECTOR('a b')"#
95    /// );
96    /// ```
97    pub fn to_tsvector<T>(expr: T, regconfig: Option<u32>) -> FunctionCall
98    where
99        T: Into<Expr>,
100    {
101        match regconfig {
102            Some(config) => {
103                let config = Expr::Value(config.into());
104                FunctionCall::new(Func::PgFunction(PgFunc::ToTsvector)).args([config, expr.into()])
105            }
106            None => FunctionCall::new(Func::PgFunction(PgFunc::ToTsvector)).arg(expr),
107        }
108    }
109
110    /// Call `PHRASE_TO_TSQUERY` function. Postgres only.
111    ///
112    /// The parameter `regconfig` represents the OID of the text search configuration.
113    /// If the value is `None` the argument is omitted from the query, and hence the database default used.
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use sea_query::{tests_cfg::*, *};
119    ///
120    /// let query = Query::select()
121    ///     .expr(PgFunc::phraseto_tsquery("a b", None))
122    ///     .to_owned();
123    ///
124    /// assert_eq!(
125    ///     query.to_string(PostgresQueryBuilder),
126    ///     r#"SELECT PHRASETO_TSQUERY('a b')"#
127    /// );
128    /// ```
129    pub fn phraseto_tsquery<T>(expr: T, regconfig: Option<u32>) -> FunctionCall
130    where
131        T: Into<Expr>,
132    {
133        match regconfig {
134            Some(config) => {
135                let config = Expr::Value(config.into());
136                FunctionCall::new(Func::PgFunction(PgFunc::PhrasetoTsquery))
137                    .args([config, expr.into()])
138            }
139            None => FunctionCall::new(Func::PgFunction(PgFunc::PhrasetoTsquery)).arg(expr),
140        }
141    }
142
143    /// Call `PLAIN_TO_TSQUERY` function. Postgres only.
144    ///
145    /// The parameter `regconfig` represents the OID of the text search configuration.
146    /// If the value is `None` the argument is omitted from the query, and hence the database default used.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// use sea_query::{tests_cfg::*, *};
152    ///
153    /// let query = Query::select()
154    ///     .expr(PgFunc::plainto_tsquery("a b", None))
155    ///     .to_owned();
156    ///
157    /// assert_eq!(
158    ///     query.to_string(PostgresQueryBuilder),
159    ///     r#"SELECT PLAINTO_TSQUERY('a b')"#
160    /// );
161    /// ```
162    pub fn plainto_tsquery<T>(expr: T, regconfig: Option<u32>) -> FunctionCall
163    where
164        T: Into<Expr>,
165    {
166        match regconfig {
167            Some(config) => {
168                let config = Expr::Value(config.into());
169                FunctionCall::new(Func::PgFunction(PgFunc::PlaintoTsquery))
170                    .args([config, expr.into()])
171            }
172            None => FunctionCall::new(Func::PgFunction(PgFunc::PlaintoTsquery)).arg(expr),
173        }
174    }
175
176    /// Call `WEBSEARCH_TO_TSQUERY` function. Postgres only.
177    ///
178    /// The parameter `regconfig` represents the OID of the text search configuration.
179    /// If the value is `None` the argument is omitted from the query, and hence the database default used.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use sea_query::{tests_cfg::*, *};
185    ///
186    /// let query = Query::select()
187    ///     .expr(PgFunc::websearch_to_tsquery("a b", None))
188    ///     .to_owned();
189    ///
190    /// assert_eq!(
191    ///     query.to_string(PostgresQueryBuilder),
192    ///     r#"SELECT WEBSEARCH_TO_TSQUERY('a b')"#
193    /// );
194    /// ```
195    pub fn websearch_to_tsquery<T>(expr: T, regconfig: Option<u32>) -> FunctionCall
196    where
197        T: Into<Expr>,
198    {
199        match regconfig {
200            Some(config) => {
201                let config = Expr::Value(config.into());
202                FunctionCall::new(Func::PgFunction(PgFunc::WebsearchToTsquery))
203                    .args([config, expr.into()])
204            }
205            None => FunctionCall::new(Func::PgFunction(PgFunc::WebsearchToTsquery)).arg(expr),
206        }
207    }
208
209    /// Call `TS_RANK` function. Postgres only.
210    ///
211    /// # Examples
212    ///
213    /// ```
214    /// use sea_query::{tests_cfg::*, *};
215    ///
216    /// let query = Query::select()
217    ///     .expr(PgFunc::ts_rank("a b", "a&b"))
218    ///     .to_owned();
219    ///
220    /// assert_eq!(
221    ///     query.to_string(PostgresQueryBuilder),
222    ///     r#"SELECT TS_RANK('a b', 'a&b')"#
223    /// );
224    /// ```
225    pub fn ts_rank<T>(vector: T, query: T) -> FunctionCall
226    where
227        T: Into<Expr>,
228    {
229        FunctionCall::new(Func::PgFunction(PgFunc::TsRank)).args([vector.into(), query.into()])
230    }
231
232    /// Call `TS_RANK_CD` function. Postgres only.
233    ///
234    /// # Examples
235    ///
236    /// ```
237    /// use sea_query::{tests_cfg::*, *};
238    ///
239    /// let query = Query::select()
240    ///     .expr(PgFunc::ts_rank_cd("a b", "a&b"))
241    ///     .to_owned();
242    ///
243    /// assert_eq!(
244    ///     query.to_string(PostgresQueryBuilder),
245    ///     r#"SELECT TS_RANK_CD('a b', 'a&b')"#
246    /// );
247    /// ```
248    pub fn ts_rank_cd<T>(vector: T, query: T) -> FunctionCall
249    where
250        T: Into<Expr>,
251    {
252        FunctionCall::new(Func::PgFunction(PgFunc::TsRankCd)).args([vector.into(), query.into()])
253    }
254
255    /// Call `ANY` function. Postgres only.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// use sea_query::{tests_cfg::*, *};
261    ///
262    /// let query = Query::select().expr(PgFunc::any(vec![0, 1])).to_owned();
263    ///
264    /// assert_eq!(
265    ///     query.to_string(PostgresQueryBuilder),
266    ///     r#"SELECT ANY(ARRAY [0,1])"#
267    /// );
268    /// ```
269    #[cfg(feature = "postgres-array")]
270    pub fn any<T>(expr: T) -> FunctionCall
271    where
272        T: Into<Expr>,
273    {
274        FunctionCall::new(Func::PgFunction(PgFunc::Any)).arg(expr)
275    }
276
277    /// Call `SOME` function. Postgres only.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// use sea_query::{tests_cfg::*, *};
283    ///
284    /// let query = Query::select().expr(PgFunc::some(vec![0, 1])).to_owned();
285    ///
286    /// assert_eq!(
287    ///     query.to_string(PostgresQueryBuilder),
288    ///     r#"SELECT SOME(ARRAY [0,1])"#
289    /// );
290    /// ```
291    #[cfg(feature = "postgres-array")]
292    pub fn some<T>(expr: T) -> FunctionCall
293    where
294        T: Into<Expr>,
295    {
296        FunctionCall::new(Func::PgFunction(PgFunc::Some)).arg(expr)
297    }
298
299    /// Call `ALL` function. Postgres only.
300    ///
301    /// # Examples
302    ///
303    /// ```
304    /// use sea_query::{tests_cfg::*, *};
305    ///
306    /// let query = Query::select().expr(PgFunc::all(vec![0, 1])).to_owned();
307    ///
308    /// assert_eq!(
309    ///     query.to_string(PostgresQueryBuilder),
310    ///     r#"SELECT ALL(ARRAY [0,1])"#
311    /// );
312    /// ```
313    #[cfg(feature = "postgres-array")]
314    pub fn all<T>(expr: T) -> FunctionCall
315    where
316        T: Into<Expr>,
317    {
318        FunctionCall::new(Func::PgFunction(PgFunc::All)).arg(expr)
319    }
320
321    /// Call `STARTS_WITH` function. Postgres only.
322    ///
323    /// # Examples
324    ///
325    /// ```
326    /// use sea_query::{tests_cfg::*, *};
327    ///
328    /// let query = Query::select()
329    ///     .expr(PgFunc::starts_with("123", "1"))
330    ///     .to_owned();
331    ///
332    /// assert_eq!(
333    ///     query.to_string(PostgresQueryBuilder),
334    ///     r#"SELECT STARTS_WITH('123', '1')"#
335    /// );
336    /// ```
337    pub fn starts_with<T, P>(text: T, prefix: P) -> FunctionCall
338    where
339        T: Into<Expr>,
340        P: Into<Expr>,
341    {
342        FunctionCall::new(Func::PgFunction(PgFunc::StartsWith)).args([text.into(), prefix.into()])
343    }
344
345    /// Call `GEN_RANDOM_UUID` function. Postgres only.
346    ///
347    /// # Examples
348    ///
349    /// ```
350    /// use sea_query::{tests_cfg::*, *};
351    ///
352    /// let query = Query::select().expr(PgFunc::gen_random_uuid()).to_owned();
353    ///
354    /// assert_eq!(
355    ///     query.to_string(PostgresQueryBuilder),
356    ///     r#"SELECT GEN_RANDOM_UUID()"#
357    /// );
358    /// ```
359    pub fn gen_random_uuid() -> FunctionCall {
360        FunctionCall::new(Func::PgFunction(PgFunc::GenRandomUUID))
361    }
362
363    /// Call the `JSON_BUILD_OBJECT` function. Postgres only.
364    ///
365    /// # Examples
366    ///
367    /// ```
368    /// use sea_query::{tests_cfg::*, *};
369    ///
370    /// let query = Query::select()
371    ///     .expr(PgFunc::json_build_object(vec![
372    ///         (Expr::val("a"), Expr::val(1)),
373    ///         (Expr::val("b"), Expr::val("2")),
374    ///     ]))
375    ///     .to_owned();
376    ///
377    /// assert_eq!(
378    ///     query.to_string(PostgresQueryBuilder),
379    ///     r#"SELECT JSON_BUILD_OBJECT('a', 1, 'b', '2')"#
380    /// );
381    /// ```
382    pub fn json_build_object<T>(pairs: Vec<(T, T)>) -> FunctionCall
383    where
384        T: Into<Expr>,
385    {
386        let mut args = vec![];
387        for (key, value) in pairs {
388            args.push(key.into());
389            args.push(value.into());
390        }
391        FunctionCall::new(Func::PgFunction(PgFunc::JsonBuildObject)).args(args)
392    }
393
394    /// Call the `DATE_TRUNC` function. Postgres only.
395    ///
396    /// # Examples
397    ///
398    /// ```
399    /// use sea_query::{tests_cfg::*, *};
400    ///
401    /// let query = Query::select()
402    ///     .expr(PgFunc::date_trunc(
403    ///         PgDateTruncUnit::Day,
404    ///         Expr::val("2020-01-01"),
405    ///     ))
406    ///     .to_owned();
407    ///
408    /// assert_eq!(
409    ///     query.to_string(PostgresQueryBuilder),
410    ///     r#"SELECT DATE_TRUNC('day', '2020-01-01')"#
411    /// );
412    ///
413    /// let query = Query::select()
414    ///     .expr(PgFunc::date_trunc(
415    ///         PgDateTruncUnit::Microseconds,
416    ///         Expr::val("2020-01-01"),
417    ///     ))
418    ///     .to_owned();
419    ///
420    /// assert_eq!(
421    ///     query.to_string(PostgresQueryBuilder),
422    ///     r#"SELECT DATE_TRUNC('microseconds', '2020-01-01')"#
423    /// );
424    /// ```
425    pub fn date_trunc<T>(unit: PgDateTruncUnit, expr: T) -> FunctionCall
426    where
427        T: Into<Expr>,
428    {
429        FunctionCall::new(Func::PgFunction(PgFunc::DateTrunc))
430            .args([Expr::val(unit.to_string()), expr.into()])
431    }
432
433    /// Call the `JSON_AGG` function. Postgres only.
434    ///
435    /// # Examples
436    ///
437    /// ```
438    /// use sea_query::{tests_cfg::*, *};
439    ///
440    /// let query = Query::select()
441    ///     .from(Char::Table)
442    ///     .expr(PgFunc::json_agg(Expr::col(Char::SizeW)))
443    ///     .to_owned();
444    ///
445    /// assert_eq!(
446    ///     query.to_string(PostgresQueryBuilder),
447    ///     r#"SELECT JSON_AGG("size_w") FROM "character""#
448    /// );
449    /// ```
450    pub fn json_agg<T>(expr: T) -> FunctionCall
451    where
452        T: Into<Expr>,
453    {
454        FunctionCall::new(Func::PgFunction(PgFunc::JsonAgg)).arg(expr)
455    }
456
457    /// Call the `ARRAY_AGG` function. Postgres only.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// use sea_query::{tests_cfg::*, *};
463    ///
464    /// let query = Query::select()
465    ///     .from(Char::Table)
466    ///     .expr(PgFunc::array_agg(Expr::col(Char::Id)))
467    ///     .group_by_col(Char::Character)
468    ///     .to_owned();
469    ///
470    /// assert_eq!(
471    ///     query.to_string(PostgresQueryBuilder),
472    ///     r#"SELECT ARRAY_AGG("id") FROM "character" GROUP BY "character""#
473    /// );
474    /// ```
475    pub fn array_agg<T>(expr: T) -> FunctionCall
476    where
477        T: Into<Expr>,
478    {
479        FunctionCall::new(Func::PgFunction(PgFunc::ArrayAgg)).arg(expr)
480    }
481
482    /// Call the `ARRAY_AGG` function with the `DISTINCT` modifier. Postgres only.
483    ///
484    /// # Examples
485    ///
486    /// ```
487    /// use sea_query::{tests_cfg::*, *};
488    ///
489    /// let query = Query::select()
490    ///     .from(Char::Table)
491    ///     .expr(PgFunc::array_agg_distinct(Expr::col(Char::Id)))
492    ///     .group_by_col(Char::Character)
493    ///     .to_owned();
494    ///
495    /// assert_eq!(
496    ///     query.to_string(PostgresQueryBuilder),
497    ///     r#"SELECT ARRAY_AGG(DISTINCT "id") FROM "character" GROUP BY "character""#
498    /// );
499    /// ```
500    pub fn array_agg_distinct<T>(expr: T) -> FunctionCall
501    where
502        T: Into<Expr>,
503    {
504        FunctionCall::new(Func::PgFunction(PgFunc::ArrayAgg))
505            .arg_with(expr, FuncArgMod { distinct: true })
506    }
507}