diesel/pg/expression/
expression_methods.rs

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