Skip to main content

diesel/pg/expression/
expression_methods.rs

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