diesel/pg/expression/
expression_methods.rs

1//! PostgreSQL specific expression methods
2
3pub(in crate::pg) use self::private::{
4    ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJsonOrJsonbOrNullableJsonb,
5    JsonRemoveIndex, JsonbOrNullableJsonb, RangeHelper, RangeOrNullableRange, TextOrNullableText,
6};
7use super::date_and_time::{AtTimeZone, DateTimeLike};
8use super::operators::*;
9use crate::dsl;
10use crate::expression::grouped::Grouped;
11use crate::expression::operators::{Asc, Concat, Desc, Like, NotLike};
12use crate::expression::{AsExpression, Expression, IntoSql, TypedExpressionType};
13use crate::pg::expression::expression_methods::private::BinaryOrNullableBinary;
14use crate::sql_types::{Array, Inet, Integer, SqlType, Text, VarChar};
15use crate::EscapeExpressionMethods;
16
17/// PostgreSQL specific methods which are present on all expressions.
18#[cfg(feature = "postgres_backend")]
19pub trait PgExpressionMethods: Expression + Sized {
20    /// Creates a PostgreSQL `IS NOT DISTINCT FROM` expression.
21    ///
22    /// This behaves identically to the `=` operator, except that `NULL` is
23    /// treated as a normal value.
24    ///
25    /// # Example
26    ///
27    /// ```rust
28    /// # include!("../../doctest_setup.rs");
29    /// #
30    /// # fn main() {
31    /// #     use schema::users::dsl::*;
32    /// #     let connection = &mut establish_connection();
33    /// let distinct = users.select(id).filter(name.is_distinct_from("Sean"));
34    /// let not_distinct = users.select(id).filter(name.is_not_distinct_from("Sean"));
35    /// assert_eq!(Ok(2), distinct.first(connection));
36    /// assert_eq!(Ok(1), not_distinct.first(connection));
37    /// # }
38    /// ```
39    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
40    fn is_not_distinct_from<T>(self, other: T) -> dsl::IsNotDistinctFrom<Self, T>
41    where
42        Self::SqlType: SqlType,
43        T: AsExpression<Self::SqlType>,
44    {
45        Grouped(IsNotDistinctFrom::new(self, other.as_expression()))
46    }
47
48    /// Creates a PostgreSQL `IS DISTINCT FROM` expression.
49    ///
50    /// This behaves identically to the `!=` operator, except that `NULL` is
51    /// treated as a normal value.
52    ///
53    /// # Example
54    ///
55    /// ```rust
56    /// # include!("../../doctest_setup.rs");
57    /// #
58    /// # fn main() {
59    /// #     use schema::users::dsl::*;
60    /// #     let connection = &mut establish_connection();
61    /// let distinct = users.select(id).filter(name.is_distinct_from("Sean"));
62    /// let not_distinct = users.select(id).filter(name.is_not_distinct_from("Sean"));
63    /// assert_eq!(Ok(2), distinct.first(connection));
64    /// assert_eq!(Ok(1), not_distinct.first(connection));
65    /// # }
66    /// ```
67    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
68    fn is_distinct_from<T>(self, other: T) -> dsl::IsDistinctFrom<Self, T>
69    where
70        Self::SqlType: SqlType,
71        T: AsExpression<Self::SqlType>,
72    {
73        Grouped(IsDistinctFrom::new(self, other.as_expression()))
74    }
75}
76
77impl<T: Expression> PgExpressionMethods for T {}
78
79/// PostgreSQL specific methods present on timestamp expressions.
80#[cfg(feature = "postgres_backend")]
81pub trait PgTimestampExpressionMethods: Expression + Sized {
82    /// Creates a PostgreSQL "AT TIME ZONE" expression.
83    ///
84    /// When this is called on a `TIMESTAMP WITHOUT TIME ZONE` column,
85    /// the value will be treated as if were in the given time zone,
86    /// and then converted to UTC.
87    ///
88    /// When this is called on a `TIMESTAMP WITH TIME ZONE` column,
89    /// the value will be converted to the given time zone,
90    /// and then have its time zone information removed.
91    ///
92    /// # Example
93    ///
94    /// ```rust
95    /// # include!("../../doctest_setup.rs");
96    /// #
97    /// # table! {
98    /// #     timestamps (timestamp) {
99    /// #         timestamp -> Timestamp,
100    /// #     }
101    /// # }
102    /// #
103    /// # fn main() {
104    /// #     run_test().unwrap();
105    /// # }
106    /// #
107    /// # #[cfg(all(feature = "postgres", feature = "chrono"))]
108    /// # fn run_test() -> QueryResult<()> {
109    /// #     use self::timestamps::dsl::*;
110    /// #     use chrono::*;
111    /// #     let connection = &mut establish_connection();
112    /// #     diesel::sql_query("CREATE TABLE timestamps (\"timestamp\"
113    /// #         timestamp NOT NULL)").execute(connection)?;
114    /// let christmas_morning = NaiveDate::from_ymd(2017, 12, 25)
115    ///     .and_hms(8, 0, 0);
116    /// diesel::insert_into(timestamps)
117    ///     .values(timestamp.eq(christmas_morning))
118    ///     .execute(connection)?;
119    ///
120    /// let utc_time = timestamps
121    ///     .select(timestamp.at_time_zone("UTC"))
122    ///     .first(connection)?;
123    /// assert_eq!(christmas_morning, utc_time);
124    ///
125    /// let eastern_time = timestamps
126    ///     .select(timestamp.at_time_zone("EST"))
127    ///     .first(connection)?;
128    /// let five_hours_later = christmas_morning + Duration::hours(5);
129    /// assert_eq!(five_hours_later, eastern_time);
130    /// #     Ok(())
131    /// # }
132    /// #
133    /// # #[cfg(not(all(feature = "postgres", feature = "chrono")))]
134    /// # fn run_test() -> QueryResult<()> {
135    /// #     Ok(())
136    /// # }
137    /// ```
138    fn at_time_zone<T>(self, timezone: T) -> dsl::AtTimeZone<Self, T>
139    where
140        T: AsExpression<VarChar>,
141    {
142        Grouped(AtTimeZone::new(self, timezone.as_expression()))
143    }
144}
145
146impl<T: Expression> PgTimestampExpressionMethods for T where T::SqlType: DateTimeLike {}
147
148/// PostgreSQL specific methods present on array expressions.
149#[cfg(feature = "postgres_backend")]
150pub trait PgArrayExpressionMethods: Expression + Sized {
151    /// Creates a PostgreSQL `&&` expression.
152    ///
153    /// This operator returns whether two arrays have common elements.
154    ///
155    /// # Example
156    ///
157    /// ```rust
158    /// # include!("../../doctest_setup.rs");
159    /// #
160    /// # table! {
161    /// #     posts {
162    /// #         id -> Integer,
163    /// #         tags -> Array<VarChar>,
164    /// #     }
165    /// # }
166    /// #
167    /// # fn main() {
168    /// #     run_test().unwrap();
169    /// # }
170    /// #
171    /// # fn run_test() -> QueryResult<()> {
172    /// #     use self::posts::dsl::*;
173    /// #     let conn = &mut establish_connection();
174    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
175    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
176    /// #           .execute(conn)
177    /// #           .unwrap();
178    /// #
179    /// diesel::insert_into(posts)
180    ///     .values(&vec![
181    ///         tags.eq(vec!["cool", "awesome"]),
182    ///         tags.eq(vec!["awesome", "great"]),
183    ///         tags.eq(vec!["cool", "great"]),
184    ///     ])
185    ///     .execute(conn)?;
186    ///
187    /// let data = posts.select(id)
188    ///     .filter(tags.overlaps_with(vec!["horrid", "cool"]))
189    ///     .load::<i32>(conn)?;
190    /// assert_eq!(vec![1, 3], data);
191    ///
192    /// let data = posts.select(id)
193    ///     .filter(tags.overlaps_with(vec!["cool", "great"]))
194    ///     .load::<i32>(conn)?;
195    /// assert_eq!(vec![1, 2, 3], data);
196    ///
197    /// let data = posts.select(id)
198    ///     .filter(tags.overlaps_with(vec!["horrid"]))
199    ///     .load::<i32>(conn)?;
200    /// assert!(data.is_empty());
201    /// #     Ok(())
202    /// # }
203    /// ```
204    fn overlaps_with<T>(self, other: T) -> dsl::OverlapsWith<Self, T>
205    where
206        Self::SqlType: SqlType,
207        T: AsExpression<Self::SqlType>,
208    {
209        Grouped(OverlapsWith::new(self, other.as_expression()))
210    }
211
212    /// Creates a PostgreSQL `@>` expression.
213    ///
214    /// This operator returns whether an array contains another array.
215    ///
216    /// # Example
217    ///
218    /// ```rust
219    /// # include!("../../doctest_setup.rs");
220    /// #
221    /// # table! {
222    /// #     posts {
223    /// #         id -> Integer,
224    /// #         tags -> Array<VarChar>,
225    /// #     }
226    /// # }
227    /// #
228    /// # fn main() {
229    /// #     run_test().unwrap();
230    /// # }
231    /// #
232    /// # fn run_test() -> QueryResult<()> {
233    /// #     use self::posts::dsl::*;
234    /// #     let conn = &mut establish_connection();
235    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
236    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
237    /// #         .execute(conn)
238    /// #         .unwrap();
239    /// #
240    /// diesel::insert_into(posts)
241    ///     .values(tags.eq(vec!["cool", "awesome"]))
242    ///     .execute(conn)?;
243    ///
244    /// let cool_posts = posts.select(id)
245    ///     .filter(tags.contains(vec!["cool"]))
246    ///     .load::<i32>(conn)?;
247    /// assert_eq!(vec![1], cool_posts);
248    ///
249    /// let amazing_posts = posts.select(id)
250    ///     .filter(tags.contains(vec!["cool", "amazing"]))
251    ///     .load::<i32>(conn)?;
252    /// assert!(amazing_posts.is_empty());
253    /// #     Ok(())
254    /// # }
255    /// ```
256    fn contains<T>(self, other: T) -> dsl::Contains<Self, T>
257    where
258        Self::SqlType: SqlType,
259        T: AsExpression<Self::SqlType>,
260    {
261        Grouped(Contains::new(self, other.as_expression()))
262    }
263
264    /// Creates a PostgreSQL `<@` expression.
265    ///
266    /// This operator returns whether an array is contained by another array.
267    /// `foo.contains(bar)` is the same as `bar.is_contained_by(foo)`
268    ///
269    /// # Example
270    ///
271    /// ```rust
272    /// # include!("../../doctest_setup.rs");
273    /// #
274    /// # table! {
275    /// #     posts {
276    /// #         id -> Integer,
277    /// #         tags -> Array<VarChar>,
278    /// #     }
279    /// # }
280    /// #
281    /// # fn main() {
282    /// #     run_test().unwrap();
283    /// # }
284    /// #
285    /// # fn run_test() -> QueryResult<()> {
286    /// #     use self::posts::dsl::*;
287    /// #     let conn = &mut establish_connection();
288    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
289    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
290    /// #         .execute(conn)
291    /// #         .unwrap();
292    /// #
293    /// diesel::insert_into(posts)
294    ///     .values(tags.eq(vec!["cool", "awesome"]))
295    ///     .execute(conn)?;
296    ///
297    /// let data = posts.select(id)
298    ///     .filter(tags.is_contained_by(vec!["cool", "awesome", "amazing"]))
299    ///     .load::<i32>(conn)?;
300    /// assert_eq!(vec![1], data);
301    ///
302    /// let data = posts.select(id)
303    ///     .filter(tags.is_contained_by(vec!["cool"]))
304    ///     .load::<i32>(conn)?;
305    /// assert!(data.is_empty());
306    /// #     Ok(())
307    /// # }
308    /// ```
309    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
310    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
311    where
312        Self::SqlType: SqlType,
313        T: AsExpression<Self::SqlType>,
314    {
315        Grouped(IsContainedBy::new(self, other.as_expression()))
316    }
317    /// Indexes a PostgreSQL array.
318    ///
319    /// This operator indexes in to an array to access a single element.
320    ///
321    /// Note that PostgreSQL arrays are 1-indexed, so `foo.index(1)` is the
322    /// first element in the array.
323    ///
324    /// # Example
325    ///
326    /// ```rust
327    /// # include!("../../doctest_setup.rs");
328    /// #
329    /// # table! {
330    /// #     posts {
331    /// #         id -> Integer,
332    /// #         tags -> Array<VarChar>,
333    /// #     }
334    /// # }
335    /// #
336    /// # fn main() {
337    /// #     run_test().unwrap();
338    /// # }
339    /// #
340    /// # fn run_test() -> QueryResult<()> {
341    /// #     use self::posts::dsl::*;
342    /// #     let conn = &mut establish_connection();
343    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
344    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
345    /// #         .execute(conn)
346    /// #         .unwrap();
347    /// #
348    /// diesel::insert_into(posts)
349    ///     .values(&vec![
350    ///         tags.eq(vec!["cool", "awesome"]),
351    ///         tags.eq(vec!["splendid", "marvellous"]),
352    ///    ])
353    ///     .execute(conn)?;
354    ///
355    /// let data = posts.select(tags.index(id))
356    ///     .load::<String>(conn)?;
357    /// assert_eq!(vec!["cool", "marvellous"], data);
358    ///
359    /// let data = posts.select(id)
360    ///     .filter(tags.index(1).eq("splendid"))
361    ///     .load::<i32>(conn)?;
362    /// assert_eq!(vec![2], data);
363    /// #     Ok(())
364    /// # }
365    /// ```
366    fn index<T>(self, other: T) -> dsl::Index<Self, T>
367    where
368        Self::SqlType: SqlType,
369        T: AsExpression<Integer>,
370    {
371        ArrayIndex::new(self, other.as_expression())
372    }
373
374    /// Creates a PostgreSQL `||` expression.
375    ///
376    /// This operator concatenates two Array values and returns Array value
377    ///
378    /// # Example
379    ///
380    /// ```rust
381    /// # include!("../../doctest_setup.rs");
382    /// #
383    /// # table! {
384    /// #     posts {
385    /// #         id -> Integer,
386    /// #         tags -> Array<VarChar>,
387    /// #     }
388    /// # }
389    /// #
390    /// # fn main() {
391    /// #     run_test().unwrap();
392    /// # }
393    /// #
394    /// # fn run_test() -> QueryResult<()> {
395    /// #     use self::posts::dsl::*;
396    /// #     let conn = &mut establish_connection();
397    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
398    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
399    /// #         .execute(conn)
400    /// #         .unwrap();
401    /// #
402    /// diesel::insert_into(posts)
403    ///     .values(tags.eq(vec!["cool", "awesome"]))
404    ///     .execute(conn)?;
405    ///
406    /// let res = posts.select(tags.concat(vec!["amazing"])).load::<Vec<String>>(conn)?;
407    /// let expected_tags = vec!["cool", "awesome", "amazing"];
408    /// assert_eq!(expected_tags, res[0]);
409    /// #     Ok(())
410    /// # }
411    ///
412    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
413    where
414        Self::SqlType: SqlType,
415        T: AsExpression<Self::SqlType>,
416    {
417        Grouped(Concat::new(self, other.as_expression()))
418    }
419}
420
421impl<T> PgArrayExpressionMethods for T
422where
423    T: Expression,
424    T::SqlType: ArrayOrNullableArray,
425{
426}
427
428/// PostgreSQL expression methods related to sorting.
429///
430/// This trait is only implemented for `Asc` and `Desc`. Although `.asc` is
431/// implicit if no order is given, you will need to call `.asc()` explicitly in
432/// order to call these methods.
433#[cfg(feature = "postgres_backend")]
434pub trait PgSortExpressionMethods: Sized {
435    /// Specify that nulls should come before other values in this ordering.
436    ///
437    /// Normally, nulls come last when sorting in ascending order and first
438    /// when sorting in descending order.
439    ///
440    /// # Example
441    ///
442    /// ```rust
443    /// # include!("../../doctest_setup.rs");
444    /// #
445    /// # table! {
446    /// #     nullable_numbers (nullable_number) {
447    /// #         nullable_number -> Nullable<Integer>,
448    /// #     }
449    /// # }
450    /// #
451    /// # fn main() {
452    /// #     run_test().unwrap();
453    /// # }
454    /// #
455    /// # fn run_test() -> QueryResult<()> {
456    /// #     use self::nullable_numbers::dsl::*;
457    /// #     let connection = &mut connection_no_data();
458    /// #     diesel::sql_query("CREATE TABLE nullable_numbers (nullable_number INTEGER)").execute(connection)?;
459    /// diesel::insert_into(nullable_numbers)
460    ///     .values(&vec![
461    ///         nullable_number.eq(None),
462    ///         nullable_number.eq(Some(1)),
463    ///         nullable_number.eq(Some(2)),
464    ///     ])
465    ///     .execute(connection)?;
466    ///
467    /// let asc_default_nulls = nullable_numbers.select(nullable_number)
468    ///     .order(nullable_number.asc())
469    ///     .load::<Option<i32>>(connection)?;
470    /// assert_eq!(vec![Some(1), Some(2), None], asc_default_nulls);
471    ///
472    /// let asc_nulls_first = nullable_numbers.select(nullable_number)
473    ///     .order(nullable_number.asc().nulls_first())
474    ///     .load::<Option<i32>>(connection)?;
475    /// assert_eq!(vec![None, Some(1), Some(2)], asc_nulls_first);
476    /// #     Ok(())
477    /// # }
478    /// ```
479    fn nulls_first(self) -> dsl::NullsFirst<Self> {
480        NullsFirst::new(self)
481    }
482
483    /// Specify that nulls should come after other values in this ordering.
484    ///
485    /// Normally, nulls come last when sorting in ascending order and first
486    /// when sorting in descending order.
487    ///
488    /// # Example
489    ///
490    /// ```rust
491    /// # include!("../../doctest_setup.rs");
492    /// #
493    /// # table! {
494    /// #     nullable_numbers (nullable_number) {
495    /// #         nullable_number -> Nullable<Integer>,
496    /// #     }
497    /// # }
498    /// #
499    /// # fn main() {
500    /// #     run_test().unwrap();
501    /// # }
502    /// #
503    /// # fn run_test() -> QueryResult<()> {
504    /// #     use self::nullable_numbers::dsl::*;
505    /// #     let connection = &mut connection_no_data();
506    /// #     diesel::sql_query("CREATE TABLE nullable_numbers (nullable_number INTEGER)").execute(connection)?;
507    /// diesel::insert_into(nullable_numbers)
508    ///     .values(&vec![
509    ///         nullable_number.eq(None),
510    ///         nullable_number.eq(Some(1)),
511    ///         nullable_number.eq(Some(2)),
512    ///     ])
513    ///     .execute(connection)?;
514    ///
515    /// let desc_default_nulls = nullable_numbers.select(nullable_number)
516    ///     .order(nullable_number.desc())
517    ///     .load::<Option<i32>>(connection)?;
518    /// assert_eq!(vec![None, Some(2), Some(1)], desc_default_nulls);
519    ///
520    /// let desc_nulls_last = nullable_numbers.select(nullable_number)
521    ///     .order(nullable_number.desc().nulls_last())
522    ///     .load::<Option<i32>>(connection)?;
523    /// assert_eq!(vec![Some(2), Some(1), None], desc_nulls_last);
524    /// #     Ok(())
525    /// # }
526    /// ```
527    fn nulls_last(self) -> dsl::NullsLast<Self> {
528        NullsLast::new(self)
529    }
530}
531
532impl<T> PgSortExpressionMethods for Asc<T> {}
533impl<T> PgSortExpressionMethods for Desc<T> {}
534
535/// PostgreSQL specific methods present on text expressions.
536#[cfg(feature = "postgres_backend")]
537pub trait PgTextExpressionMethods: Expression + Sized {
538    /// Creates a  PostgreSQL `ILIKE` expression
539    ///
540    /// # Example
541    ///
542    /// ```rust
543    /// # include!("../../doctest_setup.rs");
544    /// #
545    /// # fn main() {
546    /// #     run_test().unwrap();
547    /// # }
548    /// #
549    /// # fn run_test() -> QueryResult<()> {
550    /// #     use schema::animals::dsl::*;
551    /// #     let connection = &mut establish_connection();
552    /// let starts_with_s = animals
553    ///     .select(species)
554    ///     .filter(name.ilike("s%").or(species.ilike("s%")))
555    ///     .get_results::<String>(connection)?;
556    /// assert_eq!(vec!["spider"], starts_with_s);
557    /// #     Ok(())
558    /// # }
559    /// ```
560    fn ilike<T>(self, other: T) -> dsl::ILike<Self, T>
561    where
562        T: AsExpression<Text>,
563    {
564        Grouped(ILike::new(self, other.as_expression()))
565    }
566
567    /// Creates a PostgreSQL `NOT ILIKE` expression
568    ///
569    /// # Example
570    ///
571    /// ```rust
572    /// # include!("../../doctest_setup.rs");
573    /// #
574    /// # fn main() {
575    /// #     run_test().unwrap();
576    /// # }
577    /// #
578    /// # fn run_test() -> QueryResult<()> {
579    /// #     use schema::animals::dsl::*;
580    /// #     let connection = &mut establish_connection();
581    /// let doesnt_start_with_s = animals
582    ///     .select(species)
583    ///     .filter(name.not_ilike("s%").and(species.not_ilike("s%")))
584    ///     .get_results::<String>(connection)?;
585    /// assert_eq!(vec!["dog"], doesnt_start_with_s);
586    /// #     Ok(())
587    /// # }
588    /// ```
589    fn not_ilike<T>(self, other: T) -> dsl::NotILike<Self, T>
590    where
591        T: AsExpression<Text>,
592    {
593        Grouped(NotILike::new(self, other.as_expression()))
594    }
595
596    /// Creates a PostgreSQL `SIMILAR TO` expression
597    ///
598    /// # Example
599    /// ```
600    /// # include!("../../doctest_setup.rs");
601    /// #
602    /// # fn main() {
603    /// #     run_test().unwrap();
604    /// # }
605    /// #
606    /// # fn run_test() -> QueryResult<()> {
607    /// #     use schema::animals::dsl::*;
608    /// #     let connection = &mut establish_connection();
609    /// let starts_with_s = animals
610    ///     .select(species)
611    ///     .filter(name.similar_to("s%").or(species.similar_to("s%")))
612    ///     .get_results::<String>(connection)?;
613    /// assert_eq!(vec!["spider"], starts_with_s);
614    /// #     Ok(())
615    /// # }
616    /// ```
617    fn similar_to<T>(self, other: T) -> dsl::SimilarTo<Self, T>
618    where
619        T: AsExpression<Text>,
620    {
621        Grouped(SimilarTo::new(self, other.as_expression()))
622    }
623
624    /// Creates a PostgreSQL `NOT SIMILAR TO` expression
625    ///
626    /// # Example
627    /// ```
628    /// # include!("../../doctest_setup.rs");
629    /// #
630    /// # fn main() {
631    /// #     run_test().unwrap();
632    /// # }
633    /// #
634    /// # fn run_test() -> QueryResult<()> {
635    /// #     use schema::animals::dsl::*;
636    /// #     let connection = &mut establish_connection();
637    /// let doesnt_start_with_s = animals
638    ///     .select(species)
639    ///     .filter(name.not_similar_to("s%").and(species.not_similar_to("s%")))
640    ///     .get_results::<String>(connection)?;
641    /// assert_eq!(vec!["dog"], doesnt_start_with_s);
642    /// #     Ok(())
643    /// # }
644    /// ```
645    fn not_similar_to<T>(self, other: T) -> dsl::NotSimilarTo<Self, T>
646    where
647        T: AsExpression<Text>,
648    {
649        Grouped(NotSimilarTo::new(self, other.as_expression()))
650    }
651}
652
653impl<T> PgTextExpressionMethods for T
654where
655    T: Expression,
656    T::SqlType: TextOrNullableText,
657{
658}
659
660impl<T, U> EscapeExpressionMethods for Grouped<ILike<T, U>> {
661    type TextExpression = ILike<T, U>;
662
663    fn escape(self, character: char) -> dsl::Escape<Self> {
664        Grouped(crate::expression::operators::Escape::new(
665            self.0,
666            character.to_string().into_sql::<VarChar>(),
667        ))
668    }
669}
670
671impl<T, U> EscapeExpressionMethods for Grouped<NotILike<T, U>> {
672    type TextExpression = NotILike<T, U>;
673
674    fn escape(self, character: char) -> dsl::Escape<Self> {
675        Grouped(crate::expression::operators::Escape::new(
676            self.0,
677            character.to_string().into_sql::<VarChar>(),
678        ))
679    }
680}
681
682impl<T, U> EscapeExpressionMethods for Grouped<SimilarTo<T, U>> {
683    type TextExpression = SimilarTo<T, U>;
684
685    fn escape(self, character: char) -> dsl::Escape<Self> {
686        Grouped(crate::expression::operators::Escape::new(
687            self.0,
688            character.to_string().into_sql::<VarChar>(),
689        ))
690    }
691}
692
693impl<T, U> EscapeExpressionMethods for Grouped<NotSimilarTo<T, U>> {
694    type TextExpression = NotSimilarTo<T, U>;
695
696    fn escape(self, character: char) -> dsl::Escape<Self> {
697        Grouped(crate::expression::operators::Escape::new(
698            self.0,
699            character.to_string().into_sql::<VarChar>(),
700        ))
701    }
702}
703
704/// PostgreSQL specific methods present on range expressions.
705#[cfg(feature = "postgres_backend")]
706pub trait PgRangeExpressionMethods: Expression + Sized {
707    /// Creates a PostgreSQL `@>` expression.
708    ///
709    /// This operator returns whether a range contains an specific element
710    ///
711    /// # Example
712    ///
713    /// ```rust
714    /// # include!("../../doctest_setup.rs");
715    /// #
716    /// # table! {
717    /// #     posts {
718    /// #         id -> Integer,
719    /// #         versions -> Range<Integer>,
720    /// #     }
721    /// # }
722    /// #
723    /// # fn main() {
724    /// #     run_test().unwrap();
725    /// # }
726    /// #
727    /// # fn run_test() -> QueryResult<()> {
728    /// #     use self::posts::dsl::*;
729    /// #     use std::collections::Bound;
730    /// #     let conn = &mut establish_connection();
731    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
732    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, versions INT4RANGE NOT NULL)").execute(conn).unwrap();
733    /// #
734    /// diesel::insert_into(posts)
735    ///     .values(versions.eq((Bound::Included(5), Bound::Unbounded)))
736    ///     .execute(conn)?;
737    ///
738    /// let cool_posts = posts.select(id)
739    ///     .filter(versions.contains(42))
740    ///     .load::<i32>(conn)?;
741    /// assert_eq!(vec![1], cool_posts);
742    ///
743    /// let amazing_posts = posts.select(id)
744    ///     .filter(versions.contains(1))
745    ///     .load::<i32>(conn)?;
746    /// assert!(amazing_posts.is_empty());
747    /// #     Ok(())
748    /// # }
749    /// ```
750    fn contains<T>(self, other: T) -> dsl::RangeContains<Self, T>
751    where
752        Self::SqlType: RangeHelper,
753        <Self::SqlType as RangeHelper>::Inner: SqlType + TypedExpressionType,
754        T: AsExpression<<Self::SqlType as RangeHelper>::Inner>,
755    {
756        Grouped(Contains::new(self, other.as_expression()))
757    }
758}
759
760impl<T> PgRangeExpressionMethods for T
761where
762    T: Expression,
763    T::SqlType: RangeOrNullableRange,
764{
765}
766
767/// PostgreSQL specific methods present between CIDR/INET expressions
768#[cfg(feature = "postgres_backend")]
769pub trait PgNetExpressionMethods: Expression + Sized {
770    /// Creates a PostgreSQL `>>` expression.
771    ///
772    /// This operator returns whether a subnet strictly contains another subnet or address.
773    ///
774    /// # Example
775    ///
776    /// ```rust
777    /// # include!("../../doctest_setup.rs");
778    /// #
779    /// # table! {
780    /// #     hosts {
781    /// #         id -> Integer,
782    /// #         address -> Inet,
783    /// #     }
784    /// # }
785    /// #
786    /// # fn main() {
787    /// #     run_test().unwrap();
788    /// # }
789    /// #
790    /// # #[cfg(feature = "ipnetwork")]
791    /// # fn run_test() -> QueryResult<()> {
792    /// #     use self::hosts::dsl::*;
793    /// #     use ipnetwork::IpNetwork;
794    /// #     use std::str::FromStr;
795    /// #     let conn = &mut establish_connection();
796    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
797    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
798    /// diesel::insert_into(hosts)
799    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
800    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
801    ///     .execute(conn)?;
802    ///
803    /// let my_hosts = hosts.select(id)
804    ///     .filter(address.contains(IpNetwork::from_str("10.0.2.5").unwrap()))
805    ///     .load::<i32>(conn)?;
806    /// assert_eq!(vec![1, 2], my_hosts);
807    ///
808    /// let my_hosts = hosts.select(id)
809    ///     .filter(address.contains(IpNetwork::from_str("10.0.2.5/24").unwrap()))
810    ///     .load::<i32>(conn)?;
811    /// assert_eq!(vec![2], my_hosts);
812    ///
813    /// let my_hosts = hosts.select(id)
814    ///     .filter(address.contains(IpNetwork::from_str("10.0.3.31").unwrap()))
815    ///     .load::<i32>(conn)?;
816    /// assert_eq!(vec![2], my_hosts);
817    /// #     Ok(())
818    /// # }
819    /// #
820    /// # #[cfg(not(feature = "ipnetwork"))]
821    /// # fn run_test() -> QueryResult<()> {
822    /// #     Ok(())
823    /// # }
824    /// ```
825    fn contains<T>(self, other: T) -> dsl::ContainsNet<Self, T>
826    where
827        T: AsExpression<Inet>,
828    {
829        Grouped(ContainsNet::new(self, other.as_expression()))
830    }
831
832    /// Creates a PostgreSQL `>>=` expression.
833    ///
834    /// This operator returns whether a subnet contains or is equal to another subnet.
835    ///
836    /// # Example
837    ///
838    /// ```rust
839    /// # include!("../../doctest_setup.rs");
840    /// #
841    /// # table! {
842    /// #     hosts {
843    /// #         id -> Integer,
844    /// #         address -> Inet,
845    /// #     }
846    /// # }
847    /// #
848    /// # fn main() {
849    /// #     run_test().unwrap();
850    /// # }
851    /// #
852    /// # #[cfg(feature = "ipnetwork")]
853    /// # fn run_test() -> QueryResult<()> {
854    /// #     use self::hosts::dsl::*;
855    /// #     use ipnetwork::IpNetwork;
856    /// #     use std::str::FromStr;
857    /// #     let conn = &mut establish_connection();
858    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
859    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
860    /// diesel::insert_into(hosts)
861    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
862    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
863    ///     .execute(conn)?;
864    ///
865    /// let my_hosts = hosts.select(id)
866    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.2.5").unwrap()))
867    ///     .load::<i32>(conn)?;
868    /// assert_eq!(vec![1, 2], my_hosts);
869    ///
870    /// let my_hosts = hosts.select(id)
871    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.2.5/24").unwrap()))
872    ///     .load::<i32>(conn)?;
873    /// assert_eq!(vec![1, 2], my_hosts);
874    ///
875    /// let my_hosts = hosts.select(id)
876    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.3.31").unwrap()))
877    ///     .load::<i32>(conn)?;
878    /// assert_eq!(vec![2], my_hosts);
879    /// #     Ok(())
880    /// # }
881    /// #
882    /// # #[cfg(not(feature = "ipnetwork"))]
883    /// # fn run_test() -> QueryResult<()> {
884    /// #     Ok(())
885    /// # }
886    /// ```
887    fn contains_or_eq<T>(self, other: T) -> dsl::ContainsNetLoose<Self, T>
888    where
889        T: AsExpression<Inet>,
890    {
891        Grouped(ContainsNetLoose::new(self, other.as_expression()))
892    }
893
894    /// Creates a PostgreSQL `<<` expression.
895    ///
896    /// This operator returns whether a subnet or address is strictly contained by another subnet.
897    ///
898    /// # Example
899    ///
900    /// ```rust
901    /// # include!("../../doctest_setup.rs");
902    /// #
903    /// # table! {
904    /// #     hosts {
905    /// #         id -> Integer,
906    /// #         address -> Inet,
907    /// #     }
908    /// # }
909    /// #
910    /// # fn main() {
911    /// #     run_test().unwrap();
912    /// # }
913    /// #
914    /// # #[cfg(feature = "ipnetwork")]
915    /// # fn run_test() -> QueryResult<()> {
916    /// #     use self::hosts::dsl::*;
917    /// #     use ipnetwork::IpNetwork;
918    /// #     use std::str::FromStr;
919    /// #     let conn = &mut establish_connection();
920    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
921    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
922    /// diesel::insert_into(hosts)
923    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
924    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
925    ///     .execute(conn)?;
926    ///
927    /// let my_hosts = hosts.select(id)
928    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.2.5/24").unwrap()))
929    ///     .load::<i32>(conn)?;
930    /// assert_eq!(my_hosts.len(), 0);
931    ///
932    /// let my_hosts = hosts.select(id)
933    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.3.31/23").unwrap()))
934    ///     .load::<i32>(conn)?;
935    /// assert_eq!(vec![1], my_hosts);
936    ///
937    /// let my_hosts = hosts.select(id)
938    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.3.31/22").unwrap()))
939    ///     .load::<i32>(conn)?;
940    /// assert_eq!(vec![1, 2], my_hosts);
941    /// #     Ok(())
942    /// # }
943    /// #
944    /// # #[cfg(not(feature = "ipnetwork"))]
945    /// # fn run_test() -> QueryResult<()> {
946    /// #     Ok(())
947    /// # }
948    /// ```
949    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
950    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedByNet<Self, T>
951    where
952        T: AsExpression<Inet>,
953    {
954        Grouped(IsContainedByNet::new(self, other.as_expression()))
955    }
956
957    /// Creates a PostgreSQL `>>=` expression.
958    ///
959    /// This operator returns whether a subnet is contained by or equal to another subnet.
960    ///
961    /// # Example
962    ///
963    /// ```rust
964    /// # include!("../../doctest_setup.rs");
965    /// #
966    /// # table! {
967    /// #     hosts {
968    /// #         id -> Integer,
969    /// #         address -> Inet,
970    /// #     }
971    /// # }
972    /// #
973    /// # fn main() {
974    /// #     run_test().unwrap();
975    /// # }
976    /// #
977    /// # #[cfg(feature = "ipnetwork")]
978    /// # fn run_test() -> QueryResult<()> {
979    /// #     use self::hosts::dsl::*;
980    /// #     use ipnetwork::IpNetwork;
981    /// #     use std::str::FromStr;
982    /// #     let conn = &mut establish_connection();
983    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
984    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
985    /// diesel::insert_into(hosts)
986    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
987    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
988    ///     .execute(conn)?;
989    ///
990    /// let my_hosts = hosts.select(id)
991    ///     .filter(address.is_contained_by_or_eq(IpNetwork::from_str("10.0.2.5/24").unwrap()))
992    ///     .load::<i32>(conn)?;
993    /// assert_eq!(vec![1], my_hosts);
994    ///
995    /// let my_hosts = hosts.select(id)
996    ///     .filter(address.is_contained_by_or_eq(IpNetwork::from_str("10.0.3.31/23").unwrap()))
997    ///     .load::<i32>(conn)?;
998    /// assert_eq!(vec![1, 2], my_hosts);
999    /// #     Ok(())
1000    /// # }
1001    /// #
1002    /// # #[cfg(not(feature = "ipnetwork"))]
1003    /// # fn run_test() -> QueryResult<()> {
1004    /// #     Ok(())
1005    /// # }
1006    /// ```
1007    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
1008    fn is_contained_by_or_eq<T>(self, other: T) -> dsl::IsContainedByNetLoose<Self, T>
1009    where
1010        T: AsExpression<Inet>,
1011    {
1012        Grouped(IsContainedByNetLoose::new(self, other.as_expression()))
1013    }
1014
1015    /// Creates a PostgreSQL `&&` expression.
1016    ///
1017    /// This operator returns whether a subnet contains or is contained by another subnet.
1018    ///
1019    /// # Example
1020    ///
1021    /// ```rust
1022    /// # include!("../../doctest_setup.rs");
1023    /// #
1024    /// # table! {
1025    /// #     hosts {
1026    /// #         id -> Integer,
1027    /// #         address -> Inet,
1028    /// #     }
1029    /// # }
1030    /// #
1031    /// # fn main() {
1032    /// #     run_test().unwrap();
1033    /// # }
1034    /// #
1035    /// # #[cfg(feature = "ipnetwork")]
1036    /// # fn run_test() -> QueryResult<()> {
1037    /// #     use self::hosts::dsl::*;
1038    /// #     use ipnetwork::IpNetwork;
1039    /// #     use std::str::FromStr;
1040    /// #     let conn = &mut establish_connection();
1041    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
1042    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
1043    /// diesel::insert_into(hosts)
1044    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
1045    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
1046    ///     .execute(conn)?;
1047    ///
1048    /// let my_hosts = hosts.select(id)
1049    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.2.5/24").unwrap()))
1050    ///     .load::<i32>(conn)?;
1051    /// assert_eq!(vec![1, 2], my_hosts);
1052    ///
1053    /// let my_hosts = hosts.select(id)
1054    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.3.31/24").unwrap()))
1055    ///     .load::<i32>(conn)?;
1056    /// assert_eq!(vec![2], my_hosts);
1057    ///
1058    /// let my_hosts = hosts.select(id)
1059    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.3.31/23").unwrap()))
1060    ///     .load::<i32>(conn)?;
1061    /// assert_eq!(vec![1, 2], my_hosts);
1062    /// #     Ok(())
1063    /// # }
1064    /// #
1065    /// # #[cfg(not(feature = "ipnetwork"))]
1066    /// # fn run_test() -> QueryResult<()> {
1067    /// #     Ok(())
1068    /// # }
1069    /// ```
1070    fn overlaps_with<T>(self, other: T) -> dsl::OverlapsWithNet<Self, T>
1071    where
1072        T: AsExpression<Inet>,
1073    {
1074        Grouped(OverlapsWith::new(self, other.as_expression()))
1075    }
1076
1077    /// Creates a PostgreSQL `&` expression.
1078    ///
1079    /// This operator computes the bitwise AND between two network addresses.
1080    ///
1081    /// # Example
1082    ///
1083    /// ```rust
1084    /// # include!("../../doctest_setup.rs");
1085    /// #
1086    /// # table! {
1087    /// #     hosts {
1088    /// #         id -> Integer,
1089    /// #         address -> Inet,
1090    /// #     }
1091    /// # }
1092    /// #
1093    /// # fn main() {
1094    /// #     run_test().unwrap();
1095    /// # }
1096    /// #
1097    /// # #[cfg(feature = "ipnetwork")]
1098    /// # fn run_test() -> QueryResult<()> {
1099    /// #     use self::hosts::dsl::*;
1100    /// #     use ipnetwork::IpNetwork;
1101    /// #     use std::str::FromStr;
1102    /// #     let conn = &mut establish_connection();
1103    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
1104    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
1105    /// diesel::insert_into(hosts)
1106    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3").unwrap())])
1107    ///     .execute(conn)?;
1108    ///
1109    /// let addr = hosts
1110    ///     .select(address.and(IpNetwork::from_str("0.0.0.255").unwrap()))
1111    ///     .first::<IpNetwork>(conn)?;
1112    /// assert_eq!(addr, IpNetwork::from_str("0.0.0.3").unwrap());
1113    /// #     Ok(())
1114    /// # }
1115    /// #
1116    /// # #[cfg(not(feature = "ipnetwork"))]
1117    /// # fn run_test() -> QueryResult<()> {
1118    /// #     Ok(())
1119    /// # }
1120    /// ```
1121    fn and<T>(self, other: T) -> dsl::AndNet<Self, T>
1122    where
1123        T: AsExpression<Inet>,
1124    {
1125        Grouped(AndNet::new(self, other.as_expression()))
1126    }
1127
1128    /// Creates a PostgreSQL `|` expression.
1129    ///
1130    /// This operator computes the bitwise OR between two network addresses.
1131    ///
1132    /// # Example
1133    ///
1134    /// ```rust
1135    /// # include!("../../doctest_setup.rs");
1136    /// #
1137    /// # table! {
1138    /// #     hosts {
1139    /// #         id -> Integer,
1140    /// #         address -> Inet,
1141    /// #     }
1142    /// # }
1143    /// #
1144    /// # fn main() {
1145    /// #     run_test().unwrap();
1146    /// # }
1147    /// #
1148    /// # #[cfg(feature = "ipnetwork")]
1149    /// # fn run_test() -> QueryResult<()> {
1150    /// #     use self::hosts::dsl::*;
1151    /// #     use ipnetwork::IpNetwork;
1152    /// #     use std::str::FromStr;
1153    /// #     let conn = &mut establish_connection();
1154    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
1155    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
1156    /// diesel::insert_into(hosts)
1157    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3").unwrap())])
1158    ///     .execute(conn)?;
1159    ///
1160    /// let addr = hosts
1161    ///     .select(address.or(IpNetwork::from_str("0.0.0.255").unwrap()))
1162    ///     .first::<IpNetwork>(conn)?;
1163    /// assert_eq!(addr, IpNetwork::from_str("10.0.2.255").unwrap());
1164    /// #     Ok(())
1165    /// # }
1166    /// #
1167    /// # #[cfg(not(feature = "ipnetwork"))]
1168    /// # fn run_test() -> QueryResult<()> {
1169    /// #     Ok(())
1170    /// # }
1171    /// ```
1172    fn or<T>(self, other: T) -> dsl::OrNet<Self, T>
1173    where
1174        T: AsExpression<Inet>,
1175    {
1176        Grouped(OrNet::new(self, other.as_expression()))
1177    }
1178
1179    /// Creates a PostgreSQL `-` expression.
1180    ///
1181    /// This operator subtracts an address from an address to compute the distance between the two
1182    ///
1183    /// # Example
1184    ///
1185    /// ```rust
1186    /// # include!("../../doctest_setup.rs");
1187    /// #
1188    /// # table! {
1189    /// #     hosts {
1190    /// #         id -> Integer,
1191    /// #         address -> Inet,
1192    /// #     }
1193    /// # }
1194    /// #
1195    /// # fn main() {
1196    /// #     run_test().unwrap();
1197    /// # }
1198    /// #
1199    /// # #[cfg(feature = "ipnetwork")]
1200    /// # fn run_test() -> QueryResult<()> {
1201    /// #     use self::hosts::dsl::*;
1202    /// #     use ipnetwork::IpNetwork;
1203    /// #     use std::str::FromStr;
1204    /// #     let conn = &mut establish_connection();
1205    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
1206    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
1207    /// diesel::insert_into(hosts)
1208    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.53").unwrap())])
1209    ///     .execute(conn)?;
1210    ///
1211    /// let offset = hosts
1212    ///     .select(address.diff(IpNetwork::from_str("10.0.2.42").unwrap()))
1213    ///     .first::<i64>(conn)?;
1214    /// assert_eq!(offset, 11);
1215    /// #     Ok(())
1216    /// # }
1217    /// #
1218    /// # #[cfg(not(feature = "ipnetwork"))]
1219    /// # fn run_test() -> QueryResult<()> {
1220    /// #     Ok(())
1221    /// # }
1222    /// ```
1223    fn diff<T>(self, other: T) -> dsl::DifferenceNet<Self, T>
1224    where
1225        T: AsExpression<Inet>,
1226    {
1227        Grouped(DifferenceNet::new(self, other.as_expression()))
1228    }
1229}
1230
1231impl<T> PgNetExpressionMethods for T
1232where
1233    T: Expression,
1234    T::SqlType: InetOrCidr,
1235{
1236}
1237
1238/// PostgreSQL specific methods present on JSONB expressions.
1239#[cfg(feature = "postgres_backend")]
1240pub trait PgJsonbExpressionMethods: Expression + Sized {
1241    /// Creates a PostgreSQL `||` expression.
1242    ///
1243    /// This operator concatenates two JSONB values and returns JSONB value
1244    ///
1245    /// # Example
1246    ///
1247    /// ```rust
1248    /// # include!("../../doctest_setup.rs");
1249    /// #
1250    /// # table! {
1251    /// #    contacts {
1252    /// #        id -> Integer,
1253    /// #        name -> VarChar,
1254    /// #        address -> Jsonb,
1255    /// #    }
1256    /// # }
1257    /// #
1258    /// # fn main() {
1259    /// #     run_test().unwrap();
1260    /// # }
1261    ///
1262    /// # #[cfg(feature = "serde_json")]
1263    /// # fn run_test() -> QueryResult<()> {
1264    /// #     use self::contacts::dsl::*;
1265    /// #     let conn = &mut establish_connection();
1266    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1267    /// #     diesel::sql_query("CREATE TABLE contacts (
1268    /// #         id SERIAL PRIMARY KEY,
1269    /// #         name VARCHAR NOT NULL,
1270    /// #         address JSONB NOT NULL
1271    /// #     )").execute(conn).unwrap();
1272    /// #
1273    /// let santas_address: serde_json::Value = serde_json::json!({
1274    ///     "street": "Article Circle Expressway 1",
1275    ///     "city": "North Pole",
1276    ///     "postcode": "99705",
1277    ///     "state": "Alaska"
1278    /// });
1279    /// diesel::insert_into(contacts)
1280    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1281    ///     .execute(conn)?;
1282    ///
1283    /// let to_concatenate: serde_json::Value = serde_json::json!({
1284    ///     "continent": "NA",
1285    ///     "planet": "Earth"
1286    /// });
1287    ///
1288    /// let final_address: serde_json::Value = serde_json::json!({
1289    ///     "street": "Article Circle Expressway 1",
1290    ///     "city": "North Pole",
1291    ///     "postcode": "99705",
1292    ///     "state": "Alaska",
1293    ///     "continent": "NA",
1294    ///     "planet": "Earth"
1295    /// });
1296    ///
1297    /// let final_address_db = contacts.select(address.concat(&to_concatenate)).get_result::<serde_json::Value>(conn)?;
1298    /// assert_eq!(final_address, final_address_db);
1299    /// #     Ok(())
1300    /// # }
1301    /// # #[cfg(not(feature = "serde_json"))]
1302    /// # fn run_test() -> QueryResult<()> {
1303    /// #     Ok(())
1304    /// # }
1305    /// ```
1306    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
1307    where
1308        Self::SqlType: SqlType,
1309        T: AsExpression<Self::SqlType>,
1310    {
1311        Grouped(Concat::new(self, other.as_expression()))
1312    }
1313
1314    /// Creates a PostgreSQL `?` expression.
1315    ///
1316    /// This operator checks if the right hand side string exists as a top-level key within the JSONB
1317    ///
1318    /// # Example
1319    ///
1320    /// ```rust
1321    /// # include!("../../doctest_setup.rs");
1322    /// #
1323    /// # table! {
1324    /// #    contacts {
1325    /// #        id -> Integer,
1326    /// #        name -> VarChar,
1327    /// #        address -> Jsonb,
1328    /// #    }
1329    /// # }
1330    /// #
1331    /// # fn main() {
1332    /// #     run_test().unwrap();
1333    /// # }
1334    ///
1335    /// # #[cfg(feature = "serde_json")]
1336    /// # fn run_test() -> QueryResult<()> {
1337    /// #     use self::contacts::dsl::*;
1338    /// #     let conn = &mut establish_connection();
1339    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1340    /// #     diesel::sql_query("CREATE TABLE contacts (
1341    /// #         id SERIAL PRIMARY KEY,
1342    /// #         name VARCHAR NOT NULL,
1343    /// #         address JSONB NOT NULL
1344    /// #     )").execute(conn).unwrap();
1345    /// #
1346    /// let santas_address: serde_json::Value = serde_json::json!({
1347    ///     "street": "Article Circle Expressway 1",
1348    ///     "city": "North Pole",
1349    ///     "postcode": "99705",
1350    ///     "state": "Alaska"
1351    /// });
1352    /// diesel::insert_into(contacts)
1353    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1354    ///     .execute(conn)?;
1355    ///
1356    /// let key_exists = contacts.select(address.has_key("street")).get_result::<bool>(conn)?;
1357    /// assert!(key_exists);
1358    ///
1359    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_key("postcode")).get_result::<i32>(conn)?;
1360    /// assert_eq!(1, santas_with_address_postcode);
1361    /// #     Ok(())
1362    /// # }
1363    /// # #[cfg(not(feature = "serde_json"))]
1364    /// # fn run_test() -> QueryResult<()> {
1365    /// #     Ok(())
1366    /// # }
1367    /// ```
1368    fn has_key<T>(self, other: T) -> dsl::HasKeyJsonb<Self, T>
1369    where
1370        T: AsExpression<VarChar>,
1371    {
1372        Grouped(HasKeyJsonb::new(self, other.as_expression()))
1373    }
1374
1375    /// Creates a PostgreSQL `?|` expression.
1376    ///
1377    /// This operator checks if any of the strings in the right hand side array exists as top level key in the given JSONB
1378    ///
1379    /// # Example
1380    ///
1381    /// ```rust
1382    /// # include!("../../doctest_setup.rs");
1383    /// #
1384    /// # table! {
1385    /// #    contacts {
1386    /// #        id -> Integer,
1387    /// #        name -> VarChar,
1388    /// #        address -> Jsonb,
1389    /// #    }
1390    /// # }
1391    /// #
1392    /// # fn main() {
1393    /// #     run_test().unwrap();
1394    /// # }
1395    ///
1396    /// # #[cfg(feature = "serde_json")]
1397    /// # fn run_test() -> QueryResult<()> {
1398    /// #     use self::contacts::dsl::*;
1399    /// #     let conn = &mut establish_connection();
1400    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1401    /// #     diesel::sql_query("CREATE TABLE contacts (
1402    /// #         id SERIAL PRIMARY KEY,
1403    /// #         name VARCHAR NOT NULL,
1404    /// #         address JSONB NOT NULL
1405    /// #     )").execute(conn).unwrap();
1406    /// #
1407    /// let santas_address: serde_json::Value = serde_json::json!({
1408    ///     "street": "Article Circle Expressway 1",
1409    ///     "city": "North Pole",
1410    ///     "postcode": "99705",
1411    ///     "state": "Alaska"
1412    /// });
1413    /// diesel::insert_into(contacts)
1414    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1415    ///     .execute(conn)?;
1416    ///
1417    /// let any_key_exists = contacts.select(address.has_any_key(vec!["street", "city", "rudolf"])).get_result::<bool>(conn)?;
1418    /// assert!(any_key_exists);
1419    ///
1420    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_any_key(vec!["street", "city", "rudolf"])).get_result::<i32>(conn)?;
1421    /// assert_eq!(1, santas_with_address_postcode);
1422    /// #     Ok(())
1423    /// # }
1424    /// # #[cfg(not(feature = "serde_json"))]
1425    /// # fn run_test() -> QueryResult<()> {
1426    /// #     Ok(())
1427    /// # }
1428    /// ``````
1429    fn has_any_key<T>(self, other: T) -> dsl::HasAnyKeyJsonb<Self, T>
1430    where
1431        T: AsExpression<Array<VarChar>>,
1432    {
1433        Grouped(HasAnyKeyJsonb::new(self, other.as_expression()))
1434    }
1435
1436    /// Creates a PostgreSQL `?&` expression.
1437    ///
1438    /// This operator checks if all the strings in the right hand side array exist as top level keys in the given JSONB
1439    ///
1440    /// # Example
1441    ///
1442    /// ```rust
1443    /// # include!("../../doctest_setup.rs");
1444    /// #
1445    /// # table! {
1446    /// #    contacts {
1447    /// #        id -> Integer,
1448    /// #        name -> VarChar,
1449    /// #        address -> Jsonb,
1450    /// #    }
1451    /// # }
1452    /// #
1453    /// # fn main() {
1454    /// #     run_test().unwrap();
1455    /// # }
1456    ///
1457    /// # #[cfg(feature = "serde_json")]
1458    /// # fn run_test() -> QueryResult<()> {
1459    /// #     use self::contacts::dsl::*;
1460    /// #     let conn = &mut establish_connection();
1461    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1462    /// #     diesel::sql_query("CREATE TABLE contacts (
1463    /// #         id SERIAL PRIMARY KEY,
1464    /// #         name VARCHAR NOT NULL,
1465    /// #         address JSONB NOT NULL
1466    /// #     )").execute(conn).unwrap();
1467    /// #
1468    /// let santas_address: serde_json::Value = serde_json::json!({
1469    ///     "street": "Article Circle Expressway 1",
1470    ///     "city": "North Pole",
1471    ///     "postcode": "99705",
1472    ///     "state": "Alaska"
1473    /// });
1474    /// diesel::insert_into(contacts)
1475    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1476    ///     .execute(conn)?;
1477    ///
1478    /// let all_keys_exist = contacts.select(address.has_all_keys(vec!["street", "city", "postcode"])).get_result::<bool>(conn)?;
1479    /// assert!(all_keys_exist);
1480    ///
1481    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_all_keys(vec!["street", "city", "postcode"])).get_result::<i32>(conn)?;
1482    /// assert_eq!(1, santas_with_address_postcode);
1483    /// #     Ok(())
1484    /// # }
1485    /// # #[cfg(not(feature = "serde_json"))]
1486    /// # fn run_test() -> QueryResult<()> {
1487    /// #     Ok(())
1488    /// # }
1489    /// ``````
1490    fn has_all_keys<T>(self, other: T) -> dsl::HasAllKeysJsonb<Self, T>
1491    where
1492        T: AsExpression<Array<VarChar>>,
1493    {
1494        Grouped(HasAllKeysJsonb::new(self, other.as_expression()))
1495    }
1496
1497    /// Creates a PostgreSQL `@>` expression.
1498    ///
1499    /// This operator checks whether left hand side JSONB value contains right hand side JSONB value
1500    ///
1501    /// # Example
1502    ///
1503    /// ```rust
1504    /// # include!("../../doctest_setup.rs");
1505    /// #
1506    /// # table! {
1507    /// #    contacts {
1508    /// #        id -> Integer,
1509    /// #        name -> VarChar,
1510    /// #        address -> Jsonb,
1511    /// #    }
1512    /// # }
1513    /// #
1514    /// # fn main() {
1515    /// #     run_test().unwrap();
1516    /// # }
1517    /// #
1518    /// # #[cfg(feature = "serde_json")]
1519    /// # fn run_test() -> QueryResult<()> {
1520    /// #     use self::contacts::dsl::*;
1521    /// #     let conn = &mut establish_connection();
1522    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1523    /// #     diesel::sql_query("CREATE TABLE contacts (
1524    /// #         id SERIAL PRIMARY KEY,
1525    /// #         name VARCHAR NOT NULL,
1526    /// #         address JSONB NOT NULL
1527    /// #     )").execute(conn).unwrap();
1528    /// #
1529    /// let easter_bunny_address: serde_json::Value = serde_json::json!({
1530    ///     "street": "123 Carrot Road",
1531    ///     "province": "Easter Island",
1532    ///     "region": "Valparaíso",
1533    ///     "country": "Chile",
1534    ///     "postcode": "88888",
1535    /// });
1536    /// diesel::insert_into(contacts)
1537    ///     .values((name.eq("Bunny"), address.eq(&easter_bunny_address)))
1538    ///     .execute(conn)?;
1539    ///
1540    /// let country_chile: serde_json::Value = serde_json::json!({"country": "Chile"});
1541    /// let contains_country_chile = contacts.select(address.contains(&country_chile)).get_result::<bool>(conn)?;
1542    /// assert!(contains_country_chile);
1543    /// #     Ok(())
1544    /// # }
1545    /// # #[cfg(not(feature = "serde_json"))]
1546    /// # fn run_test() -> QueryResult<()> {
1547    /// #     Ok(())
1548    /// # }
1549    /// ```
1550    fn contains<T>(self, other: T) -> dsl::Contains<Self, T>
1551    where
1552        Self::SqlType: SqlType,
1553        T: AsExpression<Self::SqlType>,
1554    {
1555        Grouped(Contains::new(self, other.as_expression()))
1556    }
1557
1558    /// Creates a PostgreSQL `<@` expression.
1559    ///
1560    /// This operator checks whether left hand side JSONB value is contained by right hand side JSON value.
1561    /// `foo.contains(bar)` is the same as `bar.is_contained_by(foo)`.
1562    ///
1563    /// # Example
1564    ///
1565    /// ```rust
1566    /// # include!("../../doctest_setup.rs");
1567    /// #
1568    /// # table! {
1569    /// #    contacts {
1570    /// #        id -> Integer,
1571    /// #        name -> VarChar,
1572    /// #        address -> Jsonb,
1573    /// #    }
1574    /// # }
1575    /// #
1576    /// # fn main() {
1577    /// #     run_test().unwrap();
1578    /// # }
1579    /// #
1580    /// # #[cfg(feature = "serde_json")]
1581    /// # fn run_test() -> QueryResult<()> {
1582    /// #     use self::contacts::dsl::*;
1583    /// #     let conn = &mut establish_connection();
1584    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1585    /// #     diesel::sql_query("CREATE TABLE contacts (
1586    /// #         id SERIAL PRIMARY KEY,
1587    /// #         name VARCHAR NOT NULL,
1588    /// #         address JSONB NOT NULL
1589    /// #     )").execute(conn).unwrap();
1590    /// #
1591    /// let partial_easter_bunny_address: serde_json::Value = serde_json::json!({
1592    ///     "street": "123 Carrot Road",
1593    ///     "country": "Chile",
1594    /// });
1595    /// diesel::insert_into(contacts)
1596    ///     .values((name.eq("Bunny"), address.eq(&partial_easter_bunny_address)))
1597    ///     .execute(conn)?;
1598    ///
1599    /// let full_easter_bunny_address: serde_json::Value = serde_json::json!({
1600    ///     "street": "123 Carrot Road",
1601    ///     "province": "Easter Island",
1602    ///     "region": "Valparaíso",
1603    ///     "country": "Chile",
1604    ///     "postcode": "88888",
1605    /// });
1606    /// let address_is_contained_by = contacts.select(address.is_contained_by(&full_easter_bunny_address)).get_result::<bool>(conn)?;
1607    /// assert!(address_is_contained_by);
1608    /// #     Ok(())
1609    /// # }
1610    /// # #[cfg(not(feature = "serde_json"))]
1611    /// # fn run_test() -> QueryResult<()> {
1612    /// #     Ok(())
1613    /// # }
1614    /// ```
1615    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
1616    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
1617    where
1618        Self::SqlType: SqlType,
1619        T: AsExpression<Self::SqlType>,
1620    {
1621        Grouped(IsContainedBy::new(self, other.as_expression()))
1622    }
1623
1624    /// Creates a PostgreSQL `-` expression.
1625    ///
1626    /// This operator removes the value associated with the given key, that is provided on the
1627    /// Right Hand Side of the operator.
1628    ///
1629    /// # Example
1630    ///
1631    /// ```rust
1632    /// # include!("../../doctest_setup.rs");
1633    /// #
1634    /// # table! {
1635    /// #    contacts {
1636    /// #        id -> Integer,
1637    /// #        name -> VarChar,
1638    /// #        address -> Jsonb,
1639    /// #    }
1640    /// # }
1641    /// #
1642    /// # fn main() {
1643    /// #     run_test().unwrap();
1644    /// # }
1645    ///
1646    /// # #[cfg(feature = "serde_json")]
1647    /// # fn run_test() -> QueryResult<()> {
1648    /// #     use self::contacts::dsl::*;
1649    /// #     let conn = &mut establish_connection();
1650    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1651    /// #     diesel::sql_query("CREATE TABLE contacts (
1652    /// #         id SERIAL PRIMARY KEY,
1653    /// #         name VARCHAR NOT NULL,
1654    /// #         address JSONB NOT NULL
1655    /// #     )").execute(conn)
1656    /// #        .unwrap();
1657    /// #
1658    /// let santas_address: serde_json::Value = serde_json::json!({
1659    ///     "street": "Article Circle Expressway 1",
1660    ///     "city": "North Pole",
1661    ///     "postcode": "99705",
1662    ///     "state": "Alaska"
1663    /// });
1664    /// diesel::insert_into(contacts)
1665    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1666    ///     .execute(conn)?;
1667    ///
1668    /// let santas_modified_address = contacts.select(address.remove("postcode")).get_result::<serde_json::Value>(conn)?;
1669    /// assert_eq!(santas_modified_address, serde_json::json!({
1670    ///     "street": "Article Circle Expressway 1",
1671    ///     "city": "North Pole",
1672    ///     "state": "Alaska"
1673    /// }));
1674    /// diesel::insert_into(contacts)
1675    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1676    ///     .execute(conn)?;
1677    ///
1678    /// let santas_modified_address = contacts.select(address.remove(vec!["postcode", "state"])).get_result::<serde_json::Value>(conn)?;
1679    /// assert_eq!(santas_modified_address, serde_json::json!({
1680    ///     "street": "Article Circle Expressway 1",
1681    ///     "city": "North Pole",
1682    /// }));
1683    ///
1684    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
1685    ///     {
1686    ///         "street": "Somewhere In La 251",
1687    ///         "city": "Los Angeles",
1688    ///         "postcode": "12231223",
1689    ///         "state": "California"
1690    ///     },
1691    ///     {
1692    ///         "street": "Somewhere In Ny 251",
1693    ///         "city": "New York",
1694    ///         "postcode": "3213212",
1695    ///         "state": "New York"
1696    ///     }
1697    /// ]);
1698    ///
1699    /// diesel::insert_into(contacts)
1700    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
1701    ///     .execute(conn)?;
1702    ///
1703    /// let roberts_address_in_db = contacts
1704    ///                             .filter(name.eq("Robert Downey Jr."))
1705    ///                             .select(address.remove(1))
1706    ///                             .get_result::<serde_json::Value>(conn)?;
1707    ///
1708    /// let roberts_first_address = serde_json::json!([{
1709    ///         "street": "Somewhere In La 251",
1710    ///         "city": "Los Angeles",
1711    ///         "postcode": "12231223",
1712    ///         "state": "California"
1713    /// }]);
1714    /// assert_eq!(roberts_first_address, roberts_address_in_db);
1715    /// #     Ok(())
1716    /// # }
1717    /// # #[cfg(not(feature = "serde_json"))]
1718    /// # fn run_test() -> QueryResult<()> {
1719    /// #     Ok(())
1720    /// # }
1721    ///
1722    fn remove<T>(
1723        self,
1724        other: T,
1725    ) -> dsl::RemoveFromJsonb<Self, T::Expression, <T::Expression as Expression>::SqlType>
1726    where
1727        T: JsonRemoveIndex,
1728        <T::Expression as Expression>::SqlType: SqlType,
1729    {
1730        Grouped(RemoveFromJsonb::new(
1731            self,
1732            other.into_json_index_expression(),
1733        ))
1734    }
1735
1736    /// Creates a PostgreSQL `#-` expression.
1737    ///
1738    /// This operator removes the value associated with the given json path, that is provided on the
1739    /// Right Hand Side of the operator.
1740    ///
1741    /// # Example
1742    ///
1743    /// ```rust
1744    /// # include!("../../doctest_setup.rs");
1745    /// #
1746    /// # table! {
1747    /// #    contacts {
1748    /// #        id -> Integer,
1749    /// #        name -> VarChar,
1750    /// #        address -> Jsonb,
1751    /// #    }
1752    /// # }
1753    /// #
1754    /// # fn main() {
1755    /// #     run_test().unwrap();
1756    /// # }
1757    ///
1758    /// # #[cfg(feature = "serde_json")]
1759    /// # fn run_test() -> QueryResult<()> {
1760    /// #     use self::contacts::dsl::*;
1761    /// #     let conn = &mut establish_connection();
1762    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1763    /// #     diesel::sql_query("CREATE TABLE contacts (
1764    /// #         id SERIAL PRIMARY KEY,
1765    /// #         name VARCHAR NOT NULL,
1766    /// #         address JSONB NOT NULL
1767    /// #     )").execute(conn)
1768    /// #        .unwrap();
1769    /// #
1770    /// let santas_address: serde_json::Value = serde_json::json!({
1771    ///     "street": "Article Circle Expressway 1",
1772    ///     "city": "North Pole",
1773    ///     "postcode": "99705",
1774    ///     "state": "Alaska"
1775    /// });
1776    /// diesel::insert_into(contacts)
1777    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1778    ///     .execute(conn)?;
1779    ///
1780    /// let santas_modified_address = contacts.select(address.remove("postcode")).get_result::<serde_json::Value>(conn)?;
1781    /// assert_eq!(santas_modified_address, serde_json::json!({
1782    ///     "street": "Article Circle Expressway 1",
1783    ///     "city": "North Pole",
1784    ///     "state": "Alaska"
1785    /// }));
1786    /// diesel::insert_into(contacts)
1787    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1788    ///     .execute(conn)?;
1789    ///
1790    /// let santas_modified_address = contacts.select(address.remove_by_path(vec!["postcode"])).get_result::<serde_json::Value>(conn)?;
1791    /// assert_eq!(santas_modified_address, serde_json::json!({
1792    ///     "street": "Article Circle Expressway 1",
1793    ///     "city": "North Pole",
1794    ///     "state": "Alaska"
1795    /// }));
1796    ///
1797    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
1798    ///     {
1799    ///         "street": "Somewhere In La 251",
1800    ///         "city": "Los Angeles",
1801    ///         "postcode": "12231223",
1802    ///         "state": "California"
1803    ///     },
1804    ///     {
1805    ///         "street": "Somewhere In Ny 251",
1806    ///         "city": "New York",
1807    ///         "postcode": "3213212",
1808    ///         "state": "New York"
1809    ///     }
1810    /// ]);
1811    ///
1812    /// diesel::insert_into(contacts)
1813    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
1814    ///     .execute(conn)?;
1815    ///
1816    /// let roberts_address_in_db = contacts
1817    ///                             .filter(name.eq("Robert Downey Jr."))
1818    ///                             .select(address.remove_by_path(vec!["1", "postcode"]))
1819    ///                             .get_result::<serde_json::Value>(conn)?;
1820    ///
1821    /// let roberts_address = serde_json::json!([
1822    ///     {
1823    ///         "street": "Somewhere In La 251",
1824    ///         "city": "Los Angeles",
1825    ///         "postcode": "12231223",
1826    ///         "state": "California"
1827    ///     },
1828    ///     {
1829    ///         "street": "Somewhere In Ny 251",
1830    ///         "city": "New York",
1831    ///         "state": "New York"
1832    ///     }
1833    /// ]);
1834    /// assert_eq!(roberts_address, roberts_address_in_db);
1835    /// #     Ok(())
1836    /// # }
1837    /// # #[cfg(not(feature = "serde_json"))]
1838    /// # fn run_test() -> QueryResult<()> {
1839    /// #     Ok(())
1840    /// # }
1841    ///
1842    fn remove_by_path<T>(self, other: T) -> dsl::RemoveByPathFromJsonb<Self, T::Expression>
1843    where
1844        T: AsExpression<Array<Text>>,
1845    {
1846        Grouped(RemoveByPathFromJsonb::new(self, other.as_expression()))
1847    }
1848}
1849
1850impl<T> PgJsonbExpressionMethods for T
1851where
1852    T: Expression,
1853    T::SqlType: JsonbOrNullableJsonb,
1854{
1855}
1856
1857/// PostgreSQL specific methods present on JSON and JSONB expressions.
1858#[cfg(feature = "postgres_backend")]
1859pub trait PgAnyJsonExpressionMethods: Expression + Sized {
1860    /// Creates a PostgreSQL `->` expression.
1861    ///
1862    /// This operator extracts the value associated with the given key, that is provided on the
1863    /// Right Hand Side of the operator.
1864    ///
1865    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
1866    /// Extracts JSON object field with the given key.
1867    /// # Example
1868    ///
1869    /// ```rust
1870    /// # include!("../../doctest_setup.rs");
1871    /// #
1872    /// # table! {
1873    /// #    contacts {
1874    /// #        id -> Integer,
1875    /// #        name -> VarChar,
1876    /// #        address -> Jsonb,
1877    /// #    }
1878    /// # }
1879    /// #
1880    /// # fn main() {
1881    /// #     run_test().unwrap();
1882    /// # }
1883    ///
1884    /// # #[cfg(feature = "serde_json")]
1885    /// # fn run_test() -> QueryResult<()> {
1886    /// #     use self::contacts::dsl::*;
1887    /// #     let conn = &mut establish_connection();
1888    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1889    /// #     diesel::sql_query("CREATE TABLE contacts (
1890    /// #         id SERIAL PRIMARY KEY,
1891    /// #         name VARCHAR NOT NULL,
1892    /// #         address JSONB NOT NULL
1893    /// #     )").execute(conn)
1894    /// #        .unwrap();
1895    /// #
1896    /// let santas_address: serde_json::Value = serde_json::json!({
1897    ///     "street": "Article Circle Expressway 1",
1898    ///     "city": "North Pole",
1899    ///     "postcode": "99705",
1900    ///     "state": "Alaska"
1901    /// });
1902    /// diesel::insert_into(contacts)
1903    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
1904    ///     .execute(conn)?;
1905    ///
1906    /// let santas_postcode = contacts.select(address.retrieve_as_object("postcode")).get_result::<serde_json::Value>(conn)?;
1907    /// assert_eq!(santas_postcode, serde_json::json!("99705"));
1908    ///
1909    ///
1910    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
1911    ///     {
1912    ///         "street": "Somewhere In La 251",
1913    ///         "city": "Los Angeles",
1914    ///         "postcode": "12231223",
1915    ///         "state": "California"
1916    ///     },
1917    ///     {
1918    ///         "street": "Somewhere In Ny 251",
1919    ///         "city": "New York",
1920    ///         "postcode": "3213212",
1921    ///         "state": "New York"
1922    ///     }
1923    /// ]);
1924    ///
1925    /// diesel::insert_into(contacts)
1926    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
1927    ///     .execute(conn)?;
1928    ///
1929    /// let roberts_second_address_in_db = contacts
1930    ///                             .filter(name.eq("Robert Downey Jr."))
1931    ///                             .select(address.retrieve_as_object(1))
1932    ///                             .get_result::<serde_json::Value>(conn)?;
1933    ///
1934    /// let roberts_second_address = serde_json::json!({
1935    ///         "street": "Somewhere In Ny 251",
1936    ///         "city": "New York",
1937    ///         "postcode": "3213212",
1938    ///         "state": "New York"
1939    /// });
1940    /// assert_eq!(roberts_second_address, roberts_second_address_in_db);
1941    /// #     Ok(())
1942    /// # }
1943    /// # #[cfg(not(feature = "serde_json"))]
1944    /// # fn run_test() -> QueryResult<()> {
1945    /// #     Ok(())
1946    /// # }
1947    /// ```
1948    fn retrieve_as_object<T>(
1949        self,
1950        other: T,
1951    ) -> dsl::RetrieveAsObjectJson<Self, T::Expression, <T::Expression as Expression>::SqlType>
1952    where
1953        T: JsonIndex,
1954        <T::Expression as Expression>::SqlType: SqlType,
1955    {
1956        Grouped(RetrieveAsObjectJson::new(
1957            self,
1958            other.into_json_index_expression(),
1959        ))
1960    }
1961
1962    /// Creates a PostgreSQL `->>` expression.
1963    ///
1964    /// This operator extracts the value associated with the given key, that is provided on the
1965    /// Right Hand Side of the operator.
1966    ///
1967    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
1968    /// Extracts JSON object field as Text with the given key.
1969    /// # Example
1970    ///
1971    /// ```rust
1972    /// # include!("../../doctest_setup.rs");
1973    /// #
1974    /// # table! {
1975    /// #    contacts {
1976    /// #        id -> Integer,
1977    /// #        name -> VarChar,
1978    /// #        address -> Jsonb,
1979    /// #    }
1980    /// # }
1981    /// #
1982    /// # fn main() {
1983    /// #     run_test().unwrap();
1984    /// # }
1985    ///
1986    /// # #[cfg(feature = "serde_json")]
1987    /// # fn run_test() -> QueryResult<()> {
1988    /// #     use self::contacts::dsl::*;
1989    /// #     let conn = &mut establish_connection();
1990    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
1991    /// #     diesel::sql_query("CREATE TABLE contacts (
1992    /// #         id SERIAL PRIMARY KEY,
1993    /// #         name VARCHAR NOT NULL,
1994    /// #         address JSONB NOT NULL
1995    /// #     )").execute(conn)
1996    /// #        .unwrap();
1997    /// #
1998    /// let santas_address: serde_json::Value = serde_json::json!({
1999    ///     "street": "Article Circle Expressway 1",
2000    ///     "city": "North Pole",
2001    ///     "postcode": "99705",
2002    ///     "state": "Alaska"
2003    /// });
2004    /// diesel::insert_into(contacts)
2005    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2006    ///     .execute(conn)?;
2007    ///
2008    /// let santas_postcode = contacts.select(address.retrieve_as_text("postcode")).get_result::<String>(conn)?;
2009    /// assert_eq!(santas_postcode, "99705");
2010    ///
2011    ///
2012    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
2013    ///     {
2014    ///         "street": "Somewhere In La 251",
2015    ///         "city": "Los Angeles",
2016    ///         "postcode": "12231223",
2017    ///         "state": "California"
2018    ///     },
2019    ///     {
2020    ///         "street": "Somewhere In Ny 251",
2021    ///         "city": "New York",
2022    ///         "postcode": "3213212",
2023    ///         "state": "New York"
2024    ///     }
2025    /// ]);
2026    ///
2027    /// diesel::insert_into(contacts)
2028    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
2029    ///     .execute(conn)?;
2030    ///
2031    /// let roberts_second_address_in_db = contacts
2032    ///                             .filter(name.eq("Robert Downey Jr."))
2033    ///                             .select(address.retrieve_as_text(1))
2034    ///                             .get_result::<String>(conn)?;
2035    ///
2036    /// let roberts_second_address = String::from(
2037    ///     "{\"city\": \"New York\", \
2038    ///     \"state\": \"New York\", \
2039    ///     \"street\": \"Somewhere In Ny 251\", \
2040    ///     \"postcode\": \"3213212\"}"
2041    ///     );
2042    /// assert_eq!(roberts_second_address, roberts_second_address_in_db);
2043    /// #     Ok(())
2044    /// # }
2045    /// # #[cfg(not(feature = "serde_json"))]
2046    /// # fn run_test() -> QueryResult<()> {
2047    /// #     Ok(())
2048    /// # }
2049    /// ```
2050    fn retrieve_as_text<T>(
2051        self,
2052        other: T,
2053    ) -> dsl::RetrieveAsTextJson<Self, T::Expression, <T::Expression as Expression>::SqlType>
2054    where
2055        T: JsonIndex,
2056        <T::Expression as Expression>::SqlType: SqlType,
2057    {
2058        Grouped(RetrieveAsTextJson::new(
2059            self,
2060            other.into_json_index_expression(),
2061        ))
2062    }
2063
2064    /// Creates a PostgreSQL `#>` expression.
2065    ///
2066    /// This operator extracts the value associated with the given key, that is provided on the
2067    /// Right Hand Side of the operator.
2068    ///
2069    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
2070    /// Extracts JSON object field with the given key.
2071    /// # Example
2072    ///
2073    /// ```rust
2074    /// # include!("../../doctest_setup.rs");
2075    /// #
2076    /// # table! {
2077    /// #    contacts {
2078    /// #        id -> Integer,
2079    /// #        name -> VarChar,
2080    /// #        address -> Jsonb,
2081    /// #    }
2082    /// # }
2083    /// #
2084    /// # fn main() {
2085    /// #     run_test().unwrap();
2086    /// # }
2087    ///
2088    /// # #[cfg(feature = "serde_json")]
2089    /// # fn run_test() -> QueryResult<()> {
2090    /// #     use self::contacts::dsl::*;
2091    /// #     let conn = &mut establish_connection();
2092    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2093    /// #     diesel::sql_query("CREATE TABLE contacts (
2094    /// #         id SERIAL PRIMARY KEY,
2095    /// #         name VARCHAR NOT NULL,
2096    /// #         address JSONB NOT NULL
2097    /// #     )").execute(conn)
2098    /// #        .unwrap();
2099    /// #
2100    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
2101    ///     {
2102    ///         "street": "Somewhere In La 251",
2103    ///         "city": "Los Angeles",
2104    ///         "postcode": "12231223",
2105    ///         "state": "California"
2106    ///     },
2107    ///     {
2108    ///         "street": "Somewhere In Ny 251",
2109    ///         "city": "New York",
2110    ///         "postcode": "3213212",
2111    ///         "state": "New York"
2112    ///     }
2113    /// ]);
2114    ///
2115    /// diesel::insert_into(contacts)
2116    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
2117    ///     .execute(conn)?;
2118    ///
2119    /// let roberts_second_street_in_db = contacts
2120    ///                             .filter(name.eq("Robert Downey Jr."))
2121    ///                             .select(address.retrieve_by_path_as_object(vec!["1", "street"]))
2122    ///                             .get_result::<serde_json::Value>(conn)?;
2123    ///
2124    /// assert_eq!(roberts_second_street_in_db, serde_json::json!("Somewhere In Ny 251"));
2125    /// #     Ok(())
2126    /// # }
2127    /// # #[cfg(not(feature = "serde_json"))]
2128    /// # fn run_test() -> QueryResult<()> {
2129    /// #     Ok(())
2130    /// # }
2131    /// ```
2132    fn retrieve_by_path_as_object<T>(
2133        self,
2134        other: T,
2135    ) -> dsl::RetrieveByPathAsObjectJson<Self, T::Expression>
2136    where
2137        T: AsExpression<Array<Text>>,
2138    {
2139        Grouped(RetrieveByPathAsObjectJson::new(self, other.as_expression()))
2140    }
2141
2142    /// Creates a PostgreSQL `#>>` expression.
2143    ///
2144    /// This operator extracts the value associated with the given key, that is provided on the
2145    /// Right Hand Side of the operator.
2146    ///
2147    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
2148    /// Extracts JSON object field as Text with the given key.
2149    /// # Example
2150    ///
2151    /// ```rust
2152    /// # include!("../../doctest_setup.rs");
2153    /// #
2154    /// # table! {
2155    /// #    contacts {
2156    /// #        id -> Integer,
2157    /// #        name -> VarChar,
2158    /// #        address -> Jsonb,
2159    /// #    }
2160    /// # }
2161    /// #
2162    /// # fn main() {
2163    /// #     run_test().unwrap();
2164    /// # }
2165    ///
2166    /// # #[cfg(feature = "serde_json")]
2167    /// # fn run_test() -> QueryResult<()> {
2168    /// #     use self::contacts::dsl::*;
2169    /// #     let conn = &mut establish_connection();
2170    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2171    /// #     diesel::sql_query("CREATE TABLE contacts (
2172    /// #         id SERIAL PRIMARY KEY,
2173    /// #         name VARCHAR NOT NULL,
2174    /// #         address JSONB NOT NULL
2175    /// #     )").execute(conn)
2176    /// #        .unwrap();
2177    /// #
2178    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
2179    ///     {
2180    ///         "street": "Somewhere In La 251",
2181    ///         "city": "Los Angeles",
2182    ///         "postcode": "12231223",
2183    ///         "state": "California"
2184    ///     },
2185    ///     {
2186    ///         "street": "Somewhere In Ny 251",
2187    ///         "city": "New York",
2188    ///         "postcode": "3213212",
2189    ///         "state": "New York"
2190    ///     }
2191    /// ]);
2192    ///
2193    /// diesel::insert_into(contacts)
2194    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
2195    ///     .execute(conn)?;
2196    ///
2197    /// let roberts_second_street_in_db = contacts
2198    ///                             .filter(name.eq("Robert Downey Jr."))
2199    ///                             .select(address.retrieve_by_path_as_text(vec!["1", "street"]))
2200    ///                             .get_result::<String>(conn)?;
2201    ///
2202    /// assert_eq!(roberts_second_street_in_db, "Somewhere In Ny 251");
2203    ///
2204    /// #     Ok(())
2205    /// # }
2206    /// # #[cfg(not(feature = "serde_json"))]
2207    /// # fn run_test() -> QueryResult<()> {
2208    /// #     Ok(())
2209    /// # }
2210    /// ```
2211    fn retrieve_by_path_as_text<T>(
2212        self,
2213        other: T,
2214    ) -> dsl::RetrieveByPathAsTextJson<Self, T::Expression>
2215    where
2216        T: AsExpression<Array<Text>>,
2217    {
2218        Grouped(RetrieveByPathAsTextJson::new(self, other.as_expression()))
2219    }
2220}
2221
2222#[doc(hidden)]
2223impl<T> PgAnyJsonExpressionMethods for T
2224where
2225    T: Expression,
2226    T::SqlType: JsonOrNullableJsonOrJsonbOrNullableJsonb,
2227{
2228}
2229
2230/// PostgreSQL specific methods present on Binary expressions.
2231#[cfg(feature = "postgres_backend")]
2232pub trait PgBinaryExpressionMethods: Expression + Sized {
2233    /// Concatenates two PostgreSQL byte arrays using the `||` operator.
2234    ///
2235    /// # Example
2236    ///
2237    /// ```rust
2238    /// # include!("../../doctest_setup.rs");
2239    /// #
2240    /// # table! {
2241    /// #     users {
2242    /// #         id -> Integer,
2243    /// #         name -> Binary,
2244    /// #         hair_color -> Nullable<Binary>,
2245    /// #     }
2246    /// # }
2247    /// #
2248    /// # fn main() {
2249    /// #     use self::users::dsl::*;
2250    /// #     use diesel::insert_into;
2251    /// #
2252    /// #     let connection = &mut connection_no_data();
2253    /// #     diesel::sql_query("CREATE TABLE users (
2254    /// #         id INTEGER PRIMARY KEY,
2255    /// #         name BYTEA NOT NULL,
2256    /// #         hair_color BYTEA
2257    /// #     )").execute(connection).unwrap();
2258    /// #
2259    /// #     insert_into(users)
2260    /// #         .values(&vec![
2261    /// #             (id.eq(1), name.eq("Sean".as_bytes()), Some(hair_color.eq(Some("Green".as_bytes())))),
2262    /// #             (id.eq(2), name.eq("Tess".as_bytes()), None),
2263    /// #         ])
2264    /// #         .execute(connection)
2265    /// #         .unwrap();
2266    /// #
2267    /// let names = users.select(name.concat(" the Greatest".as_bytes())).load(connection);
2268    /// let expected_names = vec![
2269    ///     b"Sean the Greatest".to_vec(),
2270    ///     b"Tess the Greatest".to_vec()
2271    /// ];
2272    /// assert_eq!(Ok(expected_names), names);
2273    ///
2274    /// // If the value is nullable, the output will be nullable
2275    /// let names = users.select(hair_color.concat("ish".as_bytes())).load(connection);
2276    /// let expected_names = vec![
2277    ///     Some(b"Greenish".to_vec()),
2278    ///     None,
2279    /// ];
2280    /// assert_eq!(Ok(expected_names), names);
2281    /// # }
2282    /// ```
2283    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
2284    where
2285        Self::SqlType: SqlType,
2286        T: AsExpression<Self::SqlType>,
2287    {
2288        Grouped(Concat::new(self, other.as_expression()))
2289    }
2290
2291    /// Creates a PostgreSQL binary `LIKE` expression.
2292    ///
2293    /// This method is case sensitive. There is no case-insensitive
2294    /// equivalent as of PostgreSQL 14.
2295    ///
2296    /// # Examples
2297    ///
2298    /// ```rust
2299    /// # include!("../../doctest_setup.rs");
2300    /// #
2301    /// # table! {
2302    /// #     users {
2303    /// #         id -> Integer,
2304    /// #         name -> Binary,
2305    /// #     }
2306    /// # }
2307    /// #
2308    /// # fn main() {
2309    /// #     use self::users::dsl::*;
2310    /// #     use diesel::insert_into;
2311    /// #
2312    /// #     let connection = &mut connection_no_data();
2313    /// #     diesel::sql_query("CREATE TABLE users (
2314    /// #         id INTEGER PRIMARY KEY,
2315    /// #         name BYTEA NOT NULL
2316    /// #     )").execute(connection).unwrap();
2317    /// #
2318    /// #     insert_into(users)
2319    /// #         .values(&vec![
2320    /// #             (id.eq(1), name.eq("Sean".as_bytes())),
2321    /// #             (id.eq(2), name.eq("Tess".as_bytes()))
2322    /// #         ])
2323    /// #         .execute(connection)
2324    /// #         .unwrap();
2325    /// #
2326    /// let starts_with_s = users
2327    ///     .select(name)
2328    ///     .filter(name.like(b"S%".to_vec()))
2329    ///     .load(connection);
2330    /// assert_eq!(Ok(vec![b"Sean".to_vec()]), starts_with_s);
2331    /// # }
2332    /// ```
2333    fn like<T>(self, other: T) -> dsl::Like<Self, T>
2334    where
2335        Self::SqlType: SqlType,
2336        T: AsExpression<Self::SqlType>,
2337    {
2338        Grouped(Like::new(self, other.as_expression()))
2339    }
2340
2341    /// Creates a PostgreSQL binary `LIKE` expression.
2342    ///
2343    /// This method is case sensitive. There is no case-insensitive
2344    /// equivalent as of PostgreSQL 14.
2345    ///
2346    /// # Examples
2347    ///
2348    /// ```rust
2349    /// # include!("../../doctest_setup.rs");
2350    /// #
2351    /// # table! {
2352    /// #     users {
2353    /// #         id -> Integer,
2354    /// #         name -> Binary,
2355    /// #     }
2356    /// # }
2357    /// #
2358    /// # fn main() {
2359    /// #     use self::users::dsl::*;
2360    /// #     use diesel::insert_into;
2361    /// #
2362    /// #     let connection = &mut connection_no_data();
2363    /// #     diesel::sql_query("CREATE TABLE users (
2364    /// #         id INTEGER PRIMARY KEY,
2365    /// #         name BYTEA NOT NULL
2366    /// #     )").execute(connection).unwrap();
2367    /// #
2368    /// #     insert_into(users)
2369    /// #         .values(&vec![
2370    /// #             (id.eq(1), name.eq("Sean".as_bytes())),
2371    /// #             (id.eq(2), name.eq("Tess".as_bytes()))
2372    /// #         ])
2373    /// #         .execute(connection)
2374    /// #         .unwrap();
2375    /// #
2376    /// let starts_with_s = users
2377    ///     .select(name)
2378    ///     .filter(name.not_like(b"S%".to_vec()))
2379    ///     .load(connection);
2380    /// assert_eq!(Ok(vec![b"Tess".to_vec()]), starts_with_s);
2381    /// # }
2382    /// ```
2383    fn not_like<T>(self, other: T) -> dsl::NotLike<Self, T>
2384    where
2385        Self::SqlType: SqlType,
2386        T: AsExpression<Self::SqlType>,
2387    {
2388        Grouped(NotLike::new(self, other.as_expression()))
2389    }
2390}
2391
2392#[doc(hidden)]
2393impl<T> PgBinaryExpressionMethods for T
2394where
2395    T: Expression,
2396    T::SqlType: BinaryOrNullableBinary,
2397{
2398}
2399
2400pub(in crate::pg) mod private {
2401    use crate::sql_types::{
2402        Array, Binary, Cidr, Inet, Integer, Json, Jsonb, Nullable, Range, SqlType, Text,
2403    };
2404    use crate::{Expression, IntoSql};
2405
2406    /// Marker trait used to implement `ArrayExpressionMethods` on the appropriate
2407    /// types. Once coherence takes associated types into account, we can remove
2408    /// this trait.
2409    #[diagnostic::on_unimplemented(
2410        message = "`{Self}` is neither `diesel::sql_types::Array<_>` nor `diesel::sql_types::Nullable<Array<_>>`",
2411        note = "try to provide an expression that produces one of the expected sql types"
2412    )]
2413    pub trait ArrayOrNullableArray {}
2414
2415    impl<T> ArrayOrNullableArray for Array<T> {}
2416    impl<T> ArrayOrNullableArray for Nullable<Array<T>> {}
2417
2418    /// Marker trait used to implement `PgNetExpressionMethods` on the appropriate types.
2419    #[diagnostic::on_unimplemented(
2420        message = "`{Self}` is neither `diesel::sql_types::Inet`, `diesel::sql_types::Cidr`, `diesel::sql_types::Nullable<Inet>` nor `diesel::sql_types::Nullable<Cidr>",
2421        note = "try to provide an expression that produces one of the expected sql types"
2422    )]
2423    pub trait InetOrCidr {}
2424
2425    impl InetOrCidr for Inet {}
2426    impl InetOrCidr for Cidr {}
2427    impl InetOrCidr for Nullable<Inet> {}
2428    impl InetOrCidr for Nullable<Cidr> {}
2429
2430    /// Marker trait used to implement `PgTextExpressionMethods` on the appropriate
2431    /// types. Once coherence takes associated types into account, we can remove
2432    /// this trait.
2433    #[diagnostic::on_unimplemented(
2434        message = "`{Self}` is neither `diesel::sql_types::Text` nor `diesel::sql_types::Nullable<Text>`",
2435        note = "try to provide an expression that produces one of the expected sql types"
2436    )]
2437    pub trait TextOrNullableText {}
2438
2439    impl TextOrNullableText for Text {}
2440    impl TextOrNullableText for Nullable<Text> {}
2441
2442    /// Marker trait used to extract the inner type
2443    /// of our `Range<T>` sql type, used to implement `PgRangeExpressionMethods`
2444    pub trait RangeHelper: SqlType {
2445        type Inner;
2446    }
2447
2448    impl<ST> RangeHelper for Range<ST>
2449    where
2450        Self: 'static,
2451    {
2452        type Inner = ST;
2453    }
2454
2455    /// Marker trait used to implement `PgRangeExpressionMethods` on the appropriate
2456    /// types. Once coherence takes associated types into account, we can remove
2457    /// this trait.
2458    #[diagnostic::on_unimplemented(
2459        message = "`{Self}` is neither `diesel::sql_types::Range<_>` nor `diesel::sql_types::Nullable<Range<_>>`",
2460        note = "try to provide an expression that produces one of the expected sql types"
2461    )]
2462    pub trait RangeOrNullableRange {}
2463
2464    impl<ST> RangeOrNullableRange for Range<ST> {}
2465    impl<ST> RangeOrNullableRange for Nullable<Range<ST>> {}
2466
2467    /// Marker trait used to implement `PgJsonbExpressionMethods` on the appropriate types.
2468    #[diagnostic::on_unimplemented(
2469        message = "`{Self}` is neither `diesel::sql_types::Jsonb` nor `diesel::sql_types::Nullable<Jsonb>`",
2470        note = "try to provide an expression that produces one of the expected sql types"
2471    )]
2472    pub trait JsonbOrNullableJsonb {}
2473
2474    impl JsonbOrNullableJsonb for Jsonb {}
2475    impl JsonbOrNullableJsonb for Nullable<Jsonb> {}
2476
2477    /// A trait that describes valid json indices used by postgresql
2478    pub trait JsonRemoveIndex {
2479        /// The Expression node created by this index type
2480        type Expression: Expression;
2481
2482        /// Convert a index value into the corresponding index expression
2483        fn into_json_index_expression(self) -> Self::Expression;
2484    }
2485
2486    impl<'a> JsonRemoveIndex for &'a str {
2487        type Expression = crate::dsl::AsExprOf<&'a str, crate::sql_types::Text>;
2488
2489        fn into_json_index_expression(self) -> Self::Expression {
2490            self.into_sql::<Text>()
2491        }
2492    }
2493
2494    impl JsonRemoveIndex for String {
2495        type Expression = crate::dsl::AsExprOf<String, crate::sql_types::Text>;
2496
2497        fn into_json_index_expression(self) -> Self::Expression {
2498            self.into_sql::<Text>()
2499        }
2500    }
2501
2502    impl JsonRemoveIndex for Vec<String> {
2503        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
2504
2505        fn into_json_index_expression(self) -> Self::Expression {
2506            self.into_sql::<Array<Text>>()
2507        }
2508    }
2509
2510    impl JsonRemoveIndex for Vec<&str> {
2511        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
2512
2513        fn into_json_index_expression(self) -> Self::Expression {
2514            self.into_sql::<Array<Text>>()
2515        }
2516    }
2517
2518    impl<'a> JsonRemoveIndex for &'a [&'a str] {
2519        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
2520
2521        fn into_json_index_expression(self) -> Self::Expression {
2522            self.into_sql::<Array<Text>>()
2523        }
2524    }
2525
2526    impl JsonRemoveIndex for i32 {
2527        type Expression = crate::dsl::AsExprOf<i32, crate::sql_types::Int4>;
2528
2529        fn into_json_index_expression(self) -> Self::Expression {
2530            self.into_sql::<crate::sql_types::Int4>()
2531        }
2532    }
2533
2534    impl<T> JsonRemoveIndex for T
2535    where
2536        T: Expression,
2537        T::SqlType: TextArrayOrTextOrInteger,
2538    {
2539        type Expression = Self;
2540
2541        fn into_json_index_expression(self) -> Self::Expression {
2542            self
2543        }
2544    }
2545
2546    #[diagnostic::on_unimplemented(
2547        message = "`{Self}` is neither `diesel::sql_types::Text`, `diesel::sql_types::Integer` nor `diesel::sql_types::Array<Text>`",
2548        note = "try to provide an expression that produces one of the expected sql types"
2549    )]
2550    pub trait TextArrayOrTextOrInteger {}
2551
2552    impl TextArrayOrTextOrInteger for Array<Text> {}
2553    impl TextArrayOrTextOrInteger for Text {}
2554    impl TextArrayOrTextOrInteger for Integer {}
2555
2556    /// Marker trait used to implement `PgAnyJsonExpressionMethods` on the appropriate types.
2557    #[diagnostic::on_unimplemented(
2558        message = "`{Self}` is neither `diesel::sql_types::Json`, `diesel::sql_types::Jsonb`, `diesel::sql_types::Nullable<Json>` nor `diesel::sql_types::Nullable<Jsonb>`",
2559        note = "try to provide an expression that produces one of the expected sql types"
2560    )]
2561    pub trait JsonOrNullableJsonOrJsonbOrNullableJsonb {}
2562    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Json {}
2563    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Json> {}
2564    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Jsonb {}
2565    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Jsonb> {}
2566
2567    pub trait JsonIndex {
2568        type Expression: Expression;
2569
2570        fn into_json_index_expression(self) -> Self::Expression;
2571    }
2572
2573    impl<'a> JsonIndex for &'a str {
2574        type Expression = crate::dsl::AsExprOf<&'a str, crate::sql_types::Text>;
2575
2576        fn into_json_index_expression(self) -> Self::Expression {
2577            self.into_sql::<Text>()
2578        }
2579    }
2580
2581    impl JsonIndex for String {
2582        type Expression = crate::dsl::AsExprOf<String, crate::sql_types::Text>;
2583
2584        fn into_json_index_expression(self) -> Self::Expression {
2585            self.into_sql::<Text>()
2586        }
2587    }
2588
2589    impl JsonIndex for i32 {
2590        type Expression = crate::dsl::AsExprOf<i32, crate::sql_types::Int4>;
2591
2592        fn into_json_index_expression(self) -> Self::Expression {
2593            self.into_sql::<crate::sql_types::Int4>()
2594        }
2595    }
2596
2597    impl<T> JsonIndex for T
2598    where
2599        T: Expression,
2600        T::SqlType: TextOrInteger,
2601    {
2602        type Expression = Self;
2603
2604        fn into_json_index_expression(self) -> Self::Expression {
2605            self
2606        }
2607    }
2608
2609    #[diagnostic::on_unimplemented(
2610        message = "`{Self}` is neither `diesel::sql_types::Text` nor `diesel::sql_types::Integer`",
2611        note = "try to provide an expression that produces one of the expected sql types"
2612    )]
2613    pub trait TextOrInteger {}
2614    impl TextOrInteger for Text {}
2615    impl TextOrInteger for Integer {}
2616
2617    #[diagnostic::on_unimplemented(
2618        message = "`{Self}` is neither `diesel::sql_types::Binary` nor `diesel::sql_types::Nullable<Binary>`",
2619        note = "try to provide an expression that produces one of the expected sql types"
2620    )]
2621    pub trait BinaryOrNullableBinary {}
2622
2623    impl BinaryOrNullableBinary for Binary {}
2624    impl BinaryOrNullableBinary for Nullable<Binary> {}
2625}