diesel/pg/expression/
expression_methods.rs

1//! PostgreSQL specific expression methods
2
3pub(in crate::pg) use self::private::{
4    ArrayOrNullableArray, CombinedAllNullableValue, CombinedNullableValue, InetOrCidr, JsonIndex,
5    JsonOrNullableJson, JsonOrNullableJsonOrJsonbOrNullableJsonb, JsonRemoveIndex,
6    JsonbOrNullableJsonb, MaybeNullableValue, MultirangeOrNullableMultirange,
7    MultirangeOrRangeMaybeNullable, RangeOrMultirange, RangeOrNullableRange,
8    RecordOrNullableRecord, TextArrayOrNullableTextArray, TextOrNullableText,
9};
10use super::date_and_time::{AtTimeZone, DateTimeLike};
11use super::operators::*;
12use crate::dsl;
13use crate::expression::grouped::Grouped;
14use crate::expression::operators::{Asc, Concat, Desc, Like, NotLike};
15use crate::expression::{AsExpression, Expression, IntoSql, TypedExpressionType};
16use crate::pg::expression::expression_methods::private::BinaryOrNullableBinary;
17use crate::sql_types::{Array, Inet, Integer, Range, SqlType, Text, VarChar};
18use crate::EscapeExpressionMethods;
19
20/// PostgreSQL specific methods which are present on all expressions.
21#[cfg(feature = "postgres_backend")]
22pub trait PgExpressionMethods: Expression + Sized {
23    /// Creates a PostgreSQL `IS NOT DISTINCT FROM` expression.
24    ///
25    /// This behaves identically to the `=` operator, except that `NULL` is
26    /// treated as a normal value.
27    ///
28    /// # Example
29    ///
30    /// ```rust
31    /// # include!("../../doctest_setup.rs");
32    /// #
33    /// # fn main() {
34    /// #     use schema::users::dsl::*;
35    /// #     let connection = &mut establish_connection();
36    /// let distinct = users.select(id).filter(name.is_distinct_from("Sean"));
37    /// let not_distinct = users.select(id).filter(name.is_not_distinct_from("Sean"));
38    /// assert_eq!(Ok(2), distinct.first(connection));
39    /// assert_eq!(Ok(1), not_distinct.first(connection));
40    /// # }
41    /// ```
42    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
43    fn is_not_distinct_from<T>(self, other: T) -> dsl::IsNotDistinctFrom<Self, T>
44    where
45        Self::SqlType: SqlType,
46        T: AsExpression<Self::SqlType>,
47    {
48        Grouped(IsNotDistinctFrom::new(self, other.as_expression()))
49    }
50
51    /// Creates a PostgreSQL `IS DISTINCT FROM` expression.
52    ///
53    /// This behaves identically to the `!=` operator, except that `NULL` is
54    /// treated as a normal value.
55    ///
56    /// # Example
57    ///
58    /// ```rust
59    /// # include!("../../doctest_setup.rs");
60    /// #
61    /// # fn main() {
62    /// #     use schema::users::dsl::*;
63    /// #     let connection = &mut establish_connection();
64    /// let distinct = users.select(id).filter(name.is_distinct_from("Sean"));
65    /// let not_distinct = users.select(id).filter(name.is_not_distinct_from("Sean"));
66    /// assert_eq!(Ok(2), distinct.first(connection));
67    /// assert_eq!(Ok(1), not_distinct.first(connection));
68    /// # }
69    /// ```
70    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
71    fn is_distinct_from<T>(self, other: T) -> dsl::IsDistinctFrom<Self, T>
72    where
73        Self::SqlType: SqlType,
74        T: AsExpression<Self::SqlType>,
75    {
76        Grouped(IsDistinctFrom::new(self, other.as_expression()))
77    }
78
79    /// Creates a PostgreSQL `<@` expression.
80    ///
81    /// This operator returns true whether a element is contained by a range
82    ///
83    /// This operator evaluates to true for the following cases:
84    ///
85    /// ```text
86    /// self:     |
87    /// other:  [-----]
88    /// ```
89    ///
90    /// ```text
91    /// self:  |
92    /// other: [----]
93    /// ```
94    ///
95    /// ```text
96    /// self:       |
97    /// other:  [----]
98    /// ```
99    ///
100    /// This operator evaluates to false for the following cases:
101    ///
102    /// ```text
103    /// self:           |
104    /// other:  [-----]
105    /// ```
106    ///
107    /// ```text
108    /// self:  |
109    /// other:   [----]
110    /// ```
111    ///
112    /// ```text
113    /// self:       |
114    /// other: [----)
115    /// ```
116    ///
117    /// # Example
118    ///
119    /// ```rust
120    /// # include!("../../doctest_setup.rs");
121    /// #
122    /// # table! {
123    /// #     posts {
124    /// #         id -> Integer,
125    /// #         versions -> Range<Integer>,
126    /// #     }
127    /// # }
128    /// #
129    /// # fn main() {
130    /// #     run_test().unwrap();
131    /// # }
132    /// #
133    /// # fn run_test() -> QueryResult<()> {
134    /// #     use std::collections::Bound;
135    /// #     use diesel::dsl::int4range;
136    /// #     use diesel::sql_types::Integer;
137    /// #
138    /// #     let conn = &mut establish_connection();
139    /// #
140    ///       let my_range = int4range(1, 5, diesel::sql_types::RangeBound::LowerBoundInclusiveUpperBoundExclusive);
141    ///
142    ///       let (first, second) = diesel::select((
143    ///           4.into_sql::<Integer>().is_contained_by_range(my_range),
144    ///           10.into_sql::<Integer>().is_contained_by_range(my_range)
145    ///       )).get_result::<(bool, bool)>(conn)?;
146    ///
147    ///       assert_eq!(first, true);
148    ///       assert_eq!(second, false);
149    /// #
150    /// #     Ok(())
151    /// # }
152    /// ```
153    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
154    fn is_contained_by_range<T>(self, other: T) -> dsl::IsContainedByRange<Self, T>
155    where
156        Self::SqlType: SqlType,
157        T: AsExpression<Range<Self::SqlType>>,
158    {
159        Grouped(IsContainedBy::new(self, other.as_expression()))
160    }
161}
162
163impl<T: Expression> PgExpressionMethods for T {}
164
165/// PostgreSQL specific methods present on timestamp expressions.
166#[cfg(feature = "postgres_backend")]
167pub trait PgTimestampExpressionMethods: Expression + Sized {
168    /// Creates a PostgreSQL "AT TIME ZONE" expression.
169    ///
170    /// When this is called on a `TIMESTAMP WITHOUT TIME ZONE` column,
171    /// the value will be treated as if were in the given time zone,
172    /// and then converted to UTC.
173    ///
174    /// When this is called on a `TIMESTAMP WITH TIME ZONE` column,
175    /// the value will be converted to the given time zone,
176    /// and then have its time zone information removed.
177    ///
178    /// # Example
179    ///
180    /// ```rust
181    /// # include!("../../doctest_setup.rs");
182    /// #
183    /// # table! {
184    /// #     timestamps (timestamp) {
185    /// #         timestamp -> Timestamp,
186    /// #     }
187    /// # }
188    /// #
189    /// # fn main() {
190    /// #     run_test().unwrap();
191    /// # }
192    /// #
193    /// # #[cfg(all(feature = "postgres", feature = "chrono"))]
194    /// # fn run_test() -> QueryResult<()> {
195    /// #     use self::timestamps::dsl::*;
196    /// #     use chrono::*;
197    /// #     let connection = &mut establish_connection();
198    /// #     diesel::sql_query("CREATE TABLE timestamps (\"timestamp\"
199    /// #         timestamp NOT NULL)").execute(connection)?;
200    /// let christmas_morning = NaiveDate::from_ymd(2017, 12, 25)
201    ///     .and_hms(8, 0, 0);
202    /// diesel::insert_into(timestamps)
203    ///     .values(timestamp.eq(christmas_morning))
204    ///     .execute(connection)?;
205    ///
206    /// let utc_time = timestamps
207    ///     .select(timestamp.at_time_zone("UTC"))
208    ///     .first(connection)?;
209    /// assert_eq!(christmas_morning, utc_time);
210    ///
211    /// let eastern_time = timestamps
212    ///     .select(timestamp.at_time_zone("EST"))
213    ///     .first(connection)?;
214    /// let five_hours_later = christmas_morning + Duration::hours(5);
215    /// assert_eq!(five_hours_later, eastern_time);
216    /// #     Ok(())
217    /// # }
218    /// #
219    /// # #[cfg(not(all(feature = "postgres", feature = "chrono")))]
220    /// # fn run_test() -> QueryResult<()> {
221    /// #     Ok(())
222    /// # }
223    /// ```
224    fn at_time_zone<T>(self, timezone: T) -> dsl::AtTimeZone<Self, T>
225    where
226        T: AsExpression<VarChar>,
227    {
228        Grouped(AtTimeZone::new(self, timezone.as_expression()))
229    }
230}
231
232impl<T: Expression> PgTimestampExpressionMethods for T where T::SqlType: DateTimeLike {}
233
234/// PostgreSQL specific methods present on array expressions.
235#[cfg(feature = "postgres_backend")]
236pub trait PgArrayExpressionMethods: Expression + Sized {
237    /// Creates a PostgreSQL `&&` expression.
238    ///
239    /// This operator returns whether two arrays have common elements.
240    ///
241    /// # Example
242    ///
243    /// ```rust
244    /// # include!("../../doctest_setup.rs");
245    /// #
246    /// # table! {
247    /// #     posts {
248    /// #         id -> Integer,
249    /// #         tags -> Array<VarChar>,
250    /// #     }
251    /// # }
252    /// #
253    /// # fn main() {
254    /// #     run_test().unwrap();
255    /// # }
256    /// #
257    /// # fn run_test() -> QueryResult<()> {
258    /// #     use self::posts::dsl::*;
259    /// #     let conn = &mut establish_connection();
260    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
261    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
262    /// #           .execute(conn)
263    /// #           .unwrap();
264    /// #
265    /// diesel::insert_into(posts)
266    ///     .values(&vec![
267    ///         tags.eq(vec!["cool", "awesome"]),
268    ///         tags.eq(vec!["awesome", "great"]),
269    ///         tags.eq(vec!["cool", "great"]),
270    ///     ])
271    ///     .execute(conn)?;
272    ///
273    /// let data = posts.select(id)
274    ///     .filter(tags.overlaps_with(vec!["horrid", "cool"]))
275    ///     .load::<i32>(conn)?;
276    /// assert_eq!(vec![1, 3], data);
277    ///
278    /// let data = posts.select(id)
279    ///     .filter(tags.overlaps_with(vec!["cool", "great"]))
280    ///     .load::<i32>(conn)?;
281    /// assert_eq!(vec![1, 2, 3], data);
282    ///
283    /// let data = posts.select(id)
284    ///     .filter(tags.overlaps_with(vec!["horrid"]))
285    ///     .load::<i32>(conn)?;
286    /// assert!(data.is_empty());
287    /// #     Ok(())
288    /// # }
289    /// ```
290    fn overlaps_with<T>(self, other: T) -> dsl::OverlapsWith<Self, T>
291    where
292        Self::SqlType: SqlType,
293        T: AsExpression<Self::SqlType>,
294    {
295        Grouped(OverlapsWith::new(self, other.as_expression()))
296    }
297
298    /// Creates a PostgreSQL `@>` expression.
299    ///
300    /// This operator returns whether an array contains another array.
301    ///
302    /// # Example
303    ///
304    /// ```rust
305    /// # include!("../../doctest_setup.rs");
306    /// #
307    /// # table! {
308    /// #     posts {
309    /// #         id -> Integer,
310    /// #         tags -> Array<VarChar>,
311    /// #     }
312    /// # }
313    /// #
314    /// # fn main() {
315    /// #     run_test().unwrap();
316    /// # }
317    /// #
318    /// # fn run_test() -> QueryResult<()> {
319    /// #     use self::posts::dsl::*;
320    /// #     let conn = &mut establish_connection();
321    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
322    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
323    /// #         .execute(conn)
324    /// #         .unwrap();
325    /// #
326    /// diesel::insert_into(posts)
327    ///     .values(tags.eq(vec!["cool", "awesome"]))
328    ///     .execute(conn)?;
329    ///
330    /// let cool_posts = posts.select(id)
331    ///     .filter(tags.contains(vec!["cool"]))
332    ///     .load::<i32>(conn)?;
333    /// assert_eq!(vec![1], cool_posts);
334    ///
335    /// let amazing_posts = posts.select(id)
336    ///     .filter(tags.contains(vec!["cool", "amazing"]))
337    ///     .load::<i32>(conn)?;
338    /// assert!(amazing_posts.is_empty());
339    /// #     Ok(())
340    /// # }
341    /// ```
342    fn contains<T>(self, other: T) -> dsl::Contains<Self, T>
343    where
344        Self::SqlType: SqlType,
345        T: AsExpression<Self::SqlType>,
346    {
347        Grouped(Contains::new(self, other.as_expression()))
348    }
349
350    /// Creates a PostgreSQL `<@` expression.
351    ///
352    /// This operator returns whether an array is contained by another array.
353    /// `foo.contains(bar)` is the same as `bar.is_contained_by(foo)`
354    ///
355    /// # Example
356    ///
357    /// ```rust
358    /// # include!("../../doctest_setup.rs");
359    /// #
360    /// # table! {
361    /// #     posts {
362    /// #         id -> Integer,
363    /// #         tags -> Array<VarChar>,
364    /// #     }
365    /// # }
366    /// #
367    /// # fn main() {
368    /// #     run_test().unwrap();
369    /// # }
370    /// #
371    /// # fn run_test() -> QueryResult<()> {
372    /// #     use self::posts::dsl::*;
373    /// #     let conn = &mut establish_connection();
374    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
375    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
376    /// #         .execute(conn)
377    /// #         .unwrap();
378    /// #
379    /// diesel::insert_into(posts)
380    ///     .values(tags.eq(vec!["cool", "awesome"]))
381    ///     .execute(conn)?;
382    ///
383    /// let data = posts.select(id)
384    ///     .filter(tags.is_contained_by(vec!["cool", "awesome", "amazing"]))
385    ///     .load::<i32>(conn)?;
386    /// assert_eq!(vec![1], data);
387    ///
388    /// let data = posts.select(id)
389    ///     .filter(tags.is_contained_by(vec!["cool"]))
390    ///     .load::<i32>(conn)?;
391    /// assert!(data.is_empty());
392    /// #     Ok(())
393    /// # }
394    /// ```
395    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
396    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
397    where
398        Self::SqlType: SqlType,
399        T: AsExpression<Self::SqlType>,
400    {
401        Grouped(IsContainedBy::new(self, other.as_expression()))
402    }
403    /// Indexes a PostgreSQL array.
404    ///
405    /// This operator indexes in to an array to access a single element.
406    ///
407    /// Note that PostgreSQL arrays are 1-indexed, so `foo.index(1)` is the
408    /// first element in the array.
409    ///
410    /// # Example
411    ///
412    /// ```rust
413    /// # include!("../../doctest_setup.rs");
414    /// #
415    /// # table! {
416    /// #     posts {
417    /// #         id -> Integer,
418    /// #         tags -> Array<VarChar>,
419    /// #     }
420    /// # }
421    /// #
422    /// # fn main() {
423    /// #     run_test().unwrap();
424    /// # }
425    /// #
426    /// # fn run_test() -> QueryResult<()> {
427    /// #     use self::posts::dsl::*;
428    /// #     let conn = &mut establish_connection();
429    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
430    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
431    /// #         .execute(conn)
432    /// #         .unwrap();
433    /// #
434    /// diesel::insert_into(posts)
435    ///     .values(&vec![
436    ///         tags.eq(vec!["cool", "awesome"]),
437    ///         tags.eq(vec!["splendid", "marvellous"]),
438    ///    ])
439    ///     .execute(conn)?;
440    ///
441    /// let data = posts.select(tags.index(id))
442    ///     .load::<String>(conn)?;
443    /// assert_eq!(vec!["cool", "marvellous"], data);
444    ///
445    /// let data = posts.select(id)
446    ///     .filter(tags.index(1).eq("splendid"))
447    ///     .load::<i32>(conn)?;
448    /// assert_eq!(vec![2], data);
449    /// #     Ok(())
450    /// # }
451    /// ```
452    fn index<T>(self, other: T) -> dsl::Index<Self, T>
453    where
454        Self::SqlType: SqlType,
455        T: AsExpression<Integer>,
456    {
457        ArrayIndex::new(self, other.as_expression())
458    }
459
460    /// Creates a PostgreSQL `||` expression.
461    ///
462    /// This operator concatenates two Array values and returns Array value
463    ///
464    /// # Example
465    ///
466    /// ```rust
467    /// # include!("../../doctest_setup.rs");
468    /// #
469    /// # table! {
470    /// #     posts {
471    /// #         id -> Integer,
472    /// #         tags -> Array<VarChar>,
473    /// #     }
474    /// # }
475    /// #
476    /// # fn main() {
477    /// #     run_test().unwrap();
478    /// # }
479    /// #
480    /// # fn run_test() -> QueryResult<()> {
481    /// #     use self::posts::dsl::*;
482    /// #     let conn = &mut establish_connection();
483    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
484    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, tags TEXT[] NOT NULL)")
485    /// #         .execute(conn)
486    /// #         .unwrap();
487    /// #
488    /// diesel::insert_into(posts)
489    ///     .values(tags.eq(vec!["cool", "awesome"]))
490    ///     .execute(conn)?;
491    ///
492    /// let res = posts.select(tags.concat(vec!["amazing"])).load::<Vec<String>>(conn)?;
493    /// let expected_tags = vec!["cool", "awesome", "amazing"];
494    /// assert_eq!(expected_tags, res[0]);
495    /// #     Ok(())
496    /// # }
497    ///
498    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
499    where
500        Self::SqlType: SqlType,
501        T: AsExpression<Self::SqlType>,
502    {
503        Grouped(Concat::new(self, other.as_expression()))
504    }
505}
506
507impl<T> PgArrayExpressionMethods for T
508where
509    T: Expression,
510    T::SqlType: ArrayOrNullableArray,
511{
512}
513
514/// PostgreSQL expression methods related to sorting.
515///
516/// This trait is only implemented for `Asc` and `Desc`. Although `.asc` is
517/// implicit if no order is given, you will need to call `.asc()` explicitly in
518/// order to call these methods.
519#[cfg(feature = "postgres_backend")]
520pub trait PgSortExpressionMethods: Sized {
521    /// Specify that nulls should come before other values in this ordering.
522    ///
523    /// Normally, nulls come last when sorting in ascending order and first
524    /// when sorting in descending order.
525    ///
526    /// # Example
527    ///
528    /// ```rust
529    /// # include!("../../doctest_setup.rs");
530    /// #
531    /// # table! {
532    /// #     nullable_numbers (nullable_number) {
533    /// #         nullable_number -> Nullable<Integer>,
534    /// #     }
535    /// # }
536    /// #
537    /// # fn main() {
538    /// #     run_test().unwrap();
539    /// # }
540    /// #
541    /// # fn run_test() -> QueryResult<()> {
542    /// #     use self::nullable_numbers::dsl::*;
543    /// #     let connection = &mut connection_no_data();
544    /// #     diesel::sql_query("CREATE TABLE nullable_numbers (nullable_number INTEGER)").execute(connection)?;
545    /// diesel::insert_into(nullable_numbers)
546    ///     .values(&vec![
547    ///         nullable_number.eq(None),
548    ///         nullable_number.eq(Some(1)),
549    ///         nullable_number.eq(Some(2)),
550    ///     ])
551    ///     .execute(connection)?;
552    ///
553    /// let asc_default_nulls = nullable_numbers.select(nullable_number)
554    ///     .order(nullable_number.asc())
555    ///     .load::<Option<i32>>(connection)?;
556    /// assert_eq!(vec![Some(1), Some(2), None], asc_default_nulls);
557    ///
558    /// let asc_nulls_first = nullable_numbers.select(nullable_number)
559    ///     .order(nullable_number.asc().nulls_first())
560    ///     .load::<Option<i32>>(connection)?;
561    /// assert_eq!(vec![None, Some(1), Some(2)], asc_nulls_first);
562    /// #     Ok(())
563    /// # }
564    /// ```
565    fn nulls_first(self) -> dsl::NullsFirst<Self> {
566        NullsFirst::new(self)
567    }
568
569    /// Specify that nulls should come after other values in this ordering.
570    ///
571    /// Normally, nulls come last when sorting in ascending order and first
572    /// when sorting in descending order.
573    ///
574    /// # Example
575    ///
576    /// ```rust
577    /// # include!("../../doctest_setup.rs");
578    /// #
579    /// # table! {
580    /// #     nullable_numbers (nullable_number) {
581    /// #         nullable_number -> Nullable<Integer>,
582    /// #     }
583    /// # }
584    /// #
585    /// # fn main() {
586    /// #     run_test().unwrap();
587    /// # }
588    /// #
589    /// # fn run_test() -> QueryResult<()> {
590    /// #     use self::nullable_numbers::dsl::*;
591    /// #     let connection = &mut connection_no_data();
592    /// #     diesel::sql_query("CREATE TABLE nullable_numbers (nullable_number INTEGER)").execute(connection)?;
593    /// diesel::insert_into(nullable_numbers)
594    ///     .values(&vec![
595    ///         nullable_number.eq(None),
596    ///         nullable_number.eq(Some(1)),
597    ///         nullable_number.eq(Some(2)),
598    ///     ])
599    ///     .execute(connection)?;
600    ///
601    /// let desc_default_nulls = nullable_numbers.select(nullable_number)
602    ///     .order(nullable_number.desc())
603    ///     .load::<Option<i32>>(connection)?;
604    /// assert_eq!(vec![None, Some(2), Some(1)], desc_default_nulls);
605    ///
606    /// let desc_nulls_last = nullable_numbers.select(nullable_number)
607    ///     .order(nullable_number.desc().nulls_last())
608    ///     .load::<Option<i32>>(connection)?;
609    /// assert_eq!(vec![Some(2), Some(1), None], desc_nulls_last);
610    /// #     Ok(())
611    /// # }
612    /// ```
613    fn nulls_last(self) -> dsl::NullsLast<Self> {
614        NullsLast::new(self)
615    }
616}
617
618impl<T> PgSortExpressionMethods for Asc<T> {}
619impl<T> PgSortExpressionMethods for Desc<T> {}
620
621/// PostgreSQL specific methods present on text expressions.
622#[cfg(feature = "postgres_backend")]
623pub trait PgTextExpressionMethods: Expression + Sized {
624    /// Creates a  PostgreSQL `ILIKE` expression
625    ///
626    /// # Example
627    ///
628    /// ```rust
629    /// # include!("../../doctest_setup.rs");
630    /// #
631    /// # fn main() {
632    /// #     run_test().unwrap();
633    /// # }
634    /// #
635    /// # fn run_test() -> QueryResult<()> {
636    /// #     use schema::animals::dsl::*;
637    /// #     let connection = &mut establish_connection();
638    /// let starts_with_s = animals
639    ///     .select(species)
640    ///     .filter(name.ilike("s%").or(species.ilike("s%")))
641    ///     .get_results::<String>(connection)?;
642    /// assert_eq!(vec!["spider"], starts_with_s);
643    /// #     Ok(())
644    /// # }
645    /// ```
646    fn ilike<T>(self, other: T) -> dsl::ILike<Self, T>
647    where
648        T: AsExpression<Text>,
649    {
650        Grouped(ILike::new(self, other.as_expression()))
651    }
652
653    /// Creates a PostgreSQL `NOT ILIKE` expression
654    ///
655    /// # Example
656    ///
657    /// ```rust
658    /// # include!("../../doctest_setup.rs");
659    /// #
660    /// # fn main() {
661    /// #     run_test().unwrap();
662    /// # }
663    /// #
664    /// # fn run_test() -> QueryResult<()> {
665    /// #     use schema::animals::dsl::*;
666    /// #     let connection = &mut establish_connection();
667    /// let doesnt_start_with_s = animals
668    ///     .select(species)
669    ///     .filter(name.not_ilike("s%").and(species.not_ilike("s%")))
670    ///     .get_results::<String>(connection)?;
671    /// assert_eq!(vec!["dog"], doesnt_start_with_s);
672    /// #     Ok(())
673    /// # }
674    /// ```
675    fn not_ilike<T>(self, other: T) -> dsl::NotILike<Self, T>
676    where
677        T: AsExpression<Text>,
678    {
679        Grouped(NotILike::new(self, other.as_expression()))
680    }
681
682    /// Creates a PostgreSQL `SIMILAR TO` expression
683    ///
684    /// # Example
685    /// ```
686    /// # include!("../../doctest_setup.rs");
687    /// #
688    /// # fn main() {
689    /// #     run_test().unwrap();
690    /// # }
691    /// #
692    /// # fn run_test() -> QueryResult<()> {
693    /// #     use schema::animals::dsl::*;
694    /// #     let connection = &mut establish_connection();
695    /// let starts_with_s = animals
696    ///     .select(species)
697    ///     .filter(name.similar_to("s%").or(species.similar_to("s%")))
698    ///     .get_results::<String>(connection)?;
699    /// assert_eq!(vec!["spider"], starts_with_s);
700    /// #     Ok(())
701    /// # }
702    /// ```
703    fn similar_to<T>(self, other: T) -> dsl::SimilarTo<Self, T>
704    where
705        T: AsExpression<Text>,
706    {
707        Grouped(SimilarTo::new(self, other.as_expression()))
708    }
709
710    /// Creates a PostgreSQL `NOT SIMILAR TO` expression
711    ///
712    /// # Example
713    /// ```
714    /// # include!("../../doctest_setup.rs");
715    /// #
716    /// # fn main() {
717    /// #     run_test().unwrap();
718    /// # }
719    /// #
720    /// # fn run_test() -> QueryResult<()> {
721    /// #     use schema::animals::dsl::*;
722    /// #     let connection = &mut establish_connection();
723    /// let doesnt_start_with_s = animals
724    ///     .select(species)
725    ///     .filter(name.not_similar_to("s%").and(species.not_similar_to("s%")))
726    ///     .get_results::<String>(connection)?;
727    /// assert_eq!(vec!["dog"], doesnt_start_with_s);
728    /// #     Ok(())
729    /// # }
730    /// ```
731    fn not_similar_to<T>(self, other: T) -> dsl::NotSimilarTo<Self, T>
732    where
733        T: AsExpression<Text>,
734    {
735        Grouped(NotSimilarTo::new(self, other.as_expression()))
736    }
737
738    /// Creates a PostgreSQL `IS JSON` expression.
739    /// Requires PostgreSQL>=16
740    ///
741    /// This operator returns true whether an object is a valid JSON
742    ///
743    /// # Example
744    ///
745    /// ```rust,no_run
746    /// # include!("../../doctest_setup.rs");
747    /// #
748    /// # fn main() {
749    /// #     run_test().unwrap();
750    /// # }
751    /// #
752    /// # fn run_test() -> QueryResult<()> {
753    /// #     use std::collections::Bound;
754    /// #     use diesel::sql_types::Text;
755    /// #
756    /// #     let conn = &mut establish_connection();
757    /// #
758    ///
759    /// let res = diesel::select(("1".into_sql::<Text>().is_json())).get_result::<bool>(conn)?;
760    /// assert_eq!(res, true);
761    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_json())).get_result::<bool>(conn)?;
762    /// assert_eq!(res, true);
763    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_json())).get_result::<bool>(conn)?;
764    /// assert_eq!(res, true);
765    /// let res = diesel::select(("(1,2,3)".into_sql::<Text>().is_json())).get_result::<bool>(conn)?;
766    /// assert_eq!(res, false);
767    /// #
768    /// #     Ok(())
769    /// # }
770    /// ```
771    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
772    fn is_json(self) -> dsl::IsJson<Self> {
773        IsJson::new(self)
774    }
775
776    /// Creates a PostgreSQL `IS NOT JSON` expression.
777    /// Requires PostgreSQL>=16
778    ///
779    /// This operator returns true whether an object is not a valid JSON
780    ///
781    /// # Example
782    ///
783    /// ```rust,no_run
784    /// # include!("../../doctest_setup.rs");
785    /// #
786    /// # fn main() {
787    /// #     run_test().unwrap();
788    /// # }
789    /// #
790    /// # fn run_test() -> QueryResult<()> {
791    /// #     use std::collections::Bound;
792    /// #     use diesel::sql_types::Text;
793    /// #
794    /// #     let conn = &mut establish_connection();
795    /// #
796    ///
797    /// let res = diesel::select(("1".into_sql::<Text>().is_not_json())).get_result::<bool>(conn)?;
798    /// assert_eq!(res, false);
799    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_not_json())).get_result::<bool>(conn)?;
800    /// assert_eq!(res, false);
801    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_not_json())).get_result::<bool>(conn)?;
802    /// assert_eq!(res, false);
803    /// let res = diesel::select(("(1,2,3)".into_sql::<Text>().is_not_json())).get_result::<bool>(conn)?;
804    /// assert_eq!(res, true);
805    /// #
806    /// #     Ok(())
807    /// # }
808    /// ```
809    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
810    fn is_not_json(self) -> dsl::IsNotJson<Self> {
811        IsNotJson::new(self)
812    }
813
814    /// Creates a PostgreSQL `IS JSON OBJECT` expression.
815    /// Requires PostgreSQL>=16
816    ///
817    /// This operator returns true whether an object is a valid JSON
818    ///
819    /// # Example
820    ///
821    /// ```rust,no_run
822    /// # include!("../../doctest_setup.rs");
823    /// #
824    /// # fn main() {
825    /// #     run_test().unwrap();
826    /// # }
827    /// #
828    /// # fn run_test() -> QueryResult<()> {
829    /// #     use std::collections::Bound;
830    /// #     use diesel::sql_types::Text;
831    /// #
832    /// #     let conn = &mut establish_connection();
833    /// #
834    ///
835    /// let res = diesel::select(("123".into_sql::<Text>().is_json_object())).get_result::<bool>(conn)?;
836    /// assert_eq!(res, false);
837    /// let res = diesel::select(("abc".into_sql::<Text>().is_json_object())).get_result::<bool>(conn)?;
838    /// assert_eq!(res, false);
839    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_json_object())).get_result::<bool>(conn)?;
840    /// assert_eq!(res, true);
841    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_json_object())).get_result::<bool>(conn)?;
842    /// assert_eq!(res, false);
843    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_json_object())).get_result::<bool>(conn)?;
844    /// assert_eq!(res, false);
845    /// #
846    /// #     Ok(())
847    /// # }
848    /// ```
849    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
850    fn is_json_object(self) -> dsl::IsJsonObject<Self> {
851        IsJsonObject::new(self)
852    }
853
854    /// Creates a PostgreSQL `IS NOT JSON OBJECT` expression.
855    /// Requires PostgreSQL>=16
856    ///
857    /// This operator returns true whether an object is not a valid JSON
858    ///
859    /// # Example
860    ///
861    /// ```rust,no_run
862    /// # include!("../../doctest_setup.rs");
863    /// #
864    /// # fn main() {
865    /// #     run_test().unwrap();
866    /// # }
867    /// #
868    /// # fn run_test() -> QueryResult<()> {
869    /// #     use std::collections::Bound;
870    /// #     use diesel::sql_types::Text;
871    /// #
872    /// #     let conn = &mut establish_connection();
873    /// #
874    ///
875    /// let res = diesel::select(("123".into_sql::<Text>().is_not_json_object())).get_result::<bool>(conn)?;
876    /// assert_eq!(res, true);
877    /// let res = diesel::select(("abc".into_sql::<Text>().is_not_json_object())).get_result::<bool>(conn)?;
878    /// assert_eq!(res, true);
879    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_not_json_object())).get_result::<bool>(conn)?;
880    /// assert_eq!(res, false);
881    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_not_json_object())).get_result::<bool>(conn)?;
882    /// assert_eq!(res, true);
883    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_not_json_object())).get_result::<bool>(conn)?;
884    /// assert_eq!(res, true);
885    /// #
886    /// #     Ok(())
887    /// # }
888    /// ```
889    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
890    fn is_not_json_object(self) -> dsl::IsNotJsonObject<Self> {
891        IsNotJsonObject::new(self)
892    }
893
894    /// Creates a PostgreSQL `IS JSON ARRAY` expression.
895    /// Requires PostgreSQL>=16
896    ///
897    /// This operator returns true whether an object is a valid JSON ARRAY
898    ///
899    /// # Example
900    ///
901    /// ```rust,no_run
902    /// # include!("../../doctest_setup.rs");
903    /// #
904    /// # fn main() {
905    /// #     run_test().unwrap();
906    /// # }
907    /// #
908    /// # fn run_test() -> QueryResult<()> {
909    /// #     use std::collections::Bound;
910    /// #     use diesel::sql_types::Text;
911    /// #
912    /// #     let conn = &mut establish_connection();
913    /// #
914    ///
915    /// let res = diesel::select(("123".into_sql::<Text>().is_json_array())).get_result::<bool>(conn)?;
916    /// assert_eq!(res, false);
917    /// let res = diesel::select(("abc".into_sql::<Text>().is_json_array())).get_result::<bool>(conn)?;
918    /// assert_eq!(res, false);
919    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_json_array())).get_result::<bool>(conn)?;
920    /// assert_eq!(res, false);
921    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_json_array())).get_result::<bool>(conn)?;
922    /// assert_eq!(res, true);
923    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_json_array())).get_result::<bool>(conn)?;
924    /// assert_eq!(res, false);
925    /// #
926    /// #     Ok(())
927    /// # }
928    /// ```
929    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
930    fn is_json_array(self) -> dsl::IsJsonArray<Self> {
931        IsJsonArray::new(self)
932    }
933
934    /// Creates a PostgreSQL `IS NOT JSON ARRAY` expression.
935    /// Requires PostgreSQL>=16
936    ///
937    /// This operator returns true whether an object is not a valid JSON ARRAY
938    ///
939    /// # Example
940    ///
941    /// ```rust,no_run
942    /// # include!("../../doctest_setup.rs");
943    /// #
944    /// # fn main() {
945    /// #     run_test().unwrap();
946    /// # }
947    /// #
948    /// # fn run_test() -> QueryResult<()> {
949    /// #     use std::collections::Bound;
950    /// #     use diesel::sql_types::Text;
951    /// #
952    /// #     let conn = &mut establish_connection();
953    /// #
954    ///
955    /// let res = diesel::select(("123".into_sql::<Text>().is_not_json_array())).get_result::<bool>(conn)?;
956    /// assert_eq!(res, true);
957    /// let res = diesel::select(("abc".into_sql::<Text>().is_not_json_array())).get_result::<bool>(conn)?;
958    /// assert_eq!(res, true);
959    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_not_json_array())).get_result::<bool>(conn)?;
960    /// assert_eq!(res, true);
961    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_not_json_array())).get_result::<bool>(conn)?;
962    /// assert_eq!(res, false);
963    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_not_json_array())).get_result::<bool>(conn)?;
964    /// assert_eq!(res, true);
965    /// #
966    /// #     Ok(())
967    /// # }
968    /// ```
969    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
970    fn is_not_json_array(self) -> dsl::IsNotJsonArray<Self> {
971        IsNotJsonArray::new(self)
972    }
973
974    /// Creates a PostgreSQL `IS JSON SCALAR` expression.
975    /// Requires PostgreSQL>=16
976    ///
977    /// This operator returns true whether an object is a valid JSON SCALAR
978    ///
979    /// # Example
980    ///
981    /// ```rust,no_run
982    /// # include!("../../doctest_setup.rs");
983    /// #
984    /// # fn main() {
985    /// #     run_test().unwrap();
986    /// # }
987    /// #
988    /// # fn run_test() -> QueryResult<()> {
989    /// #     use std::collections::Bound;
990    /// #     use diesel::sql_types::{Text, Nullable};
991    /// #     use diesel::dsl::sql;
992    /// #
993    /// #     let conn = &mut establish_connection();
994    /// #
995    ///
996    /// let res = diesel::select(("123".into_sql::<Text>().is_json_scalar())).get_result::<bool>(conn)?;
997    /// assert_eq!(res, true);
998    /// let res = diesel::select(("abc".into_sql::<Text>().is_json_scalar())).get_result::<bool>(conn)?;
999    /// assert_eq!(res, false);
1000    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_json_scalar())).get_result::<bool>(conn)?;
1001    /// assert_eq!(res, false);
1002    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_json_scalar())).get_result::<bool>(conn)?;
1003    /// assert_eq!(res, false);
1004    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_json_scalar())).get_result::<bool>(conn)?;
1005    /// assert_eq!(res, true);
1006    /// let res = diesel::select(sql::<Nullable<Text>>("NULL").is_json_scalar()).get_result::<Option<bool>>(conn)?;
1007    /// assert!(res.is_none());
1008    /// #     Ok(())
1009    /// # }
1010    /// ```
1011    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
1012    fn is_json_scalar(self) -> dsl::IsJsonScalar<Self> {
1013        IsJsonScalar::new(self)
1014    }
1015
1016    /// Creates a PostgreSQL `IS NOT JSON SCALAR` expression.
1017    /// Requires PostgreSQL>=16
1018    ///
1019    /// This operator returns true whether an object is not a valid JSON SCALAR
1020    ///
1021    /// # Example
1022    ///
1023    /// ```rust,no_run
1024    /// # include!("../../doctest_setup.rs");
1025    /// #
1026    /// # fn main() {
1027    /// #     run_test().unwrap();
1028    /// # }
1029    /// #
1030    /// # fn run_test() -> QueryResult<()> {
1031    /// #     use std::collections::Bound;
1032    /// #     use diesel::sql_types::Text;
1033    /// #
1034    /// #     let conn = &mut establish_connection();
1035    /// #
1036    ///
1037    /// let res = diesel::select(("123".into_sql::<Text>().is_not_json_scalar())).get_result::<bool>(conn)?;
1038    /// assert_eq!(res, false);
1039    /// let res = diesel::select(("abc".into_sql::<Text>().is_not_json_scalar())).get_result::<bool>(conn)?;
1040    /// assert_eq!(res, true);
1041    /// let res = diesel::select(("{\"products\": [1,2,3]}".into_sql::<Text>().is_not_json_scalar())).get_result::<bool>(conn)?;
1042    /// assert_eq!(res, true);
1043    /// let res = diesel::select(("[1,2,3]".into_sql::<Text>().is_not_json_scalar())).get_result::<bool>(conn)?;
1044    /// assert_eq!(res, true);
1045    /// let res = diesel::select(("\"abc\"".into_sql::<Text>().is_not_json_scalar())).get_result::<bool>(conn)?;
1046    /// assert_eq!(res, false);
1047    /// #
1048    /// #     Ok(())
1049    /// # }
1050    /// ```
1051    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
1052    fn is_not_json_scalar(self) -> dsl::IsNotJsonScalar<Self> {
1053        IsNotJsonScalar::new(self)
1054    }
1055}
1056
1057impl<T> PgTextExpressionMethods for T
1058where
1059    T: Expression,
1060    T::SqlType: TextOrNullableText,
1061{
1062}
1063
1064impl<T, U> EscapeExpressionMethods for Grouped<ILike<T, U>> {
1065    type TextExpression = ILike<T, U>;
1066
1067    fn escape(self, character: char) -> dsl::Escape<Self> {
1068        Grouped(crate::expression::operators::Escape::new(
1069            self.0,
1070            character.to_string().into_sql::<VarChar>(),
1071        ))
1072    }
1073}
1074
1075impl<T, U> EscapeExpressionMethods for Grouped<NotILike<T, U>> {
1076    type TextExpression = NotILike<T, U>;
1077
1078    fn escape(self, character: char) -> dsl::Escape<Self> {
1079        Grouped(crate::expression::operators::Escape::new(
1080            self.0,
1081            character.to_string().into_sql::<VarChar>(),
1082        ))
1083    }
1084}
1085
1086impl<T, U> EscapeExpressionMethods for Grouped<SimilarTo<T, U>> {
1087    type TextExpression = SimilarTo<T, U>;
1088
1089    fn escape(self, character: char) -> dsl::Escape<Self> {
1090        Grouped(crate::expression::operators::Escape::new(
1091            self.0,
1092            character.to_string().into_sql::<VarChar>(),
1093        ))
1094    }
1095}
1096
1097impl<T, U> EscapeExpressionMethods for Grouped<NotSimilarTo<T, U>> {
1098    type TextExpression = NotSimilarTo<T, U>;
1099
1100    fn escape(self, character: char) -> dsl::Escape<Self> {
1101        Grouped(crate::expression::operators::Escape::new(
1102            self.0,
1103            character.to_string().into_sql::<VarChar>(),
1104        ))
1105    }
1106}
1107
1108/// PostgreSQL specific methods present on range expressions.
1109#[cfg(feature = "postgres_backend")]
1110pub trait PgRangeExpressionMethods: Expression + Sized {
1111    /// Creates a PostgreSQL `@>` expression.
1112    ///
1113    /// This operator returns true whether a range contains an specific element
1114    ///
1115    /// This operator evaluates to true for the following cases:
1116    ///
1117    /// ```text
1118    /// self:   [-----]
1119    /// other:    |
1120    /// ```
1121    ///
1122    /// ```text
1123    /// self:  [----]
1124    /// other: |
1125    /// ```
1126    ///
1127    /// ```text
1128    /// self:  [----]
1129    /// other:      |
1130    /// ```
1131    ///
1132    /// This operator evaluates to false for the following cases:
1133    ///
1134    /// ```text
1135    /// self:   [-----]
1136    /// other:          |
1137    /// ```
1138    ///
1139    /// ```text
1140    /// self:    [----]
1141    /// other: |
1142    /// ```
1143    ///
1144    /// ```text
1145    /// self:  [----)
1146    /// other:      |
1147    /// ```
1148    ///
1149    /// # Example
1150    ///
1151    /// ```rust
1152    /// # include!("../../doctest_setup.rs");
1153    /// #
1154    /// # fn main() {
1155    /// #     run_test().unwrap();
1156    /// # }
1157    /// #
1158    /// # fn run_test() -> QueryResult<()> {
1159    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1160    /// #
1161    /// #     let conn = &mut establish_connection();
1162    /// assert!(diesel::select((1..5).into_sql::<Range<Integer>>().contains(4)).first::<bool>(conn).unwrap());
1163    /// assert!(!diesel::select((1..5).into_sql::<Range<Integer>>().contains(8)).first::<bool>(conn).unwrap());
1164    ///
1165    /// assert!(diesel::select((vec![1..5]).into_sql::<Multirange<Integer>>().contains(4)).first::<bool>(conn).unwrap());
1166    /// assert!(!diesel::select((vec![1..5]).into_sql::<Multirange<Integer>>().contains(8)).first::<bool>(conn).unwrap());
1167    ///
1168    /// #     Ok(())
1169    /// # }
1170    /// ```
1171    fn contains<T>(self, other: T) -> dsl::RangeContains<Self, T>
1172    where
1173        Self::SqlType: RangeOrMultirange,
1174        <Self::SqlType as RangeOrMultirange>::Inner: SqlType + TypedExpressionType,
1175        T: AsExpression<<Self::SqlType as RangeOrMultirange>::Inner>,
1176    {
1177        Grouped(Contains::new(self, other.as_expression()))
1178    }
1179
1180    /// Creates a PostgreSQL `@>` expression.
1181    ///
1182    /// This operator returns true whether a range contains another range
1183    ///
1184    /// This operator evaluates to true for the following cases:
1185    ///
1186    /// ```text
1187    /// self:   [-------]
1188    /// other:     [--]
1189    /// ```
1190    ///
1191    /// ```text
1192    /// self:  [------]
1193    /// other: [------]
1194    /// ```
1195    ///
1196    /// This operator evaluates to false for the following cases:
1197    ///
1198    /// ```text
1199    /// self:   [-----]
1200    /// other:     [----]
1201    /// ```
1202    ///
1203    /// ```text
1204    /// self:    [----]
1205    /// other: [--------]
1206    /// ```
1207    ///
1208    /// ```text
1209    /// self:  [----)
1210    /// other: [----]
1211    /// ```
1212    ///
1213    /// # Example
1214    ///
1215    /// ```rust
1216    /// # include!("../../doctest_setup.rs");
1217    /// #
1218    /// # fn main() {
1219    /// #     run_test().unwrap();
1220    /// # }
1221    /// #
1222    /// # fn run_test() -> QueryResult<()> {
1223    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1224    /// #     let conn = &mut establish_connection();
1225    /// assert!(diesel::select(
1226    ///     (1..5).into_sql::<Range<Integer>>().contains_range(1..5)
1227    ///     ).first::<bool>(conn).unwrap());
1228    /// assert!(!diesel::select(
1229    ///     (1..5).into_sql::<Range<Integer>>().contains_range(3..7)
1230    ///     ).first::<bool>(conn).unwrap());
1231    ///
1232    /// assert!(diesel::select(
1233    ///     vec![1..5].into_sql::<Multirange<Integer>>().contains_range(vec![1..5])
1234    ///     ).first::<bool>(conn).unwrap());
1235    /// assert!(!diesel::select(
1236    ///     vec![1..5].into_sql::<Multirange<Integer>>().contains_range(vec![3..7])
1237    ///     ).first::<bool>(conn).unwrap());
1238    /// #     Ok(())
1239    /// # }
1240    /// ```
1241    fn contains_range<T>(self, other: T) -> dsl::ContainsRange<Self, T>
1242    where
1243        Self::SqlType: SqlType,
1244        T: AsExpression<Self::SqlType>,
1245    {
1246        Grouped(Contains::new(self, other.as_expression()))
1247    }
1248
1249    /// Creates a PostgreSQL `<@` expression.
1250    ///
1251    /// This operator returns true whether a range is contained by another range
1252    ///
1253    /// This operator evaluates to true for the following cases:
1254    ///
1255    /// ```text
1256    /// self:   [-----]
1257    /// other: [-------]
1258    /// ```
1259    ///
1260    /// ```text
1261    /// self:  [----]
1262    /// other: [----]
1263    /// ```
1264    ///
1265    /// This operator evaluates to false for the following cases:
1266    ///
1267    /// ```text
1268    /// self:   [------]
1269    /// other:   [---]
1270    /// ```
1271    ///
1272    /// ```text
1273    /// self:   [----]
1274    /// other: [-----)
1275    /// ```
1276    ///
1277    /// ```text
1278    /// self:  [----]
1279    /// other:   [----]
1280    /// ```
1281    ///
1282    /// # Example
1283    ///
1284    /// ```rust
1285    /// # include!("../../doctest_setup.rs");
1286    /// #
1287    /// # fn main() {
1288    /// #     run_test().unwrap();
1289    /// # }
1290    /// #
1291    /// # fn run_test() -> QueryResult<()> {
1292    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1293    /// #     let conn = &mut establish_connection();
1294    /// assert!(diesel::select(
1295    ///     (1..5).into_sql::<Range<Integer>>().is_contained_by(1..5)
1296    ///     ).first::<bool>(conn).unwrap());
1297    /// assert!(!diesel::select(
1298    ///     (1..5).into_sql::<Range<Integer>>().is_contained_by(3..7)
1299    ///     ).first::<bool>(conn).unwrap());
1300    ///
1301    /// assert!(diesel::select(
1302    ///     vec![1..5].into_sql::<Multirange<Integer>>().is_contained_by(vec![1..5])
1303    ///     ).first::<bool>(conn).unwrap());
1304    /// assert!(!diesel::select(
1305    ///     vec![1..5].into_sql::<Multirange<Integer>>().is_contained_by(vec![3..7])
1306    ///     ).first::<bool>(conn).unwrap());
1307    /// #     Ok(())
1308    /// # }
1309    /// ```
1310    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
1311    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
1312    where
1313        Self::SqlType: SqlType,
1314        T: AsExpression<Self::SqlType>,
1315    {
1316        Grouped(IsContainedBy::new(self, other.as_expression()))
1317    }
1318
1319    /// Creates a PostgreSQL `&&` expression.
1320    ///
1321    /// This operator returns true whether two ranges overlap.
1322    ///
1323    /// This operator evaluates to true for the following cases:
1324    ///
1325    /// ```text
1326    /// self:   [-----]
1327    /// other:    [-----]
1328    /// ```
1329    ///
1330    /// ```text
1331    /// self:     [----]
1332    /// other: [----]
1333    /// ```
1334    ///
1335    /// ```text
1336    /// self:     [----]
1337    /// other:  [-------]
1338    /// ```
1339    ///
1340    /// ```text
1341    /// self:   [----]
1342    /// other:  [----]
1343    /// ```
1344    ///
1345    /// ```text
1346    /// self:   [----]
1347    /// other:  [----)
1348    /// ```
1349    ///
1350    /// This operator evaluates to false for the following cases:
1351    ///
1352    /// ```text
1353    /// self:   [-----]
1354    /// other:          [-----]
1355    /// ```
1356    ///
1357    /// ```text
1358    /// self:       [----]
1359    /// other: [--]
1360    /// ```
1361    ///
1362    /// # Example
1363    ///
1364    /// ```rust
1365    /// # include!("../../doctest_setup.rs");
1366    /// #
1367    /// # fn main() {
1368    /// #     run_test().unwrap();
1369    /// # }
1370    /// #
1371    /// # fn run_test() -> QueryResult<()> {
1372    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1373    /// #     let conn = &mut establish_connection();
1374    /// assert!(diesel::select(
1375    ///     (1..5).into_sql::<Range<Integer>>().overlaps_with(3..7)
1376    ///     ).first::<bool>(conn).unwrap());
1377    /// assert!(!diesel::select(
1378    ///     (1..5).into_sql::<Range<Integer>>().overlaps_with(10..15)
1379    ///     ).first::<bool>(conn).unwrap());
1380    ///
1381    /// assert!(diesel::select(
1382    ///     vec![1..5].into_sql::<Multirange<Integer>>().overlaps_with(vec![3..7])
1383    ///     ).first::<bool>(conn).unwrap());
1384    /// assert!(!diesel::select(
1385    ///     vec![1..5].into_sql::<Multirange<Integer>>().overlaps_with(vec![10..15])
1386    ///     ).first::<bool>(conn).unwrap());
1387    /// #     Ok(())
1388    /// # }
1389    /// ```
1390    fn overlaps_with<T>(self, other: T) -> dsl::OverlapsWith<Self, T>
1391    where
1392        Self::SqlType: SqlType,
1393        T: AsExpression<Self::SqlType>,
1394    {
1395        Grouped(OverlapsWith::new(self, other.as_expression()))
1396    }
1397
1398    /// Creates a PostgreSQL `&<` expression.
1399    ///
1400    /// This operator returns true whether the argument range extend to the right of the current range
1401    ///
1402    /// Postgresql defines "extends" as does not have a lower bound smaller than the lower bound of the
1403    /// self range. That means the right hand side range can overlap parts of the left hand side
1404    /// range or be on the right side of the left hand side range
1405    ///
1406    /// The following constelations evaluate to true:
1407    /// ```text
1408    /// self:   [------)
1409    /// other:    [----)
1410    /// ```
1411    ///
1412    /// ```text
1413    /// self:  [----)
1414    /// other:         [----)
1415    /// ```
1416    ///
1417    /// ```text
1418    /// self:  [------)
1419    /// other:    [------)
1420    /// ```
1421    ///
1422    /// The following constelations evaluate to false:
1423    ///
1424    /// ```text
1425    /// self:             [------]
1426    /// other:    [----]
1427    /// ```
1428    ///
1429    /// ```text
1430    /// self:            [------]
1431    /// other:         [----]
1432    /// ```
1433    ///
1434    /// ```text
1435    /// self:  [------]
1436    /// other: [------)
1437    /// ```
1438    ///
1439    /// # Example
1440    ///
1441    /// ```rust
1442    /// # include!("../../doctest_setup.rs");
1443    /// #
1444    /// # fn main() {
1445    /// #     run_test().unwrap();
1446    /// # }
1447    /// #
1448    /// # fn run_test() -> QueryResult<()> {
1449    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1450    /// #     let conn = &mut establish_connection();
1451    /// #
1452    /// assert!(diesel::select(
1453    ///     (1..20).into_sql::<Range<Integer>>().range_extends_right_to(18..20)
1454    ///     ).first::<bool>(conn).unwrap());
1455    /// assert!(diesel::select(
1456    ///     (1..20).into_sql::<Range<Integer>>().range_extends_right_to(25..30)
1457    ///     ).first::<bool>(conn).unwrap());
1458    /// assert!(!diesel::select(
1459    ///     (1..20).into_sql::<Range<Integer>>().range_extends_right_to(-10..0)
1460    ///     ).first::<bool>(conn).unwrap());
1461    ///
1462    /// assert!(diesel::select(
1463    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_right_to(vec![18..20])
1464    ///     ).first::<bool>(conn).unwrap());
1465    /// assert!(diesel::select(
1466    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_right_to(vec![25..30])
1467    ///     ).first::<bool>(conn).unwrap());
1468    /// assert!(!diesel::select(
1469    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_right_to(vec![-10..0])
1470    ///     ).first::<bool>(conn).unwrap());
1471    /// #     Ok(())
1472    /// # }
1473    /// ```
1474    fn range_extends_right_to<T>(self, other: T) -> dsl::RangeExtendsRightTo<Self, T>
1475    where
1476        Self::SqlType: SqlType,
1477        T: AsExpression<Self::SqlType>,
1478    {
1479        Grouped(ExtendsRightTo::new(self, other.as_expression()))
1480    }
1481
1482    /// Creates a PostgreSQL `&>` expression.
1483    ///
1484    /// This operator returns true whether a range does extend to the left of another
1485    ///
1486    /// Postgresql defines "extends" as does not have a upper bound greater than the upper bound of the
1487    /// self range. That means the right hand side range can overlap parts of the left hand side
1488    /// range or be on the left side of the left hand side range
1489    ///
1490    /// The following constelations evaluate to true:
1491    /// ```text
1492    /// self:        [------)
1493    /// other:    [----)
1494    /// ```
1495    ///
1496    /// ```text
1497    /// self:          [----)
1498    /// other: [----)
1499    /// ```
1500    ///
1501    /// ```text
1502    /// self:  [------)
1503    /// other:        [------)
1504    /// ```
1505    ///
1506    /// The following constelations evaluate to false:
1507    ///
1508    /// ```text
1509    /// self:   [--------]
1510    /// other:    [----]
1511    /// ```
1512    ///
1513    /// ```text
1514    /// self:  [------]
1515    /// other:          [----]
1516    /// ```
1517    ///
1518    /// ```text
1519    /// self:  [------]
1520    /// other: (------]
1521    /// ```
1522    ///
1523    /// # Example
1524    ///
1525    /// ```rust
1526    /// # include!("../../doctest_setup.rs");
1527    /// #
1528    /// # fn main() {
1529    /// #     run_test().unwrap();
1530    /// # }
1531    /// #
1532    /// # fn run_test() -> QueryResult<()> {
1533    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1534    /// #     let conn = &mut establish_connection();
1535    /// #
1536    /// assert!(diesel::select(
1537    ///     (1..20).into_sql::<Range<Integer>>().range_extends_left_to(-10..5)
1538    ///     ).first::<bool>(conn).unwrap());
1539    /// assert!(diesel::select(
1540    ///     (1..20).into_sql::<Range<Integer>>().range_extends_left_to(-10..-5)
1541    ///     ).first::<bool>(conn).unwrap());
1542    /// assert!(!diesel::select(
1543    ///     (1..20).into_sql::<Range<Integer>>().range_extends_left_to(25..30)
1544    ///     ).first::<bool>(conn).unwrap());
1545    ///
1546    /// assert!(diesel::select(
1547    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_left_to(vec![-10..5])
1548    ///     ).first::<bool>(conn).unwrap());
1549    /// assert!(diesel::select(
1550    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_left_to(vec![-10..-5])
1551    ///     ).first::<bool>(conn).unwrap());
1552    /// assert!(!diesel::select(
1553    ///     vec![1..20].into_sql::<Multirange<Integer>>().range_extends_left_to(vec![25..30])
1554    ///     ).first::<bool>(conn).unwrap());
1555    /// #     Ok(())
1556    /// # }
1557    /// ```
1558    fn range_extends_left_to<T>(self, other: T) -> dsl::RangeExtendsLeftTo<Self, T>
1559    where
1560        Self::SqlType: SqlType,
1561        T: AsExpression<Self::SqlType>,
1562    {
1563        Grouped(ExtendsLeftTo::new(self, other.as_expression()))
1564    }
1565
1566    /// Creates a PostgreSQL `<<` expression.
1567    ///
1568    /// Is the first range strictly left of the second?
1569    ///
1570    /// The following constelations evaluate to true:
1571    /// ```text
1572    /// self:   [------)
1573    /// other:            [----)
1574    /// ```
1575    ///
1576    /// ```text
1577    /// self:  [----)
1578    /// other:      [----)
1579    /// ```
1580    ///
1581    /// The following constelations evaluate to false:
1582    ///
1583    /// ```text
1584    /// self:             [------]
1585    /// other:    [----]
1586    /// ```
1587    ///
1588    /// ```text
1589    /// self:     [------]
1590    /// other:         [----]
1591    /// ```
1592    ///
1593    /// ```text
1594    /// self:  [------]
1595    /// other:        [------)
1596    /// ```
1597    ///
1598    /// # Example
1599    ///
1600    /// ```rust
1601    /// # include!("../../doctest_setup.rs");
1602    /// #
1603    /// # table! {
1604    /// #     posts {
1605    /// #         id -> Integer,
1606    /// #         versions -> Range<Integer>,
1607    /// #     }
1608    /// # }
1609    /// #
1610    /// # fn main() {
1611    /// #     run_test().unwrap();
1612    /// # }
1613    /// #
1614    /// # fn run_test() -> QueryResult<()> {
1615    /// #     use self::posts::dsl::*;
1616    /// #     use std::collections::Bound;
1617    /// #     let conn = &mut establish_connection();
1618    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
1619    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, versions INT4RANGE NOT NULL)").execute(conn).unwrap();
1620    /// #
1621    /// diesel::insert_into(posts)
1622    ///     .values(&vec![
1623    ///         (versions.eq((Bound::Included(1), Bound::Included(2)))),
1624    ///         (versions.eq((Bound::Included(3), Bound::Included(4)))),
1625    ///         (versions.eq((Bound::Included(5), Bound::Included(6))))
1626    ///     ])
1627    ///     .execute(conn)?;
1628    ///
1629    /// let data = posts.select(id)
1630    ///     .filter(versions.lesser_than((Bound::Included(1), Bound::Included(4))))
1631    ///     .load::<i32>(conn)?;
1632    /// assert!(data.is_empty());
1633    ///
1634    /// let data = posts.select(id)
1635    ///     .filter(versions.lesser_than((Bound::Included(5), Bound::Included(8))))
1636    ///     .load::<i32>(conn)?;
1637    /// assert_eq!(vec![1, 2], data);
1638    /// #     Ok(())
1639    /// # }
1640    /// ```
1641    fn lesser_than<T>(self, other: T) -> dsl::LesserThanRange<Self, T>
1642    where
1643        Self::SqlType: SqlType,
1644        T: AsExpression<Self::SqlType>,
1645    {
1646        Grouped(IsContainedByNet::new(self, other.as_expression()))
1647    }
1648
1649    /// Creates a PostgreSQL `>>` expression.
1650    ///
1651    /// Is the first range strictly right of the second?
1652    ///
1653    /// The following constelations evaluate to true:
1654    /// ```text
1655    /// self:          [------)
1656    /// other: [----)
1657    /// ```
1658    ///
1659    /// ```text
1660    /// self:        [----)
1661    /// other:  [----)
1662    /// ```
1663    ///
1664    /// The following constelations evaluate to false:
1665    ///
1666    /// ```text
1667    /// self:  [------]
1668    /// other:          [----]
1669    /// ```
1670    ///
1671    /// ```text
1672    /// self:     [------]
1673    /// other:         [----]
1674    /// ```
1675    ///
1676    /// ```text
1677    /// self:         [------]
1678    /// other: [------]
1679    /// ```
1680    ///
1681    /// # Example
1682    ///
1683    /// ```rust
1684    /// # include!("../../doctest_setup.rs");
1685    /// #
1686    /// # table! {
1687    /// #     posts {
1688    /// #         id -> Integer,
1689    /// #         versions -> Range<Integer>,
1690    /// #     }
1691    /// # }
1692    /// #
1693    /// # fn main() {
1694    /// #     run_test().unwrap();
1695    /// # }
1696    /// #
1697    /// # fn run_test() -> QueryResult<()> {
1698    /// #     use self::posts::dsl::*;
1699    /// #     use std::collections::Bound;
1700    /// #     let conn = &mut establish_connection();
1701    /// #     diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
1702    /// #     diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, versions INT4RANGE NOT NULL)").execute(conn).unwrap();
1703    /// #
1704    /// diesel::insert_into(posts)
1705    ///     .values(&vec![
1706    ///         (versions.eq((Bound::Included(1), Bound::Included(2)))),
1707    ///         (versions.eq((Bound::Included(3), Bound::Included(4)))),
1708    ///         (versions.eq((Bound::Included(5), Bound::Included(6))))
1709    ///     ])
1710    ///     .execute(conn)?;
1711    ///
1712    /// let data = posts.select(id)
1713    ///     .filter(versions.greater_than((Bound::Included(1), Bound::Included(2))))
1714    ///     .load::<i32>(conn)?;
1715    /// assert_eq!(vec![2, 3], data);
1716    ///
1717    /// let data = posts.select(id)
1718    ///     .filter(versions.greater_than((Bound::Included(5), Bound::Included(8))))
1719    ///     .load::<i32>(conn)?;
1720    /// assert!(data.is_empty());
1721    /// #     Ok(())
1722    /// # }
1723    /// ```
1724    fn greater_than<T>(self, other: T) -> dsl::GreaterThanRange<Self, T>
1725    where
1726        Self::SqlType: SqlType,
1727        T: AsExpression<Self::SqlType>,
1728    {
1729        Grouped(ContainsNet::new(self, other.as_expression()))
1730    }
1731
1732    /// Creates a PostgreSQL ` -|- ` expression.
1733    ///
1734    /// This operator evaluates to true if the two ranges are adjacent
1735    ///
1736    /// The following constelations evaluate to true:
1737    /// ```text
1738    /// self:   [------)
1739    /// other:         [----)
1740    /// ```
1741    ///
1742    /// ```text
1743    /// self:       [----)
1744    /// other: [----)
1745    /// ```
1746    ///
1747    /// ```text
1748    /// self:        [----)
1749    /// other: [----]
1750    /// ```
1751    ///
1752    /// ```text
1753    /// self:  [----]
1754    /// other:       [----]
1755    /// ```
1756    ///
1757    /// The following constelations evaluate to false:
1758    ///
1759    /// ```text
1760    /// self:        [------]
1761    /// other:    [----]
1762    /// ```
1763    ///
1764    /// ```text
1765    /// self:     [------]
1766    /// other:         [----]
1767    /// ```
1768    ///
1769    /// ```text
1770    /// self:  [------]
1771    /// other:        [------]
1772    /// ```
1773    ///
1774    /// ```text
1775    /// self:  [------]
1776    /// other:           [------]
1777    /// ```
1778    ///
1779    /// # Example
1780    ///
1781    /// ```rust
1782    /// # include!("../../doctest_setup.rs");
1783    /// #
1784    /// # fn main() {
1785    /// #     run_test().unwrap();
1786    /// # }
1787    /// #
1788    /// # fn run_test() -> QueryResult<()> {
1789    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1790    /// #     let conn = &mut establish_connection();
1791    /// assert!(diesel::select(
1792    ///     (1..2).into_sql::<Range<Integer>>().range_adjacent(2..=6)
1793    ///     ).first::<bool>(conn).unwrap());
1794    /// assert!(!diesel::select(
1795    ///     (4..7).into_sql::<Range<Integer>>().range_adjacent(2..=6)
1796    ///     ).first::<bool>(conn).unwrap());
1797    ///
1798    /// assert!(diesel::select(
1799    ///     vec![1..2].into_sql::<Multirange<Integer>>().range_adjacent(vec![2..=6])
1800    ///     ).first::<bool>(conn).unwrap());
1801    /// assert!(!diesel::select(
1802    ///     vec![4..7].into_sql::<Multirange<Integer>>().range_adjacent(vec![2..=6])
1803    ///     ).first::<bool>(conn).unwrap());
1804    /// #     Ok(())
1805    /// # }
1806    /// ```
1807    fn range_adjacent<T>(self, other: T) -> dsl::RangeAdjacent<Self, T>
1808    where
1809        Self::SqlType: SqlType,
1810        T: AsExpression<Self::SqlType>,
1811    {
1812        Grouped(RangeAdjacent::new(self, other.as_expression()))
1813    }
1814
1815    /// Creates a PostgreSQL ` + ` expression.
1816    ///
1817    /// This operator unions two ranges and returns the union.
1818    ///
1819    /// ```text
1820    /// self:   [------)
1821    /// other:      [----)
1822    /// result: [--------)
1823    /// ```
1824    ///
1825    /// ```text
1826    /// self:          [----)
1827    /// other: [----)
1828    /// result: error
1829    /// ```
1830    ///
1831    /// ```text
1832    /// self:      [----)
1833    /// other: [----]
1834    /// result [--------)
1835    /// ```
1836    ///
1837    /// # Example
1838    ///
1839    /// ```rust
1840    /// # include!("../../doctest_setup.rs");
1841    /// #
1842    /// # fn main() {
1843    /// #     run_test().unwrap();
1844    /// # }
1845    /// #
1846    /// # fn run_test() -> QueryResult<()> {
1847    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1848    /// #     let conn = &mut establish_connection();
1849    /// assert!(diesel::select(
1850    ///     (1..=2).into_sql::<Range<Integer>>().union_range(2..=6).eq(1..=6)
1851    ///     ).first::<bool>(conn).unwrap());
1852    ///
1853    /// assert!(diesel::select(
1854    ///     vec![1..=2].into_sql::<Multirange<Integer>>().union_range(vec![1..=6]).eq(vec![1..=6])
1855    ///     ).first::<bool>(conn).unwrap());
1856    /// #     Ok(())
1857    /// # }
1858    /// ```
1859    fn union_range<T>(self, other: T) -> dsl::UnionRange<Self, T>
1860    where
1861        Self::SqlType: SqlType,
1862        T: AsExpression<Self::SqlType>,
1863    {
1864        Grouped(UnionsRange::new(self, other.as_expression()))
1865    }
1866
1867    /// Creates a PostgreSQL ` - ` expression.
1868    ///
1869    /// This operator takes two ranges and returns the difference.
1870    ///
1871    /// The second range must not be contained in the first in such a way that the
1872    /// difference would not be a single range.
1873    ///
1874    /// ```text
1875    /// self:   [------)
1876    /// other:      [----)
1877    /// result: [---)
1878    /// ```
1879    ///
1880    /// ```text
1881    /// self:      [----)
1882    /// other:  [----)
1883    /// result:      [--)
1884    /// ```
1885    ///
1886    /// ```text
1887    /// self:      [--------)
1888    /// other:       [----]
1889    /// result: error
1890    /// ```
1891    ///
1892    /// # Example
1893    ///
1894    /// ```rust
1895    /// # include!("../../doctest_setup.rs");
1896    /// #
1897    /// # fn main() {
1898    /// #     run_test().unwrap();
1899    /// # }
1900    /// #
1901    /// # fn run_test() -> QueryResult<()> {
1902    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1903    /// #     let conn = &mut establish_connection();
1904    /// assert!(diesel::select(
1905    ///     (1..=8).into_sql::<Range<Integer>>().difference_range(3..=8).eq(1..3)
1906    ///     ).first::<bool>(conn).unwrap());
1907    ///
1908    /// assert!(diesel::select(
1909    ///     vec![1..=8].into_sql::<Multirange<Integer>>().difference_range(vec![3..=8]).eq(vec![1..3])
1910    ///     ).first::<bool>(conn).unwrap());
1911    /// #     Ok(())
1912    /// # }
1913    /// ```
1914    fn difference_range<T>(self, other: T) -> dsl::Difference<Self, T>
1915    where
1916        Self::SqlType: SqlType,
1917        T: AsExpression<Self::SqlType>,
1918    {
1919        Grouped(DifferenceRange::new(self, other.as_expression()))
1920    }
1921
1922    /// Creates a PostgreSQL ` * ` expression.
1923    ///
1924    /// This operator takes two ranges and returns the intersection.
1925    ///
1926    /// ```text
1927    /// self:   [------)
1928    /// other:      [----)
1929    /// result:     [--)
1930    /// ```
1931    ///
1932    /// ```text
1933    /// self:      [----)
1934    /// other:  [----)
1935    /// result:    [-)
1936    /// ```
1937    ///
1938    /// ```text
1939    /// self:    [--------)
1940    /// other:     [----]
1941    /// result:    [----]
1942    /// ```
1943    ///
1944    /// ```text
1945    /// self:    [--------)
1946    /// other:               [----]
1947    /// result: empty range
1948    /// ```
1949    ///
1950    /// # Example
1951    ///
1952    /// ```rust
1953    /// # include!("../../doctest_setup.rs");
1954    /// #
1955    /// # fn main() {
1956    /// #     run_test().unwrap();
1957    /// # }
1958    /// #
1959    /// # fn run_test() -> QueryResult<()> {
1960    /// #     use diesel::sql_types::{Integer, Range, Multirange};
1961    /// #     let conn = &mut establish_connection();
1962    /// assert!(diesel::select(
1963    ///     (1..=8).into_sql::<Range<Integer>>().intersection_range(3..=8).eq(3..=8)
1964    ///     ).first::<bool>(conn).unwrap());
1965    ///
1966    /// assert!(diesel::select(
1967    ///     vec![1..=8].into_sql::<Multirange<Integer>>().intersection_range(vec![3..=8]).eq(vec![3..=8])
1968    ///     ).first::<bool>(conn).unwrap());
1969    /// #     Ok(())
1970    /// # }
1971    /// ```
1972    fn intersection_range<T>(self, other: T) -> dsl::Intersection<Self, T>
1973    where
1974        Self::SqlType: SqlType,
1975        T: AsExpression<Self::SqlType>,
1976    {
1977        Grouped(IntersectionRange::new(self, other.as_expression()))
1978    }
1979}
1980
1981impl<T> PgRangeExpressionMethods for T
1982where
1983    T: Expression,
1984    T::SqlType: MultirangeOrRangeMaybeNullable,
1985{
1986}
1987
1988/// PostgreSQL specific methods present between CIDR/INET expressions
1989#[cfg(feature = "postgres_backend")]
1990pub trait PgNetExpressionMethods: Expression + Sized {
1991    /// Creates a PostgreSQL `>>` expression.
1992    ///
1993    /// This operator returns whether a subnet strictly contains another subnet or address.
1994    ///
1995    /// # Example
1996    ///
1997    /// ```rust
1998    /// # include!("../../doctest_setup.rs");
1999    /// #
2000    /// # table! {
2001    /// #     hosts {
2002    /// #         id -> Integer,
2003    /// #         address -> Inet,
2004    /// #     }
2005    /// # }
2006    /// #
2007    /// # fn main() {
2008    /// #     run_test().unwrap();
2009    /// # }
2010    /// #
2011    /// # #[cfg(feature = "ipnetwork")]
2012    /// # fn run_test() -> QueryResult<()> {
2013    /// #     use self::hosts::dsl::*;
2014    /// #     use ipnetwork::IpNetwork;
2015    /// #     use std::str::FromStr;
2016    /// #     let conn = &mut establish_connection();
2017    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2018    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2019    /// diesel::insert_into(hosts)
2020    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
2021    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
2022    ///     .execute(conn)?;
2023    ///
2024    /// let my_hosts = hosts.select(id)
2025    ///     .filter(address.contains(IpNetwork::from_str("10.0.2.5").unwrap()))
2026    ///     .load::<i32>(conn)?;
2027    /// assert_eq!(vec![1, 2], my_hosts);
2028    ///
2029    /// let my_hosts = hosts.select(id)
2030    ///     .filter(address.contains(IpNetwork::from_str("10.0.2.5/24").unwrap()))
2031    ///     .load::<i32>(conn)?;
2032    /// assert_eq!(vec![2], my_hosts);
2033    ///
2034    /// let my_hosts = hosts.select(id)
2035    ///     .filter(address.contains(IpNetwork::from_str("10.0.3.31").unwrap()))
2036    ///     .load::<i32>(conn)?;
2037    /// assert_eq!(vec![2], my_hosts);
2038    /// #     Ok(())
2039    /// # }
2040    /// #
2041    /// # #[cfg(not(feature = "ipnetwork"))]
2042    /// # fn run_test() -> QueryResult<()> {
2043    /// #     Ok(())
2044    /// # }
2045    /// ```
2046    fn contains<T>(self, other: T) -> dsl::ContainsNet<Self, T>
2047    where
2048        T: AsExpression<Inet>,
2049    {
2050        Grouped(ContainsNet::new(self, other.as_expression()))
2051    }
2052
2053    /// Creates a PostgreSQL `>>=` expression.
2054    ///
2055    /// This operator returns whether a subnet contains or is equal to another subnet.
2056    ///
2057    /// # Example
2058    ///
2059    /// ```rust
2060    /// # include!("../../doctest_setup.rs");
2061    /// #
2062    /// # table! {
2063    /// #     hosts {
2064    /// #         id -> Integer,
2065    /// #         address -> Inet,
2066    /// #     }
2067    /// # }
2068    /// #
2069    /// # fn main() {
2070    /// #     run_test().unwrap();
2071    /// # }
2072    /// #
2073    /// # #[cfg(feature = "ipnetwork")]
2074    /// # fn run_test() -> QueryResult<()> {
2075    /// #     use self::hosts::dsl::*;
2076    /// #     use ipnetwork::IpNetwork;
2077    /// #     use std::str::FromStr;
2078    /// #     let conn = &mut establish_connection();
2079    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2080    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2081    /// diesel::insert_into(hosts)
2082    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
2083    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
2084    ///     .execute(conn)?;
2085    ///
2086    /// let my_hosts = hosts.select(id)
2087    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.2.5").unwrap()))
2088    ///     .load::<i32>(conn)?;
2089    /// assert_eq!(vec![1, 2], my_hosts);
2090    ///
2091    /// let my_hosts = hosts.select(id)
2092    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.2.5/24").unwrap()))
2093    ///     .load::<i32>(conn)?;
2094    /// assert_eq!(vec![1, 2], my_hosts);
2095    ///
2096    /// let my_hosts = hosts.select(id)
2097    ///     .filter(address.contains_or_eq(IpNetwork::from_str("10.0.3.31").unwrap()))
2098    ///     .load::<i32>(conn)?;
2099    /// assert_eq!(vec![2], my_hosts);
2100    /// #     Ok(())
2101    /// # }
2102    /// #
2103    /// # #[cfg(not(feature = "ipnetwork"))]
2104    /// # fn run_test() -> QueryResult<()> {
2105    /// #     Ok(())
2106    /// # }
2107    /// ```
2108    fn contains_or_eq<T>(self, other: T) -> dsl::ContainsNetLoose<Self, T>
2109    where
2110        T: AsExpression<Inet>,
2111    {
2112        Grouped(ContainsNetLoose::new(self, other.as_expression()))
2113    }
2114
2115    /// Creates a PostgreSQL `<<` expression.
2116    ///
2117    /// This operator returns whether a subnet or address is strictly contained by another subnet.
2118    ///
2119    /// # Example
2120    ///
2121    /// ```rust
2122    /// # include!("../../doctest_setup.rs");
2123    /// #
2124    /// # table! {
2125    /// #     hosts {
2126    /// #         id -> Integer,
2127    /// #         address -> Inet,
2128    /// #     }
2129    /// # }
2130    /// #
2131    /// # fn main() {
2132    /// #     run_test().unwrap();
2133    /// # }
2134    /// #
2135    /// # #[cfg(feature = "ipnetwork")]
2136    /// # fn run_test() -> QueryResult<()> {
2137    /// #     use self::hosts::dsl::*;
2138    /// #     use ipnetwork::IpNetwork;
2139    /// #     use std::str::FromStr;
2140    /// #     let conn = &mut establish_connection();
2141    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2142    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2143    /// diesel::insert_into(hosts)
2144    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
2145    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
2146    ///     .execute(conn)?;
2147    ///
2148    /// let my_hosts = hosts.select(id)
2149    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.2.5/24").unwrap()))
2150    ///     .load::<i32>(conn)?;
2151    /// assert_eq!(my_hosts.len(), 0);
2152    ///
2153    /// let my_hosts = hosts.select(id)
2154    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.3.31/23").unwrap()))
2155    ///     .load::<i32>(conn)?;
2156    /// assert_eq!(vec![1], my_hosts);
2157    ///
2158    /// let my_hosts = hosts.select(id)
2159    ///     .filter(address.is_contained_by(IpNetwork::from_str("10.0.3.31/22").unwrap()))
2160    ///     .load::<i32>(conn)?;
2161    /// assert_eq!(vec![1, 2], my_hosts);
2162    /// #     Ok(())
2163    /// # }
2164    /// #
2165    /// # #[cfg(not(feature = "ipnetwork"))]
2166    /// # fn run_test() -> QueryResult<()> {
2167    /// #     Ok(())
2168    /// # }
2169    /// ```
2170    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
2171    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedByNet<Self, T>
2172    where
2173        T: AsExpression<Inet>,
2174    {
2175        Grouped(IsContainedByNet::new(self, other.as_expression()))
2176    }
2177
2178    /// Creates a PostgreSQL `>>=` expression.
2179    ///
2180    /// This operator returns whether a subnet is contained by or equal to another subnet.
2181    ///
2182    /// # Example
2183    ///
2184    /// ```rust
2185    /// # include!("../../doctest_setup.rs");
2186    /// #
2187    /// # table! {
2188    /// #     hosts {
2189    /// #         id -> Integer,
2190    /// #         address -> Inet,
2191    /// #     }
2192    /// # }
2193    /// #
2194    /// # fn main() {
2195    /// #     run_test().unwrap();
2196    /// # }
2197    /// #
2198    /// # #[cfg(feature = "ipnetwork")]
2199    /// # fn run_test() -> QueryResult<()> {
2200    /// #     use self::hosts::dsl::*;
2201    /// #     use ipnetwork::IpNetwork;
2202    /// #     use std::str::FromStr;
2203    /// #     let conn = &mut establish_connection();
2204    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2205    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2206    /// diesel::insert_into(hosts)
2207    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
2208    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
2209    ///     .execute(conn)?;
2210    ///
2211    /// let my_hosts = hosts.select(id)
2212    ///     .filter(address.is_contained_by_or_eq(IpNetwork::from_str("10.0.2.5/24").unwrap()))
2213    ///     .load::<i32>(conn)?;
2214    /// assert_eq!(vec![1], my_hosts);
2215    ///
2216    /// let my_hosts = hosts.select(id)
2217    ///     .filter(address.is_contained_by_or_eq(IpNetwork::from_str("10.0.3.31/23").unwrap()))
2218    ///     .load::<i32>(conn)?;
2219    /// assert_eq!(vec![1, 2], my_hosts);
2220    /// #     Ok(())
2221    /// # }
2222    /// #
2223    /// # #[cfg(not(feature = "ipnetwork"))]
2224    /// # fn run_test() -> QueryResult<()> {
2225    /// #     Ok(())
2226    /// # }
2227    /// ```
2228    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
2229    fn is_contained_by_or_eq<T>(self, other: T) -> dsl::IsContainedByNetLoose<Self, T>
2230    where
2231        T: AsExpression<Inet>,
2232    {
2233        Grouped(IsContainedByNetLoose::new(self, other.as_expression()))
2234    }
2235
2236    /// Creates a PostgreSQL `&&` expression.
2237    ///
2238    /// This operator returns whether a subnet contains or is contained by another subnet.
2239    ///
2240    /// # Example
2241    ///
2242    /// ```rust
2243    /// # include!("../../doctest_setup.rs");
2244    /// #
2245    /// # table! {
2246    /// #     hosts {
2247    /// #         id -> Integer,
2248    /// #         address -> Inet,
2249    /// #     }
2250    /// # }
2251    /// #
2252    /// # fn main() {
2253    /// #     run_test().unwrap();
2254    /// # }
2255    /// #
2256    /// # #[cfg(feature = "ipnetwork")]
2257    /// # fn run_test() -> QueryResult<()> {
2258    /// #     use self::hosts::dsl::*;
2259    /// #     use ipnetwork::IpNetwork;
2260    /// #     use std::str::FromStr;
2261    /// #     let conn = &mut establish_connection();
2262    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2263    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2264    /// diesel::insert_into(hosts)
2265    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3/24").unwrap()),
2266    ///                  address.eq(IpNetwork::from_str("10.0.3.4/23").unwrap())])
2267    ///     .execute(conn)?;
2268    ///
2269    /// let my_hosts = hosts.select(id)
2270    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.2.5/24").unwrap()))
2271    ///     .load::<i32>(conn)?;
2272    /// assert_eq!(vec![1, 2], my_hosts);
2273    ///
2274    /// let my_hosts = hosts.select(id)
2275    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.3.31/24").unwrap()))
2276    ///     .load::<i32>(conn)?;
2277    /// assert_eq!(vec![2], my_hosts);
2278    ///
2279    /// let my_hosts = hosts.select(id)
2280    ///     .filter(address.overlaps_with(IpNetwork::from_str("10.0.3.31/23").unwrap()))
2281    ///     .load::<i32>(conn)?;
2282    /// assert_eq!(vec![1, 2], my_hosts);
2283    /// #     Ok(())
2284    /// # }
2285    /// #
2286    /// # #[cfg(not(feature = "ipnetwork"))]
2287    /// # fn run_test() -> QueryResult<()> {
2288    /// #     Ok(())
2289    /// # }
2290    /// ```
2291    fn overlaps_with<T>(self, other: T) -> dsl::OverlapsWithNet<Self, T>
2292    where
2293        T: AsExpression<Inet>,
2294    {
2295        Grouped(OverlapsWith::new(self, other.as_expression()))
2296    }
2297
2298    /// Creates a PostgreSQL `&` expression.
2299    ///
2300    /// This operator computes the bitwise AND between two network addresses.
2301    ///
2302    /// # Example
2303    ///
2304    /// ```rust
2305    /// # include!("../../doctest_setup.rs");
2306    /// #
2307    /// # table! {
2308    /// #     hosts {
2309    /// #         id -> Integer,
2310    /// #         address -> Inet,
2311    /// #     }
2312    /// # }
2313    /// #
2314    /// # fn main() {
2315    /// #     run_test().unwrap();
2316    /// # }
2317    /// #
2318    /// # #[cfg(feature = "ipnetwork")]
2319    /// # fn run_test() -> QueryResult<()> {
2320    /// #     use self::hosts::dsl::*;
2321    /// #     use ipnetwork::IpNetwork;
2322    /// #     use std::str::FromStr;
2323    /// #     let conn = &mut establish_connection();
2324    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2325    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2326    /// diesel::insert_into(hosts)
2327    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3").unwrap())])
2328    ///     .execute(conn)?;
2329    ///
2330    /// let addr = hosts
2331    ///     .select(address.and(IpNetwork::from_str("0.0.0.255").unwrap()))
2332    ///     .first::<IpNetwork>(conn)?;
2333    /// assert_eq!(addr, IpNetwork::from_str("0.0.0.3").unwrap());
2334    /// #     Ok(())
2335    /// # }
2336    /// #
2337    /// # #[cfg(not(feature = "ipnetwork"))]
2338    /// # fn run_test() -> QueryResult<()> {
2339    /// #     Ok(())
2340    /// # }
2341    /// ```
2342    fn and<T>(self, other: T) -> dsl::AndNet<Self, T>
2343    where
2344        T: AsExpression<Inet>,
2345    {
2346        Grouped(AndNet::new(self, other.as_expression()))
2347    }
2348
2349    /// Creates a PostgreSQL `|` expression.
2350    ///
2351    /// This operator computes the bitwise OR between two network addresses.
2352    ///
2353    /// # Example
2354    ///
2355    /// ```rust
2356    /// # include!("../../doctest_setup.rs");
2357    /// #
2358    /// # table! {
2359    /// #     hosts {
2360    /// #         id -> Integer,
2361    /// #         address -> Inet,
2362    /// #     }
2363    /// # }
2364    /// #
2365    /// # fn main() {
2366    /// #     run_test().unwrap();
2367    /// # }
2368    /// #
2369    /// # #[cfg(feature = "ipnetwork")]
2370    /// # fn run_test() -> QueryResult<()> {
2371    /// #     use self::hosts::dsl::*;
2372    /// #     use ipnetwork::IpNetwork;
2373    /// #     use std::str::FromStr;
2374    /// #     let conn = &mut establish_connection();
2375    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2376    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2377    /// diesel::insert_into(hosts)
2378    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.3").unwrap())])
2379    ///     .execute(conn)?;
2380    ///
2381    /// let addr = hosts
2382    ///     .select(address.or(IpNetwork::from_str("0.0.0.255").unwrap()))
2383    ///     .first::<IpNetwork>(conn)?;
2384    /// assert_eq!(addr, IpNetwork::from_str("10.0.2.255").unwrap());
2385    /// #     Ok(())
2386    /// # }
2387    /// #
2388    /// # #[cfg(not(feature = "ipnetwork"))]
2389    /// # fn run_test() -> QueryResult<()> {
2390    /// #     Ok(())
2391    /// # }
2392    /// ```
2393    fn or<T>(self, other: T) -> dsl::OrNet<Self, T>
2394    where
2395        T: AsExpression<Inet>,
2396    {
2397        Grouped(OrNet::new(self, other.as_expression()))
2398    }
2399
2400    /// Creates a PostgreSQL `-` expression.
2401    ///
2402    /// This operator subtracts an address from an address to compute the distance between the two
2403    ///
2404    /// # Example
2405    ///
2406    /// ```rust
2407    /// # include!("../../doctest_setup.rs");
2408    /// #
2409    /// # table! {
2410    /// #     hosts {
2411    /// #         id -> Integer,
2412    /// #         address -> Inet,
2413    /// #     }
2414    /// # }
2415    /// #
2416    /// # fn main() {
2417    /// #     run_test().unwrap();
2418    /// # }
2419    /// #
2420    /// # #[cfg(feature = "ipnetwork")]
2421    /// # fn run_test() -> QueryResult<()> {
2422    /// #     use self::hosts::dsl::*;
2423    /// #     use ipnetwork::IpNetwork;
2424    /// #     use std::str::FromStr;
2425    /// #     let conn = &mut establish_connection();
2426    /// #     diesel::sql_query("DROP TABLE IF EXISTS hosts").execute(conn).unwrap();
2427    /// #     diesel::sql_query("CREATE TABLE hosts (id SERIAL PRIMARY KEY, address INET NOT NULL)").execute(conn).unwrap();
2428    /// diesel::insert_into(hosts)
2429    ///     .values(vec![address.eq(IpNetwork::from_str("10.0.2.53").unwrap())])
2430    ///     .execute(conn)?;
2431    ///
2432    /// let offset = hosts
2433    ///     .select(address.diff(IpNetwork::from_str("10.0.2.42").unwrap()))
2434    ///     .first::<i64>(conn)?;
2435    /// assert_eq!(offset, 11);
2436    /// #     Ok(())
2437    /// # }
2438    /// #
2439    /// # #[cfg(not(feature = "ipnetwork"))]
2440    /// # fn run_test() -> QueryResult<()> {
2441    /// #     Ok(())
2442    /// # }
2443    /// ```
2444    fn diff<T>(self, other: T) -> dsl::DifferenceNet<Self, T>
2445    where
2446        T: AsExpression<Inet>,
2447    {
2448        Grouped(DifferenceNet::new(self, other.as_expression()))
2449    }
2450}
2451
2452impl<T> PgNetExpressionMethods for T
2453where
2454    T: Expression,
2455    T::SqlType: InetOrCidr,
2456{
2457}
2458
2459/// PostgreSQL specific methods present on JSONB expressions.
2460#[cfg(feature = "postgres_backend")]
2461pub trait PgJsonbExpressionMethods: Expression + Sized {
2462    /// Creates a PostgreSQL `||` expression.
2463    ///
2464    /// This operator concatenates two JSONB values and returns JSONB value
2465    ///
2466    /// # Example
2467    ///
2468    /// ```rust
2469    /// # include!("../../doctest_setup.rs");
2470    /// #
2471    /// # table! {
2472    /// #    contacts {
2473    /// #        id -> Integer,
2474    /// #        name -> VarChar,
2475    /// #        address -> Jsonb,
2476    /// #    }
2477    /// # }
2478    /// #
2479    /// # fn main() {
2480    /// #     run_test().unwrap();
2481    /// # }
2482    ///
2483    /// # #[cfg(feature = "serde_json")]
2484    /// # fn run_test() -> QueryResult<()> {
2485    /// #     use self::contacts::dsl::*;
2486    /// #     let conn = &mut establish_connection();
2487    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2488    /// #     diesel::sql_query("CREATE TABLE contacts (
2489    /// #         id SERIAL PRIMARY KEY,
2490    /// #         name VARCHAR NOT NULL,
2491    /// #         address JSONB NOT NULL
2492    /// #     )").execute(conn).unwrap();
2493    /// #
2494    /// let santas_address: serde_json::Value = serde_json::json!({
2495    ///     "street": "Article Circle Expressway 1",
2496    ///     "city": "North Pole",
2497    ///     "postcode": "99705",
2498    ///     "state": "Alaska"
2499    /// });
2500    /// diesel::insert_into(contacts)
2501    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2502    ///     .execute(conn)?;
2503    ///
2504    /// let to_concatenate: serde_json::Value = serde_json::json!({
2505    ///     "continent": "NA",
2506    ///     "planet": "Earth"
2507    /// });
2508    ///
2509    /// let final_address: serde_json::Value = serde_json::json!({
2510    ///     "street": "Article Circle Expressway 1",
2511    ///     "city": "North Pole",
2512    ///     "postcode": "99705",
2513    ///     "state": "Alaska",
2514    ///     "continent": "NA",
2515    ///     "planet": "Earth"
2516    /// });
2517    ///
2518    /// let final_address_db = contacts.select(address.concat(&to_concatenate)).get_result::<serde_json::Value>(conn)?;
2519    /// assert_eq!(final_address, final_address_db);
2520    /// #     Ok(())
2521    /// # }
2522    /// # #[cfg(not(feature = "serde_json"))]
2523    /// # fn run_test() -> QueryResult<()> {
2524    /// #     Ok(())
2525    /// # }
2526    /// ```
2527    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
2528    where
2529        Self::SqlType: SqlType,
2530        T: AsExpression<Self::SqlType>,
2531    {
2532        Grouped(Concat::new(self, other.as_expression()))
2533    }
2534
2535    /// Creates a PostgreSQL `?` expression.
2536    ///
2537    /// This operator checks if the right hand side string exists as a top-level key within the JSONB
2538    ///
2539    /// # Example
2540    ///
2541    /// ```rust
2542    /// # include!("../../doctest_setup.rs");
2543    /// #
2544    /// # table! {
2545    /// #    contacts {
2546    /// #        id -> Integer,
2547    /// #        name -> VarChar,
2548    /// #        address -> Jsonb,
2549    /// #    }
2550    /// # }
2551    /// #
2552    /// # fn main() {
2553    /// #     run_test().unwrap();
2554    /// # }
2555    ///
2556    /// # #[cfg(feature = "serde_json")]
2557    /// # fn run_test() -> QueryResult<()> {
2558    /// #     use self::contacts::dsl::*;
2559    /// #     let conn = &mut establish_connection();
2560    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2561    /// #     diesel::sql_query("CREATE TABLE contacts (
2562    /// #         id SERIAL PRIMARY KEY,
2563    /// #         name VARCHAR NOT NULL,
2564    /// #         address JSONB NOT NULL
2565    /// #     )").execute(conn).unwrap();
2566    /// #
2567    /// let santas_address: serde_json::Value = serde_json::json!({
2568    ///     "street": "Article Circle Expressway 1",
2569    ///     "city": "North Pole",
2570    ///     "postcode": "99705",
2571    ///     "state": "Alaska"
2572    /// });
2573    /// diesel::insert_into(contacts)
2574    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2575    ///     .execute(conn)?;
2576    ///
2577    /// let key_exists = contacts.select(address.has_key("street")).get_result::<bool>(conn)?;
2578    /// assert!(key_exists);
2579    ///
2580    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_key("postcode")).get_result::<i32>(conn)?;
2581    /// assert_eq!(1, santas_with_address_postcode);
2582    /// #     Ok(())
2583    /// # }
2584    /// # #[cfg(not(feature = "serde_json"))]
2585    /// # fn run_test() -> QueryResult<()> {
2586    /// #     Ok(())
2587    /// # }
2588    /// ```
2589    fn has_key<T>(self, other: T) -> dsl::HasKeyJsonb<Self, T>
2590    where
2591        T: AsExpression<VarChar>,
2592    {
2593        Grouped(HasKeyJsonb::new(self, other.as_expression()))
2594    }
2595
2596    /// Creates a PostgreSQL `?|` expression.
2597    ///
2598    /// This operator checks if any of the strings in the right hand side array exists as top level key in the given JSONB
2599    ///
2600    /// # Example
2601    ///
2602    /// ```rust
2603    /// # include!("../../doctest_setup.rs");
2604    /// #
2605    /// # table! {
2606    /// #    contacts {
2607    /// #        id -> Integer,
2608    /// #        name -> VarChar,
2609    /// #        address -> Jsonb,
2610    /// #    }
2611    /// # }
2612    /// #
2613    /// # fn main() {
2614    /// #     run_test().unwrap();
2615    /// # }
2616    ///
2617    /// # #[cfg(feature = "serde_json")]
2618    /// # fn run_test() -> QueryResult<()> {
2619    /// #     use self::contacts::dsl::*;
2620    /// #     let conn = &mut establish_connection();
2621    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2622    /// #     diesel::sql_query("CREATE TABLE contacts (
2623    /// #         id SERIAL PRIMARY KEY,
2624    /// #         name VARCHAR NOT NULL,
2625    /// #         address JSONB NOT NULL
2626    /// #     )").execute(conn).unwrap();
2627    /// #
2628    /// let santas_address: serde_json::Value = serde_json::json!({
2629    ///     "street": "Article Circle Expressway 1",
2630    ///     "city": "North Pole",
2631    ///     "postcode": "99705",
2632    ///     "state": "Alaska"
2633    /// });
2634    /// diesel::insert_into(contacts)
2635    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2636    ///     .execute(conn)?;
2637    ///
2638    /// let any_key_exists = contacts.select(address.has_any_key(vec!["street", "city", "rudolf"])).get_result::<bool>(conn)?;
2639    /// assert!(any_key_exists);
2640    ///
2641    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_any_key(vec!["street", "city", "rudolf"])).get_result::<i32>(conn)?;
2642    /// assert_eq!(1, santas_with_address_postcode);
2643    /// #     Ok(())
2644    /// # }
2645    /// # #[cfg(not(feature = "serde_json"))]
2646    /// # fn run_test() -> QueryResult<()> {
2647    /// #     Ok(())
2648    /// # }
2649    /// ``````
2650    fn has_any_key<T>(self, other: T) -> dsl::HasAnyKeyJsonb<Self, T>
2651    where
2652        T: AsExpression<Array<VarChar>>,
2653    {
2654        Grouped(HasAnyKeyJsonb::new(self, other.as_expression()))
2655    }
2656
2657    /// Creates a PostgreSQL `?&` expression.
2658    ///
2659    /// This operator checks if all the strings in the right hand side array exist as top level keys in the given JSONB
2660    ///
2661    /// # Example
2662    ///
2663    /// ```rust
2664    /// # include!("../../doctest_setup.rs");
2665    /// #
2666    /// # table! {
2667    /// #    contacts {
2668    /// #        id -> Integer,
2669    /// #        name -> VarChar,
2670    /// #        address -> Jsonb,
2671    /// #    }
2672    /// # }
2673    /// #
2674    /// # fn main() {
2675    /// #     run_test().unwrap();
2676    /// # }
2677    ///
2678    /// # #[cfg(feature = "serde_json")]
2679    /// # fn run_test() -> QueryResult<()> {
2680    /// #     use self::contacts::dsl::*;
2681    /// #     let conn = &mut establish_connection();
2682    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2683    /// #     diesel::sql_query("CREATE TABLE contacts (
2684    /// #         id SERIAL PRIMARY KEY,
2685    /// #         name VARCHAR NOT NULL,
2686    /// #         address JSONB NOT NULL
2687    /// #     )").execute(conn).unwrap();
2688    /// #
2689    /// let santas_address: serde_json::Value = serde_json::json!({
2690    ///     "street": "Article Circle Expressway 1",
2691    ///     "city": "North Pole",
2692    ///     "postcode": "99705",
2693    ///     "state": "Alaska"
2694    /// });
2695    /// diesel::insert_into(contacts)
2696    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2697    ///     .execute(conn)?;
2698    ///
2699    /// let all_keys_exist = contacts.select(address.has_all_keys(vec!["street", "city", "postcode"])).get_result::<bool>(conn)?;
2700    /// assert!(all_keys_exist);
2701    ///
2702    /// let santas_with_address_postcode = contacts.select(id).filter(address.has_all_keys(vec!["street", "city", "postcode"])).get_result::<i32>(conn)?;
2703    /// assert_eq!(1, santas_with_address_postcode);
2704    /// #     Ok(())
2705    /// # }
2706    /// # #[cfg(not(feature = "serde_json"))]
2707    /// # fn run_test() -> QueryResult<()> {
2708    /// #     Ok(())
2709    /// # }
2710    /// ``````
2711    fn has_all_keys<T>(self, other: T) -> dsl::HasAllKeysJsonb<Self, T>
2712    where
2713        T: AsExpression<Array<VarChar>>,
2714    {
2715        Grouped(HasAllKeysJsonb::new(self, other.as_expression()))
2716    }
2717
2718    /// Creates a PostgreSQL `@>` expression.
2719    ///
2720    /// This operator checks whether left hand side JSONB value contains right hand side JSONB value
2721    ///
2722    /// # Example
2723    ///
2724    /// ```rust
2725    /// # include!("../../doctest_setup.rs");
2726    /// #
2727    /// # table! {
2728    /// #    contacts {
2729    /// #        id -> Integer,
2730    /// #        name -> VarChar,
2731    /// #        address -> Jsonb,
2732    /// #    }
2733    /// # }
2734    /// #
2735    /// # fn main() {
2736    /// #     run_test().unwrap();
2737    /// # }
2738    /// #
2739    /// # #[cfg(feature = "serde_json")]
2740    /// # fn run_test() -> QueryResult<()> {
2741    /// #     use self::contacts::dsl::*;
2742    /// #     let conn = &mut establish_connection();
2743    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2744    /// #     diesel::sql_query("CREATE TABLE contacts (
2745    /// #         id SERIAL PRIMARY KEY,
2746    /// #         name VARCHAR NOT NULL,
2747    /// #         address JSONB NOT NULL
2748    /// #     )").execute(conn).unwrap();
2749    /// #
2750    /// let easter_bunny_address: serde_json::Value = serde_json::json!({
2751    ///     "street": "123 Carrot Road",
2752    ///     "province": "Easter Island",
2753    ///     "region": "Valparaíso",
2754    ///     "country": "Chile",
2755    ///     "postcode": "88888",
2756    /// });
2757    /// diesel::insert_into(contacts)
2758    ///     .values((name.eq("Bunny"), address.eq(&easter_bunny_address)))
2759    ///     .execute(conn)?;
2760    ///
2761    /// let country_chile: serde_json::Value = serde_json::json!({"country": "Chile"});
2762    /// let contains_country_chile = contacts.select(address.contains(&country_chile)).get_result::<bool>(conn)?;
2763    /// assert!(contains_country_chile);
2764    /// #     Ok(())
2765    /// # }
2766    /// # #[cfg(not(feature = "serde_json"))]
2767    /// # fn run_test() -> QueryResult<()> {
2768    /// #     Ok(())
2769    /// # }
2770    /// ```
2771    fn contains<T>(self, other: T) -> dsl::Contains<Self, T>
2772    where
2773        Self::SqlType: SqlType,
2774        T: AsExpression<Self::SqlType>,
2775    {
2776        Grouped(Contains::new(self, other.as_expression()))
2777    }
2778
2779    /// Creates a PostgreSQL `<@` expression.
2780    ///
2781    /// This operator checks whether left hand side JSONB value is contained by right hand side JSON value.
2782    /// `foo.contains(bar)` is the same as `bar.is_contained_by(foo)`.
2783    ///
2784    /// # Example
2785    ///
2786    /// ```rust
2787    /// # include!("../../doctest_setup.rs");
2788    /// #
2789    /// # table! {
2790    /// #    contacts {
2791    /// #        id -> Integer,
2792    /// #        name -> VarChar,
2793    /// #        address -> Jsonb,
2794    /// #    }
2795    /// # }
2796    /// #
2797    /// # fn main() {
2798    /// #     run_test().unwrap();
2799    /// # }
2800    /// #
2801    /// # #[cfg(feature = "serde_json")]
2802    /// # fn run_test() -> QueryResult<()> {
2803    /// #     use self::contacts::dsl::*;
2804    /// #     let conn = &mut establish_connection();
2805    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2806    /// #     diesel::sql_query("CREATE TABLE contacts (
2807    /// #         id SERIAL PRIMARY KEY,
2808    /// #         name VARCHAR NOT NULL,
2809    /// #         address JSONB NOT NULL
2810    /// #     )").execute(conn).unwrap();
2811    /// #
2812    /// let partial_easter_bunny_address: serde_json::Value = serde_json::json!({
2813    ///     "street": "123 Carrot Road",
2814    ///     "country": "Chile",
2815    /// });
2816    /// diesel::insert_into(contacts)
2817    ///     .values((name.eq("Bunny"), address.eq(&partial_easter_bunny_address)))
2818    ///     .execute(conn)?;
2819    ///
2820    /// let full_easter_bunny_address: serde_json::Value = serde_json::json!({
2821    ///     "street": "123 Carrot Road",
2822    ///     "province": "Easter Island",
2823    ///     "region": "Valparaíso",
2824    ///     "country": "Chile",
2825    ///     "postcode": "88888",
2826    /// });
2827    /// let address_is_contained_by = contacts.select(address.is_contained_by(&full_easter_bunny_address)).get_result::<bool>(conn)?;
2828    /// assert!(address_is_contained_by);
2829    /// #     Ok(())
2830    /// # }
2831    /// # #[cfg(not(feature = "serde_json"))]
2832    /// # fn run_test() -> QueryResult<()> {
2833    /// #     Ok(())
2834    /// # }
2835    /// ```
2836    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
2837    fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
2838    where
2839        Self::SqlType: SqlType,
2840        T: AsExpression<Self::SqlType>,
2841    {
2842        Grouped(IsContainedBy::new(self, other.as_expression()))
2843    }
2844
2845    /// Creates a PostgreSQL `-` expression.
2846    ///
2847    /// This operator removes the value associated with the given key, that is provided on the
2848    /// Right Hand Side of the operator.
2849    ///
2850    /// # Example
2851    ///
2852    /// ```rust
2853    /// # include!("../../doctest_setup.rs");
2854    /// #
2855    /// # table! {
2856    /// #    contacts {
2857    /// #        id -> Integer,
2858    /// #        name -> VarChar,
2859    /// #        address -> Jsonb,
2860    /// #    }
2861    /// # }
2862    /// #
2863    /// # fn main() {
2864    /// #     run_test().unwrap();
2865    /// # }
2866    ///
2867    /// # #[cfg(feature = "serde_json")]
2868    /// # fn run_test() -> QueryResult<()> {
2869    /// #     use self::contacts::dsl::*;
2870    /// #     let conn = &mut establish_connection();
2871    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2872    /// #     diesel::sql_query("CREATE TABLE contacts (
2873    /// #         id SERIAL PRIMARY KEY,
2874    /// #         name VARCHAR NOT NULL,
2875    /// #         address JSONB NOT NULL
2876    /// #     )").execute(conn)
2877    /// #        .unwrap();
2878    /// #
2879    /// let santas_address: serde_json::Value = serde_json::json!({
2880    ///     "street": "Article Circle Expressway 1",
2881    ///     "city": "North Pole",
2882    ///     "postcode": "99705",
2883    ///     "state": "Alaska"
2884    /// });
2885    /// diesel::insert_into(contacts)
2886    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2887    ///     .execute(conn)?;
2888    ///
2889    /// let santas_modified_address = contacts.select(address.remove("postcode")).get_result::<serde_json::Value>(conn)?;
2890    /// assert_eq!(santas_modified_address, serde_json::json!({
2891    ///     "street": "Article Circle Expressway 1",
2892    ///     "city": "North Pole",
2893    ///     "state": "Alaska"
2894    /// }));
2895    /// diesel::insert_into(contacts)
2896    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2897    ///     .execute(conn)?;
2898    ///
2899    /// let santas_modified_address = contacts.select(address.remove(vec!["postcode", "state"])).get_result::<serde_json::Value>(conn)?;
2900    /// assert_eq!(santas_modified_address, serde_json::json!({
2901    ///     "street": "Article Circle Expressway 1",
2902    ///     "city": "North Pole",
2903    /// }));
2904    ///
2905    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
2906    ///     {
2907    ///         "street": "Somewhere In La 251",
2908    ///         "city": "Los Angeles",
2909    ///         "postcode": "12231223",
2910    ///         "state": "California"
2911    ///     },
2912    ///     {
2913    ///         "street": "Somewhere In Ny 251",
2914    ///         "city": "New York",
2915    ///         "postcode": "3213212",
2916    ///         "state": "New York"
2917    ///     }
2918    /// ]);
2919    ///
2920    /// diesel::insert_into(contacts)
2921    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
2922    ///     .execute(conn)?;
2923    ///
2924    /// let roberts_address_in_db = contacts
2925    ///                             .filter(name.eq("Robert Downey Jr."))
2926    ///                             .select(address.remove(1))
2927    ///                             .get_result::<serde_json::Value>(conn)?;
2928    ///
2929    /// let roberts_first_address = serde_json::json!([{
2930    ///         "street": "Somewhere In La 251",
2931    ///         "city": "Los Angeles",
2932    ///         "postcode": "12231223",
2933    ///         "state": "California"
2934    /// }]);
2935    /// assert_eq!(roberts_first_address, roberts_address_in_db);
2936    /// #     Ok(())
2937    /// # }
2938    /// # #[cfg(not(feature = "serde_json"))]
2939    /// # fn run_test() -> QueryResult<()> {
2940    /// #     Ok(())
2941    /// # }
2942    ///
2943    fn remove<T>(
2944        self,
2945        other: T,
2946    ) -> dsl::RemoveFromJsonb<Self, T::Expression, <T::Expression as Expression>::SqlType>
2947    where
2948        T: JsonRemoveIndex,
2949        <T::Expression as Expression>::SqlType: SqlType,
2950    {
2951        Grouped(RemoveFromJsonb::new(
2952            self,
2953            other.into_json_index_expression(),
2954        ))
2955    }
2956
2957    /// Creates a PostgreSQL `#-` expression.
2958    ///
2959    /// This operator removes the value associated with the given json path, that is provided on the
2960    /// Right Hand Side of the operator.
2961    ///
2962    /// # Example
2963    ///
2964    /// ```rust
2965    /// # include!("../../doctest_setup.rs");
2966    /// #
2967    /// # table! {
2968    /// #    contacts {
2969    /// #        id -> Integer,
2970    /// #        name -> VarChar,
2971    /// #        address -> Jsonb,
2972    /// #    }
2973    /// # }
2974    /// #
2975    /// # fn main() {
2976    /// #     run_test().unwrap();
2977    /// # }
2978    ///
2979    /// # #[cfg(feature = "serde_json")]
2980    /// # fn run_test() -> QueryResult<()> {
2981    /// #     use self::contacts::dsl::*;
2982    /// #     let conn = &mut establish_connection();
2983    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
2984    /// #     diesel::sql_query("CREATE TABLE contacts (
2985    /// #         id SERIAL PRIMARY KEY,
2986    /// #         name VARCHAR NOT NULL,
2987    /// #         address JSONB NOT NULL
2988    /// #     )").execute(conn)
2989    /// #        .unwrap();
2990    /// #
2991    /// let santas_address: serde_json::Value = serde_json::json!({
2992    ///     "street": "Article Circle Expressway 1",
2993    ///     "city": "North Pole",
2994    ///     "postcode": "99705",
2995    ///     "state": "Alaska"
2996    /// });
2997    /// diesel::insert_into(contacts)
2998    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
2999    ///     .execute(conn)?;
3000    ///
3001    /// let santas_modified_address = contacts.select(address.remove("postcode")).get_result::<serde_json::Value>(conn)?;
3002    /// assert_eq!(santas_modified_address, serde_json::json!({
3003    ///     "street": "Article Circle Expressway 1",
3004    ///     "city": "North Pole",
3005    ///     "state": "Alaska"
3006    /// }));
3007    /// diesel::insert_into(contacts)
3008    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
3009    ///     .execute(conn)?;
3010    ///
3011    /// let santas_modified_address = contacts.select(address.remove_by_path(vec!["postcode"])).get_result::<serde_json::Value>(conn)?;
3012    /// assert_eq!(santas_modified_address, serde_json::json!({
3013    ///     "street": "Article Circle Expressway 1",
3014    ///     "city": "North Pole",
3015    ///     "state": "Alaska"
3016    /// }));
3017    ///
3018    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
3019    ///     {
3020    ///         "street": "Somewhere In La 251",
3021    ///         "city": "Los Angeles",
3022    ///         "postcode": "12231223",
3023    ///         "state": "California"
3024    ///     },
3025    ///     {
3026    ///         "street": "Somewhere In Ny 251",
3027    ///         "city": "New York",
3028    ///         "postcode": "3213212",
3029    ///         "state": "New York"
3030    ///     }
3031    /// ]);
3032    ///
3033    /// diesel::insert_into(contacts)
3034    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
3035    ///     .execute(conn)?;
3036    ///
3037    /// let roberts_address_in_db = contacts
3038    ///                             .filter(name.eq("Robert Downey Jr."))
3039    ///                             .select(address.remove_by_path(vec!["1", "postcode"]))
3040    ///                             .get_result::<serde_json::Value>(conn)?;
3041    ///
3042    /// let roberts_address = serde_json::json!([
3043    ///     {
3044    ///         "street": "Somewhere In La 251",
3045    ///         "city": "Los Angeles",
3046    ///         "postcode": "12231223",
3047    ///         "state": "California"
3048    ///     },
3049    ///     {
3050    ///         "street": "Somewhere In Ny 251",
3051    ///         "city": "New York",
3052    ///         "state": "New York"
3053    ///     }
3054    /// ]);
3055    /// assert_eq!(roberts_address, roberts_address_in_db);
3056    /// #     Ok(())
3057    /// # }
3058    /// # #[cfg(not(feature = "serde_json"))]
3059    /// # fn run_test() -> QueryResult<()> {
3060    /// #     Ok(())
3061    /// # }
3062    ///
3063    fn remove_by_path<T>(self, other: T) -> dsl::RemoveByPathFromJsonb<Self, T::Expression>
3064    where
3065        T: AsExpression<Array<Text>>,
3066    {
3067        Grouped(RemoveByPathFromJsonb::new(self, other.as_expression()))
3068    }
3069}
3070
3071impl<T> PgJsonbExpressionMethods for T
3072where
3073    T: Expression,
3074    T::SqlType: JsonbOrNullableJsonb,
3075{
3076}
3077
3078/// PostgreSQL specific methods present on JSON and JSONB expressions.
3079#[cfg(feature = "postgres_backend")]
3080pub trait PgAnyJsonExpressionMethods: Expression + Sized {
3081    /// Creates a PostgreSQL `->` expression.
3082    ///
3083    /// This operator extracts the value associated with the given key, that is provided on the
3084    /// Right Hand Side of the operator.
3085    ///
3086    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
3087    /// Extracts JSON object field with the given key.
3088    /// # Example
3089    ///
3090    /// ```rust
3091    /// # include!("../../doctest_setup.rs");
3092    /// #
3093    /// # table! {
3094    /// #    contacts {
3095    /// #        id -> Integer,
3096    /// #        name -> VarChar,
3097    /// #        address -> Jsonb,
3098    /// #    }
3099    /// # }
3100    /// #
3101    /// # fn main() {
3102    /// #     run_test().unwrap();
3103    /// # }
3104    ///
3105    /// # #[cfg(feature = "serde_json")]
3106    /// # fn run_test() -> QueryResult<()> {
3107    /// #     use self::contacts::dsl::*;
3108    /// #     let conn = &mut establish_connection();
3109    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
3110    /// #     diesel::sql_query("CREATE TABLE contacts (
3111    /// #         id SERIAL PRIMARY KEY,
3112    /// #         name VARCHAR NOT NULL,
3113    /// #         address JSONB NOT NULL
3114    /// #     )").execute(conn)
3115    /// #        .unwrap();
3116    /// #
3117    /// let santas_address: serde_json::Value = serde_json::json!({
3118    ///     "street": "Article Circle Expressway 1",
3119    ///     "city": "North Pole",
3120    ///     "postcode": "99705",
3121    ///     "state": "Alaska"
3122    /// });
3123    /// diesel::insert_into(contacts)
3124    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
3125    ///     .execute(conn)?;
3126    ///
3127    /// let santas_postcode = contacts.select(address.retrieve_as_object("postcode")).get_result::<serde_json::Value>(conn)?;
3128    /// assert_eq!(santas_postcode, serde_json::json!("99705"));
3129    ///
3130    ///
3131    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
3132    ///     {
3133    ///         "street": "Somewhere In La 251",
3134    ///         "city": "Los Angeles",
3135    ///         "postcode": "12231223",
3136    ///         "state": "California"
3137    ///     },
3138    ///     {
3139    ///         "street": "Somewhere In Ny 251",
3140    ///         "city": "New York",
3141    ///         "postcode": "3213212",
3142    ///         "state": "New York"
3143    ///     }
3144    /// ]);
3145    ///
3146    /// diesel::insert_into(contacts)
3147    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
3148    ///     .execute(conn)?;
3149    ///
3150    /// let roberts_second_address_in_db = contacts
3151    ///                             .filter(name.eq("Robert Downey Jr."))
3152    ///                             .select(address.retrieve_as_object(1))
3153    ///                             .get_result::<serde_json::Value>(conn)?;
3154    ///
3155    /// let roberts_second_address = serde_json::json!({
3156    ///         "street": "Somewhere In Ny 251",
3157    ///         "city": "New York",
3158    ///         "postcode": "3213212",
3159    ///         "state": "New York"
3160    /// });
3161    /// assert_eq!(roberts_second_address, roberts_second_address_in_db);
3162    /// #     Ok(())
3163    /// # }
3164    /// # #[cfg(not(feature = "serde_json"))]
3165    /// # fn run_test() -> QueryResult<()> {
3166    /// #     Ok(())
3167    /// # }
3168    /// ```
3169    fn retrieve_as_object<T>(
3170        self,
3171        other: T,
3172    ) -> dsl::RetrieveAsObjectJson<Self, T::Expression, <T::Expression as Expression>::SqlType>
3173    where
3174        T: JsonIndex,
3175        <T::Expression as Expression>::SqlType: SqlType,
3176    {
3177        Grouped(RetrieveAsObjectJson::new(
3178            self,
3179            other.into_json_index_expression(),
3180        ))
3181    }
3182
3183    /// Creates a PostgreSQL `->>` expression.
3184    ///
3185    /// This operator extracts the value associated with the given key, that is provided on the
3186    /// Right Hand Side of the operator.
3187    ///
3188    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
3189    /// Extracts JSON object field as Text with the given key.
3190    /// # Example
3191    ///
3192    /// ```rust
3193    /// # include!("../../doctest_setup.rs");
3194    /// #
3195    /// # table! {
3196    /// #    contacts {
3197    /// #        id -> Integer,
3198    /// #        name -> VarChar,
3199    /// #        address -> Jsonb,
3200    /// #    }
3201    /// # }
3202    /// #
3203    /// # fn main() {
3204    /// #     run_test().unwrap();
3205    /// # }
3206    ///
3207    /// # #[cfg(feature = "serde_json")]
3208    /// # fn run_test() -> QueryResult<()> {
3209    /// #     use self::contacts::dsl::*;
3210    /// #     let conn = &mut establish_connection();
3211    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
3212    /// #     diesel::sql_query("CREATE TABLE contacts (
3213    /// #         id SERIAL PRIMARY KEY,
3214    /// #         name VARCHAR NOT NULL,
3215    /// #         address JSONB NOT NULL
3216    /// #     )").execute(conn)
3217    /// #        .unwrap();
3218    /// #
3219    /// let santas_address: serde_json::Value = serde_json::json!({
3220    ///     "street": "Article Circle Expressway 1",
3221    ///     "city": "North Pole",
3222    ///     "postcode": "99705",
3223    ///     "state": "Alaska"
3224    /// });
3225    /// diesel::insert_into(contacts)
3226    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
3227    ///     .execute(conn)?;
3228    ///
3229    /// let santas_postcode = contacts.select(address.retrieve_as_text("postcode")).get_result::<String>(conn)?;
3230    /// assert_eq!(santas_postcode, "99705");
3231    ///
3232    ///
3233    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
3234    ///     {
3235    ///         "street": "Somewhere In La 251",
3236    ///         "city": "Los Angeles",
3237    ///         "postcode": "12231223",
3238    ///         "state": "California"
3239    ///     },
3240    ///     {
3241    ///         "street": "Somewhere In Ny 251",
3242    ///         "city": "New York",
3243    ///         "postcode": "3213212",
3244    ///         "state": "New York"
3245    ///     }
3246    /// ]);
3247    ///
3248    /// diesel::insert_into(contacts)
3249    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
3250    ///     .execute(conn)?;
3251    ///
3252    /// let roberts_second_address_in_db = contacts
3253    ///                             .filter(name.eq("Robert Downey Jr."))
3254    ///                             .select(address.retrieve_as_text(1))
3255    ///                             .get_result::<String>(conn)?;
3256    ///
3257    /// let roberts_second_address = String::from(
3258    ///     "{\"city\": \"New York\", \
3259    ///     \"state\": \"New York\", \
3260    ///     \"street\": \"Somewhere In Ny 251\", \
3261    ///     \"postcode\": \"3213212\"}"
3262    ///     );
3263    /// assert_eq!(roberts_second_address, roberts_second_address_in_db);
3264    /// #     Ok(())
3265    /// # }
3266    /// # #[cfg(not(feature = "serde_json"))]
3267    /// # fn run_test() -> QueryResult<()> {
3268    /// #     Ok(())
3269    /// # }
3270    /// ```
3271    fn retrieve_as_text<T>(
3272        self,
3273        other: T,
3274    ) -> dsl::RetrieveAsTextJson<Self, T::Expression, <T::Expression as Expression>::SqlType>
3275    where
3276        T: JsonIndex,
3277        <T::Expression as Expression>::SqlType: SqlType,
3278    {
3279        Grouped(RetrieveAsTextJson::new(
3280            self,
3281            other.into_json_index_expression(),
3282        ))
3283    }
3284
3285    /// Creates a PostgreSQL `#>` expression.
3286    ///
3287    /// This operator extracts the value associated with the given key, that is provided on the
3288    /// Right Hand Side of the operator.
3289    ///
3290    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
3291    /// Extracts JSON object field with the given key.
3292    /// # Example
3293    ///
3294    /// ```rust
3295    /// # include!("../../doctest_setup.rs");
3296    /// #
3297    /// # table! {
3298    /// #    contacts {
3299    /// #        id -> Integer,
3300    /// #        name -> VarChar,
3301    /// #        address -> Jsonb,
3302    /// #    }
3303    /// # }
3304    /// #
3305    /// # fn main() {
3306    /// #     run_test().unwrap();
3307    /// # }
3308    ///
3309    /// # #[cfg(feature = "serde_json")]
3310    /// # fn run_test() -> QueryResult<()> {
3311    /// #     use self::contacts::dsl::*;
3312    /// #     let conn = &mut establish_connection();
3313    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
3314    /// #     diesel::sql_query("CREATE TABLE contacts (
3315    /// #         id SERIAL PRIMARY KEY,
3316    /// #         name VARCHAR NOT NULL,
3317    /// #         address JSONB NOT NULL
3318    /// #     )").execute(conn)
3319    /// #        .unwrap();
3320    /// #
3321    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
3322    ///     {
3323    ///         "street": "Somewhere In La 251",
3324    ///         "city": "Los Angeles",
3325    ///         "postcode": "12231223",
3326    ///         "state": "California"
3327    ///     },
3328    ///     {
3329    ///         "street": "Somewhere In Ny 251",
3330    ///         "city": "New York",
3331    ///         "postcode": "3213212",
3332    ///         "state": "New York"
3333    ///     }
3334    /// ]);
3335    ///
3336    /// diesel::insert_into(contacts)
3337    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
3338    ///     .execute(conn)?;
3339    ///
3340    /// let roberts_second_street_in_db = contacts
3341    ///                             .filter(name.eq("Robert Downey Jr."))
3342    ///                             .select(address.retrieve_by_path_as_object(vec!["1", "street"]))
3343    ///                             .get_result::<serde_json::Value>(conn)?;
3344    ///
3345    /// assert_eq!(roberts_second_street_in_db, serde_json::json!("Somewhere In Ny 251"));
3346    /// #     Ok(())
3347    /// # }
3348    /// # #[cfg(not(feature = "serde_json"))]
3349    /// # fn run_test() -> QueryResult<()> {
3350    /// #     Ok(())
3351    /// # }
3352    /// ```
3353    fn retrieve_by_path_as_object<T>(
3354        self,
3355        other: T,
3356    ) -> dsl::RetrieveByPathAsObjectJson<Self, T::Expression>
3357    where
3358        T: AsExpression<Array<Text>>,
3359    {
3360        Grouped(RetrieveByPathAsObjectJson::new(self, other.as_expression()))
3361    }
3362
3363    /// Creates a PostgreSQL `#>>` expression.
3364    ///
3365    /// This operator extracts the value associated with the given key, that is provided on the
3366    /// Right Hand Side of the operator.
3367    ///
3368    /// Extracts n'th element of JSON array (array elements are indexed from zero, but negative integers count from the end).
3369    /// Extracts JSON object field as Text with the given key.
3370    /// # Example
3371    ///
3372    /// ```rust
3373    /// # include!("../../doctest_setup.rs");
3374    /// #
3375    /// # table! {
3376    /// #    contacts {
3377    /// #        id -> Integer,
3378    /// #        name -> VarChar,
3379    /// #        address -> Jsonb,
3380    /// #    }
3381    /// # }
3382    /// #
3383    /// # fn main() {
3384    /// #     run_test().unwrap();
3385    /// # }
3386    ///
3387    /// # #[cfg(feature = "serde_json")]
3388    /// # fn run_test() -> QueryResult<()> {
3389    /// #     use self::contacts::dsl::*;
3390    /// #     let conn = &mut establish_connection();
3391    /// #     diesel::sql_query("DROP TABLE IF EXISTS contacts").execute(conn).unwrap();
3392    /// #     diesel::sql_query("CREATE TABLE contacts (
3393    /// #         id SERIAL PRIMARY KEY,
3394    /// #         name VARCHAR NOT NULL,
3395    /// #         address JSONB NOT NULL
3396    /// #     )").execute(conn)
3397    /// #        .unwrap();
3398    /// #
3399    /// let robert_downey_jr_addresses: serde_json::Value = serde_json::json!([
3400    ///     {
3401    ///         "street": "Somewhere In La 251",
3402    ///         "city": "Los Angeles",
3403    ///         "postcode": "12231223",
3404    ///         "state": "California"
3405    ///     },
3406    ///     {
3407    ///         "street": "Somewhere In Ny 251",
3408    ///         "city": "New York",
3409    ///         "postcode": "3213212",
3410    ///         "state": "New York"
3411    ///     }
3412    /// ]);
3413    ///
3414    /// diesel::insert_into(contacts)
3415    ///     .values((name.eq("Robert Downey Jr."), address.eq(&robert_downey_jr_addresses)))
3416    ///     .execute(conn)?;
3417    ///
3418    /// let roberts_second_street_in_db = contacts
3419    ///                             .filter(name.eq("Robert Downey Jr."))
3420    ///                             .select(address.retrieve_by_path_as_text(vec!["1", "street"]))
3421    ///                             .get_result::<String>(conn)?;
3422    ///
3423    /// assert_eq!(roberts_second_street_in_db, "Somewhere In Ny 251");
3424    ///
3425    /// #     Ok(())
3426    /// # }
3427    /// # #[cfg(not(feature = "serde_json"))]
3428    /// # fn run_test() -> QueryResult<()> {
3429    /// #     Ok(())
3430    /// # }
3431    /// ```
3432    fn retrieve_by_path_as_text<T>(
3433        self,
3434        other: T,
3435    ) -> dsl::RetrieveByPathAsTextJson<Self, T::Expression>
3436    where
3437        T: AsExpression<Array<Text>>,
3438    {
3439        Grouped(RetrieveByPathAsTextJson::new(self, other.as_expression()))
3440    }
3441}
3442
3443#[doc(hidden)]
3444impl<T> PgAnyJsonExpressionMethods for T
3445where
3446    T: Expression,
3447    T::SqlType: JsonOrNullableJsonOrJsonbOrNullableJsonb,
3448{
3449}
3450
3451/// PostgreSQL specific methods present on Binary expressions.
3452#[cfg(feature = "postgres_backend")]
3453pub trait PgBinaryExpressionMethods: Expression + Sized {
3454    /// Concatenates two PostgreSQL byte arrays using the `||` operator.
3455    ///
3456    /// # Example
3457    ///
3458    /// ```rust
3459    /// # include!("../../doctest_setup.rs");
3460    /// #
3461    /// # table! {
3462    /// #     users {
3463    /// #         id -> Integer,
3464    /// #         name -> Binary,
3465    /// #         hair_color -> Nullable<Binary>,
3466    /// #     }
3467    /// # }
3468    /// #
3469    /// # fn main() {
3470    /// #     use self::users::dsl::*;
3471    /// #     use diesel::insert_into;
3472    /// #
3473    /// #     let connection = &mut connection_no_data();
3474    /// #     diesel::sql_query("CREATE TABLE users (
3475    /// #         id INTEGER PRIMARY KEY,
3476    /// #         name BYTEA NOT NULL,
3477    /// #         hair_color BYTEA
3478    /// #     )").execute(connection).unwrap();
3479    /// #
3480    /// #     insert_into(users)
3481    /// #         .values(&vec![
3482    /// #             (id.eq(1), name.eq("Sean".as_bytes()), Some(hair_color.eq(Some("Green".as_bytes())))),
3483    /// #             (id.eq(2), name.eq("Tess".as_bytes()), None),
3484    /// #         ])
3485    /// #         .execute(connection)
3486    /// #         .unwrap();
3487    /// #
3488    /// let names = users.select(name.concat(" the Greatest".as_bytes())).load(connection);
3489    /// let expected_names = vec![
3490    ///     b"Sean the Greatest".to_vec(),
3491    ///     b"Tess the Greatest".to_vec()
3492    /// ];
3493    /// assert_eq!(Ok(expected_names), names);
3494    ///
3495    /// // If the value is nullable, the output will be nullable
3496    /// let names = users.select(hair_color.concat("ish".as_bytes())).load(connection);
3497    /// let expected_names = vec![
3498    ///     Some(b"Greenish".to_vec()),
3499    ///     None,
3500    /// ];
3501    /// assert_eq!(Ok(expected_names), names);
3502    /// # }
3503    /// ```
3504    fn concat<T>(self, other: T) -> dsl::Concat<Self, T>
3505    where
3506        Self::SqlType: SqlType,
3507        T: AsExpression<Self::SqlType>,
3508    {
3509        Grouped(Concat::new(self, other.as_expression()))
3510    }
3511
3512    /// Creates a PostgreSQL binary `LIKE` expression.
3513    ///
3514    /// This method is case sensitive. There is no case-insensitive
3515    /// equivalent as of PostgreSQL 14.
3516    ///
3517    /// # Examples
3518    ///
3519    /// ```rust
3520    /// # include!("../../doctest_setup.rs");
3521    /// #
3522    /// # table! {
3523    /// #     users {
3524    /// #         id -> Integer,
3525    /// #         name -> Binary,
3526    /// #     }
3527    /// # }
3528    /// #
3529    /// # fn main() {
3530    /// #     use self::users::dsl::*;
3531    /// #     use diesel::insert_into;
3532    /// #
3533    /// #     let connection = &mut connection_no_data();
3534    /// #     diesel::sql_query("CREATE TABLE users (
3535    /// #         id INTEGER PRIMARY KEY,
3536    /// #         name BYTEA NOT NULL
3537    /// #     )").execute(connection).unwrap();
3538    /// #
3539    /// #     insert_into(users)
3540    /// #         .values(&vec![
3541    /// #             (id.eq(1), name.eq("Sean".as_bytes())),
3542    /// #             (id.eq(2), name.eq("Tess".as_bytes()))
3543    /// #         ])
3544    /// #         .execute(connection)
3545    /// #         .unwrap();
3546    /// #
3547    /// let starts_with_s = users
3548    ///     .select(name)
3549    ///     .filter(name.like(b"S%".to_vec()))
3550    ///     .load(connection);
3551    /// assert_eq!(Ok(vec![b"Sean".to_vec()]), starts_with_s);
3552    /// # }
3553    /// ```
3554    fn like<T>(self, other: T) -> dsl::Like<Self, T>
3555    where
3556        Self::SqlType: SqlType,
3557        T: AsExpression<Self::SqlType>,
3558    {
3559        Grouped(Like::new(self, other.as_expression()))
3560    }
3561
3562    /// Creates a PostgreSQL binary `LIKE` expression.
3563    ///
3564    /// This method is case sensitive. There is no case-insensitive
3565    /// equivalent as of PostgreSQL 14.
3566    ///
3567    /// # Examples
3568    ///
3569    /// ```rust
3570    /// # include!("../../doctest_setup.rs");
3571    /// #
3572    /// # table! {
3573    /// #     users {
3574    /// #         id -> Integer,
3575    /// #         name -> Binary,
3576    /// #     }
3577    /// # }
3578    /// #
3579    /// # fn main() {
3580    /// #     use self::users::dsl::*;
3581    /// #     use diesel::insert_into;
3582    /// #
3583    /// #     let connection = &mut connection_no_data();
3584    /// #     diesel::sql_query("CREATE TABLE users (
3585    /// #         id INTEGER PRIMARY KEY,
3586    /// #         name BYTEA NOT NULL
3587    /// #     )").execute(connection).unwrap();
3588    /// #
3589    /// #     insert_into(users)
3590    /// #         .values(&vec![
3591    /// #             (id.eq(1), name.eq("Sean".as_bytes())),
3592    /// #             (id.eq(2), name.eq("Tess".as_bytes()))
3593    /// #         ])
3594    /// #         .execute(connection)
3595    /// #         .unwrap();
3596    /// #
3597    /// let starts_with_s = users
3598    ///     .select(name)
3599    ///     .filter(name.not_like(b"S%".to_vec()))
3600    ///     .load(connection);
3601    /// assert_eq!(Ok(vec![b"Tess".to_vec()]), starts_with_s);
3602    /// # }
3603    /// ```
3604    fn not_like<T>(self, other: T) -> dsl::NotLike<Self, T>
3605    where
3606        Self::SqlType: SqlType,
3607        T: AsExpression<Self::SqlType>,
3608    {
3609        Grouped(NotLike::new(self, other.as_expression()))
3610    }
3611}
3612
3613#[doc(hidden)]
3614impl<T> PgBinaryExpressionMethods for T
3615where
3616    T: Expression,
3617    T::SqlType: BinaryOrNullableBinary,
3618{
3619}
3620
3621pub(in crate::pg) mod private {
3622    use crate::sql_types::{
3623        AllAreNullable, Array, Binary, Cidr, Inet, Integer, Json, Jsonb, MaybeNullableType,
3624        Multirange, Nullable, OneIsNullable, Range, Record, SingleValue, SqlType, Text,
3625    };
3626    use crate::{Expression, IntoSql};
3627
3628    /// Marker trait used to implement `ArrayExpressionMethods` on the appropriate
3629    /// types. Once coherence takes associated types into account, we can remove
3630    /// this trait.
3631    #[diagnostic::on_unimplemented(
3632        message = "`{Self}` is neither `diesel::sql_types::Array<_>` nor `diesel::sql_types::Nullable<Array<_>>`",
3633        note = "try to provide an expression that produces one of the expected sql types"
3634    )]
3635    pub trait ArrayOrNullableArray {
3636        type Inner;
3637    }
3638
3639    impl<T> ArrayOrNullableArray for Array<T> {
3640        type Inner = T;
3641    }
3642    impl<T> ArrayOrNullableArray for Nullable<Array<T>> {
3643        type Inner = T;
3644    }
3645
3646    /// Marker trait used to implement `PgNetExpressionMethods` on the appropriate types.
3647    #[diagnostic::on_unimplemented(
3648        message = "`{Self}` is neither `diesel::sql_types::Inet`, `diesel::sql_types::Cidr`, `diesel::sql_types::Nullable<Inet>` nor `diesel::sql_types::Nullable<Cidr>",
3649        note = "try to provide an expression that produces one of the expected sql types"
3650    )]
3651    pub trait InetOrCidr {}
3652
3653    impl InetOrCidr for Inet {}
3654    impl InetOrCidr for Cidr {}
3655    impl InetOrCidr for Nullable<Inet> {}
3656    impl InetOrCidr for Nullable<Cidr> {}
3657
3658    /// Marker trait used to implement `PgTextExpressionMethods` on the appropriate
3659    /// types. Once coherence takes associated types into account, we can remove
3660    /// this trait.
3661    #[diagnostic::on_unimplemented(
3662        message = "`{Self}` is neither `diesel::sql_types::Text` nor `diesel::sql_types::Nullable<Text>`",
3663        note = "try to provide an expression that produces one of the expected sql types"
3664    )]
3665    pub trait TextOrNullableText {}
3666
3667    impl TextOrNullableText for Text {}
3668    impl TextOrNullableText for Nullable<Text> {}
3669
3670    /// Marker trait used to extract the inner type
3671    /// of our `Range<T>` and `Multirange<T>` sql type, used to implement `PgRangeExpressionMethods`
3672    pub trait RangeOrMultirange: SqlType + SingleValue {
3673        type Inner: SingleValue;
3674    }
3675
3676    impl<ST> RangeOrMultirange for Range<ST>
3677    where
3678        Self: 'static,
3679        ST: SingleValue,
3680    {
3681        type Inner = ST;
3682    }
3683
3684    impl<ST> RangeOrMultirange for Multirange<ST>
3685    where
3686        Self: 'static,
3687        ST: SingleValue,
3688    {
3689        type Inner = ST;
3690    }
3691
3692    /// Marker trait used to implement `PgRangeExpressionMethods` on the appropriate
3693    /// types. Once coherence takes associated types into account, we can remove
3694    /// this trait.
3695    #[diagnostic::on_unimplemented(
3696        message = "`{Self}` is neither `diesel::sql_types::Range<_>` nor `diesel::sql_types::Nullable<Range<_>>`",
3697        note = "try to provide an expression that produces one of the expected sql types"
3698    )]
3699    pub trait RangeOrNullableRange {
3700        type Inner: SingleValue;
3701    }
3702
3703    impl<ST: SingleValue> RangeOrNullableRange for Range<ST> {
3704        type Inner = ST;
3705    }
3706    impl<ST: SingleValue> RangeOrNullableRange for Nullable<Range<ST>> {
3707        type Inner = ST;
3708    }
3709
3710    /// Marker trait used to implement `PgRangeExpressionMethods` on the appropriate
3711    /// types. Once coherence takes associated types into account, we can remove
3712    /// this trait.
3713    #[diagnostic::on_unimplemented(
3714        message = "`{Self}` is neither `diesel::sql_types::Range<_>` nor `diesel::sql_types::Nullable<Range<_>>`",
3715        note = "try to provide an expression that produces one of the expected sql types"
3716    )]
3717    pub trait MultirangeOrNullableMultirange {
3718        type Inner: SingleValue;
3719        type Range: SingleValue;
3720    }
3721
3722    impl<ST: SingleValue> MultirangeOrNullableMultirange for Multirange<ST> {
3723        type Inner = ST;
3724        type Range = Range<ST>;
3725    }
3726    impl<ST: SingleValue> MultirangeOrNullableMultirange for Nullable<Multirange<ST>> {
3727        type Inner = ST;
3728        type Range = Nullable<Range<ST>>;
3729    }
3730
3731    /// Marker trait used to implement `PgRangeExpressionMethods` on the appropriate
3732    /// types. Once coherence takes associated types into account, we can remove
3733    /// this trait.
3734    #[diagnostic::on_unimplemented(
3735        message = "`{Self}` is neither `diesel::sql_types::Range<_>` nor `diesel::sql_types::Multirange<_>`",
3736        note = "try to provide an expression that produces one of the expected sql types"
3737    )]
3738    pub trait MultirangeOrRangeMaybeNullable {
3739        type Inner: SingleValue;
3740    }
3741
3742    impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Range<ST> {
3743        type Inner = ST;
3744    }
3745    impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Nullable<Range<ST>> {
3746        type Inner = ST;
3747    }
3748    impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Multirange<ST> {
3749        type Inner = ST;
3750    }
3751    impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Nullable<Multirange<ST>> {
3752        type Inner = ST;
3753    }
3754
3755    /// Marker trait used to implement `PgJsonbExpressionMethods` on the appropriate types.
3756    #[diagnostic::on_unimplemented(
3757        message = "`{Self}` is neither `diesel::sql_types::Jsonb` nor `diesel::sql_types::Nullable<Jsonb>`",
3758        note = "try to provide an expression that produces one of the expected sql types"
3759    )]
3760    pub trait JsonbOrNullableJsonb {}
3761
3762    impl JsonbOrNullableJsonb for Jsonb {}
3763    impl JsonbOrNullableJsonb for Nullable<Jsonb> {}
3764
3765    #[diagnostic::on_unimplemented(
3766        message = "`{Self}` is neither `diesel::sql_types::Json` nor `diesel::sql_types::Nullable<Json>`",
3767        note = "try to provide an expression that produces one of the expected sql types"
3768    )]
3769    pub trait JsonOrNullableJson {}
3770
3771    impl JsonOrNullableJson for Json {}
3772    impl JsonOrNullableJson for Nullable<Json> {}
3773
3774    /// A trait that describes valid json indices used by postgresql
3775    pub trait JsonRemoveIndex {
3776        /// The Expression node created by this index type
3777        type Expression: Expression;
3778
3779        /// Convert a index value into the corresponding index expression
3780        fn into_json_index_expression(self) -> Self::Expression;
3781    }
3782
3783    impl<'a> JsonRemoveIndex for &'a str {
3784        type Expression = crate::dsl::AsExprOf<&'a str, crate::sql_types::Text>;
3785
3786        fn into_json_index_expression(self) -> Self::Expression {
3787            self.into_sql::<Text>()
3788        }
3789    }
3790
3791    impl JsonRemoveIndex for String {
3792        type Expression = crate::dsl::AsExprOf<String, crate::sql_types::Text>;
3793
3794        fn into_json_index_expression(self) -> Self::Expression {
3795            self.into_sql::<Text>()
3796        }
3797    }
3798
3799    impl JsonRemoveIndex for Vec<String> {
3800        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
3801
3802        fn into_json_index_expression(self) -> Self::Expression {
3803            self.into_sql::<Array<Text>>()
3804        }
3805    }
3806
3807    impl JsonRemoveIndex for Vec<&str> {
3808        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
3809
3810        fn into_json_index_expression(self) -> Self::Expression {
3811            self.into_sql::<Array<Text>>()
3812        }
3813    }
3814
3815    impl<'a> JsonRemoveIndex for &'a [&'a str] {
3816        type Expression = crate::dsl::AsExprOf<Self, Array<Text>>;
3817
3818        fn into_json_index_expression(self) -> Self::Expression {
3819            self.into_sql::<Array<Text>>()
3820        }
3821    }
3822
3823    impl JsonRemoveIndex for i32 {
3824        type Expression = crate::dsl::AsExprOf<i32, crate::sql_types::Int4>;
3825
3826        fn into_json_index_expression(self) -> Self::Expression {
3827            self.into_sql::<crate::sql_types::Int4>()
3828        }
3829    }
3830
3831    impl<T> JsonRemoveIndex for T
3832    where
3833        T: Expression,
3834        T::SqlType: TextArrayOrTextOrInteger,
3835    {
3836        type Expression = Self;
3837
3838        fn into_json_index_expression(self) -> Self::Expression {
3839            self
3840        }
3841    }
3842
3843    #[diagnostic::on_unimplemented(
3844        message = "`{Self}` is neither `diesel::sql_types::Text`, `diesel::sql_types::Integer` nor `diesel::sql_types::Array<Text>`",
3845        note = "try to provide an expression that produces one of the expected sql types"
3846    )]
3847    pub trait TextArrayOrTextOrInteger {}
3848
3849    impl TextArrayOrTextOrInteger for Array<Text> {}
3850    impl TextArrayOrTextOrInteger for Text {}
3851    impl TextArrayOrTextOrInteger for Integer {}
3852
3853    /// Marker trait used to implement `PgAnyJsonExpressionMethods` on the appropriate types.
3854    #[diagnostic::on_unimplemented(
3855        message = "`{Self}` is neither `diesel::sql_types::Json`, `diesel::sql_types::Jsonb`, `diesel::sql_types::Nullable<Json>` nor `diesel::sql_types::Nullable<Jsonb>`",
3856        note = "try to provide an expression that produces one of the expected sql types"
3857    )]
3858    pub trait JsonOrNullableJsonOrJsonbOrNullableJsonb {}
3859    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Json {}
3860    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Json> {}
3861    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Jsonb {}
3862    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Jsonb> {}
3863
3864    pub trait JsonIndex {
3865        type Expression: Expression;
3866
3867        fn into_json_index_expression(self) -> Self::Expression;
3868    }
3869
3870    impl<'a> JsonIndex for &'a str {
3871        type Expression = crate::dsl::AsExprOf<&'a str, crate::sql_types::Text>;
3872
3873        fn into_json_index_expression(self) -> Self::Expression {
3874            self.into_sql::<Text>()
3875        }
3876    }
3877
3878    impl JsonIndex for String {
3879        type Expression = crate::dsl::AsExprOf<String, crate::sql_types::Text>;
3880
3881        fn into_json_index_expression(self) -> Self::Expression {
3882            self.into_sql::<Text>()
3883        }
3884    }
3885
3886    impl JsonIndex for i32 {
3887        type Expression = crate::dsl::AsExprOf<i32, crate::sql_types::Int4>;
3888
3889        fn into_json_index_expression(self) -> Self::Expression {
3890            self.into_sql::<crate::sql_types::Int4>()
3891        }
3892    }
3893
3894    impl<T> JsonIndex for T
3895    where
3896        T: Expression,
3897        T::SqlType: TextOrInteger,
3898    {
3899        type Expression = Self;
3900
3901        fn into_json_index_expression(self) -> Self::Expression {
3902            self
3903        }
3904    }
3905
3906    #[diagnostic::on_unimplemented(
3907        message = "`{Self}` is neither `diesel::sql_types::Text` nor `diesel::sql_types::Integer`",
3908        note = "try to provide an expression that produces one of the expected sql types"
3909    )]
3910    pub trait TextOrInteger {}
3911    impl TextOrInteger for Text {}
3912    impl TextOrInteger for Integer {}
3913
3914    #[diagnostic::on_unimplemented(
3915        message = "`{Self}` is neither `diesel::sql_types::Binary` nor `diesel::sql_types::Nullable<Binary>`",
3916        note = "try to provide an expression that produces one of the expected sql types"
3917    )]
3918    pub trait BinaryOrNullableBinary {}
3919
3920    impl BinaryOrNullableBinary for Binary {}
3921    impl BinaryOrNullableBinary for Nullable<Binary> {}
3922
3923    pub trait MaybeNullableValue<T>: SingleValue {
3924        type Out: SingleValue;
3925    }
3926
3927    impl<T, O> MaybeNullableValue<O> for T
3928    where
3929        T: SingleValue,
3930        T::IsNull: MaybeNullableType<O>,
3931        <T::IsNull as MaybeNullableType<O>>::Out: SingleValue,
3932    {
3933        type Out = <T::IsNull as MaybeNullableType<O>>::Out;
3934    }
3935
3936    pub trait CombinedNullableValue<O, Out>: SingleValue {
3937        type Out: SingleValue;
3938    }
3939
3940    impl<T, O, Out> CombinedNullableValue<O, Out> for T
3941    where
3942        T: SingleValue,
3943        O: SingleValue,
3944        T::IsNull: OneIsNullable<O::IsNull>,
3945        <T::IsNull as OneIsNullable<O::IsNull>>::Out: MaybeNullableType<Out>,
3946        <<T::IsNull as OneIsNullable<O::IsNull>>::Out as MaybeNullableType<Out>>::Out: SingleValue,
3947    {
3948        type Out = <<T::IsNull as OneIsNullable<O::IsNull>>::Out as MaybeNullableType<Out>>::Out;
3949    }
3950
3951    #[diagnostic::on_unimplemented(
3952        message = "`{Self}` is neither `Array<Text>`, `Array<Nullable<Text>>`,\
3953                   `Nullable<Array<Text>>` nor `diesel::sql_types::Nullable<Array<Nullable<Text>>>`",
3954        note = "try to provide an expression that produces one of the expected sql types"
3955    )]
3956    pub trait TextArrayOrNullableTextArray {}
3957
3958    impl TextArrayOrNullableTextArray for Array<Text> {}
3959    impl TextArrayOrNullableTextArray for Array<Nullable<Text>> {}
3960    impl TextArrayOrNullableTextArray for Nullable<Array<Text>> {}
3961    impl TextArrayOrNullableTextArray for Nullable<Array<Nullable<Text>>> {}
3962
3963    #[diagnostic::on_unimplemented(
3964        message = "`{Self}` is neither `Record<T>` nor `Nullable<Record<T>>`",
3965        note = "try to provide an expression that produces one of the expected sql types"
3966    )]
3967    pub trait RecordOrNullableRecord {}
3968
3969    impl<T> RecordOrNullableRecord for Record<T> {}
3970    impl<T> RecordOrNullableRecord for Nullable<Record<T>> {}
3971
3972    pub trait CombinedAllNullableValue<O, Out>: SingleValue {
3973        type Out: SingleValue;
3974    }
3975
3976    impl<T, O, Out> CombinedAllNullableValue<O, Out> for T
3977    where
3978        T: SingleValue,
3979        O: SingleValue,
3980        T::IsNull: AllAreNullable<O::IsNull>,
3981        <T::IsNull as AllAreNullable<O::IsNull>>::Out: MaybeNullableType<Out>,
3982        <<T::IsNull as AllAreNullable<O::IsNull>>::Out as MaybeNullableType<Out>>::Out: SingleValue,
3983    {
3984        type Out = <<T::IsNull as AllAreNullable<O::IsNull>>::Out as MaybeNullableType<Out>>::Out;
3985    }
3986}