sea_query/extension/postgres/
expr.rs

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