diesel/pg/expression/
expression_methods.rs

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