sea_query/extension/postgres/
expr.rs

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