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 {}