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