sea_query/extension/postgres/
expr.rs

1use super::PgBinOper;
2use crate::{Expr, ExprTrait, IntoLikeExpr};
3
4/// Postgres-specific operator methods for building expressions.
5pub trait PgExpr: ExprTrait {
6    /// Express an postgres concatenate (`||`) expression.
7    ///
8    /// # Examples
9    ///
10    /// ```
11    /// use sea_query::{extension::postgres::PgExpr, tests_cfg::*, *};
12    ///
13    /// let query = Query::select().expr(Expr::val("a").concatenate("b")).take();
14    ///
15    /// assert_eq!(
16    ///     query.to_string(PostgresQueryBuilder),
17    ///     r#"SELECT 'a' || 'b'"#
18    /// );
19    ///
20    /// #[cfg(feature = "postgres-array")]
21    /// {
22    ///     let query = Query::select()
23    ///         .expr(Expr::val(vec!["a".to_owned()]).concatenate(vec!["b".to_owned()]))
24    ///         .take();
25    ///
26    ///     assert_eq!(
27    ///         query.to_string(PostgresQueryBuilder),
28    ///         r#"SELECT ARRAY ['a'] || ARRAY ['b']"#
29    ///     );
30    /// }
31    /// ```
32    fn concatenate<T>(self, right: T) -> Expr
33    where
34        T: Into<Expr>,
35    {
36        self.binary(PgBinOper::Concatenate, right)
37    }
38
39    /// Alias of [`PgExpr::concatenate`]
40    fn concat<T>(self, right: T) -> Expr
41    where
42        T: Into<Expr>,
43    {
44        self.concatenate(right)
45    }
46
47    /// Express an postgres fulltext search matches (`@@`) expression.
48    ///
49    /// # Examples
50    ///
51    /// ```
52    /// use sea_query::{*, tests_cfg::*, extension::postgres::PgExpr};
53    ///
54    /// let query = Query::select()
55    ///     .columns([Font::Name, Font::Variant, Font::Language])
56    ///     .from(Font::Table)
57    ///     .and_where(Expr::val("a & b").matches("a b"))
58    ///     .and_where(Expr::col(Font::Name).matches("a b"))
59    ///     .to_owned();
60    ///
61    /// assert_eq!(
62    ///     query.to_string(PostgresQueryBuilder),
63    ///     r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' @@ 'a b' AND "name" @@ 'a b'"#
64    /// );
65    /// ```
66    fn matches<T>(self, expr: T) -> Expr
67    where
68        T: Into<Expr>,
69    {
70        self.binary(PgBinOper::Matches, expr)
71    }
72
73    /// Express an postgres fulltext search contains (`@>`) expression.
74    ///
75    /// # Examples
76    ///
77    /// ```
78    /// use sea_query::{*, tests_cfg::*, extension::postgres::PgExpr};
79    ///
80    /// let query = Query::select()
81    ///     .columns([Font::Name, Font::Variant, Font::Language])
82    ///     .from(Font::Table)
83    ///     .and_where(Expr::val("a & b").contains("a b"))
84    ///     .and_where(Expr::col(Font::Name).contains("a b"))
85    ///     .to_owned();
86    ///
87    /// assert_eq!(
88    ///     query.to_string(PostgresQueryBuilder),
89    ///     r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' @> 'a b' AND "name" @> 'a b'"#
90    /// );
91    /// ```
92    fn contains<T>(self, expr: T) -> Expr
93    where
94        T: Into<Expr>,
95    {
96        self.binary(PgBinOper::Contains, expr)
97    }
98
99    /// Express an postgres fulltext search contained (`<@`) expression.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use sea_query::{*, tests_cfg::*, extension::postgres::PgExpr};
105    ///
106    /// let query = Query::select()
107    ///     .columns([Font::Name, Font::Variant, Font::Language])
108    ///     .from(Font::Table)
109    ///     .and_where(Expr::val("a & b").contained("a b"))
110    ///     .and_where(Expr::col(Font::Name).contained("a b"))
111    ///     .to_owned();
112    ///
113    /// assert_eq!(
114    ///     query.to_string(PostgresQueryBuilder),
115    ///     r#"SELECT "name", "variant", "language" FROM "font" WHERE 'a & b' <@ 'a b' AND "name" <@ 'a b'"#
116    /// );
117    /// ```
118    fn contained<T>(self, expr: T) -> Expr
119    where
120        T: Into<Expr>,
121    {
122        self.binary(PgBinOper::Contained, expr)
123    }
124
125    /// Express a `ILIKE` expression.
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// use sea_query::{*, tests_cfg::*, extension::postgres::PgExpr};
131    ///
132    /// let query = Query::select()
133    ///     .columns([Char::Character, Char::SizeW, Char::SizeH])
134    ///     .from(Char::Table)
135    ///     .and_where(Expr::col((Char::Table, Char::Character)).ilike("Ours'%"))
136    ///     .to_owned();
137    ///
138    /// assert_eq!(
139    ///     query.to_string(PostgresQueryBuilder),
140    ///     r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."character" ILIKE E'Ours\'%'"#
141    /// );
142    /// ```
143    fn ilike<L>(self, like: L) -> Expr
144    where
145        L: IntoLikeExpr,
146    {
147        self.binary(PgBinOper::ILike, like.into_like_expr())
148    }
149
150    /// Express a `NOT ILIKE` expression
151    fn not_ilike<L>(self, like: L) -> Expr
152    where
153        L: IntoLikeExpr,
154    {
155        self.binary(PgBinOper::NotILike, like.into_like_expr())
156    }
157
158    /// Express a postgres retrieves JSON field as JSON value (`->`).
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use sea_query::{extension::postgres::PgExpr, tests_cfg::*, *};
164    ///
165    /// let query = Query::select()
166    ///     .column(Font::Variant)
167    ///     .from(Font::Table)
168    ///     .and_where(Expr::col(Font::Variant).get_json_field("a"))
169    ///     .to_owned();
170    ///
171    /// assert_eq!(
172    ///     query.to_string(PostgresQueryBuilder),
173    ///     r#"SELECT "variant" FROM "font" WHERE "variant" -> 'a'"#
174    /// );
175    /// ```
176    fn get_json_field<T>(self, right: T) -> Expr
177    where
178        T: Into<Expr>,
179    {
180        self.binary(PgBinOper::GetJsonField, right)
181    }
182
183    /// Express a postgres retrieves JSON field and casts it to an appropriate SQL type (`->>`).
184    ///
185    /// # Examples
186    ///
187    /// ```
188    /// use sea_query::{extension::postgres::PgExpr, tests_cfg::*, *};
189    ///
190    /// let query = Query::select()
191    ///     .column(Font::Variant)
192    ///     .from(Font::Table)
193    ///     .and_where(Expr::col(Font::Variant).cast_json_field("a"))
194    ///     .to_owned();
195    ///
196    /// assert_eq!(
197    ///     query.to_string(PostgresQueryBuilder),
198    ///     r#"SELECT "variant" FROM "font" WHERE "variant" ->> 'a'"#
199    /// );
200    /// ```
201    fn cast_json_field<T>(self, right: T) -> Expr
202    where
203        T: Into<Expr>,
204    {
205        self.binary(PgBinOper::CastJsonField, right)
206    }
207}
208
209/// You should be able to use Postgres-specific operators with all types of expressions.
210impl<T> PgExpr for T where T: ExprTrait {}