1use crate::dialect::DialectTypes;
25use crate::sql::{SQL, Token};
26use crate::traits::SQLParam;
27use crate::types::{Compatible, DataType, Textual};
28
29use super::{AggOr, AggregateKind, Expr, NonNull, SQLExpr};
30
31fn binary_op<'a, V, L, R>(left: L, operator: Token, right: R) -> SQL<'a, V>
36where
37 V: SQLParam + 'a,
38 L: Expr<'a, V>,
39 R: ComparisonOperand<'a, V, L::SQLType>,
40{
41 let left_sql = operand_sql(left);
42 let right_sql = right.into_comparison_sql();
43
44 left_sql.push(operator).append(right_sql)
45}
46
47#[inline]
48fn operand_sql<'a, V, T>(value: T) -> SQL<'a, V>
49where
50 V: SQLParam + 'a,
51 T: Expr<'a, V>,
52{
53 value.into_expr_sql()
54}
55
56pub trait ComparisonOperand<'a, V, Expected>
67where
68 V: SQLParam + 'a,
69 Expected: DataType,
70{
71 type SQLType: DataType;
72 type Aggregate: AggregateKind;
73
74 fn into_comparison_sql(self) -> SQL<'a, V>;
75}
76
77impl<'a, V, Expected, R> ComparisonOperand<'a, V, Expected> for R
78where
79 V: SQLParam + 'a,
80 Expected: DataType + Compatible<R::SQLType>,
81 R: Expr<'a, V>,
82{
83 type SQLType = R::SQLType;
84 type Aggregate = R::Aggregate;
85
86 fn into_comparison_sql(self) -> SQL<'a, V> {
87 self.into_expr_sql()
88 }
89}
90
91#[allow(clippy::type_complexity)]
114pub fn eq<'a, V, L, R>(
115 left: L,
116 right: R,
117) -> SQLExpr<
118 'a,
119 V,
120 <V::DialectMarker as DialectTypes>::Bool,
121 NonNull,
122 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
123>
124where
125 V: SQLParam + 'a,
126 L: Expr<'a, V>,
127 R: ComparisonOperand<'a, V, L::SQLType>,
128 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
129{
130 SQLExpr::new(binary_op(left, Token::EQ, right))
131}
132
133#[allow(clippy::type_complexity)]
137pub fn neq<'a, V, L, R>(
138 left: L,
139 right: R,
140) -> SQLExpr<
141 'a,
142 V,
143 <V::DialectMarker as DialectTypes>::Bool,
144 NonNull,
145 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
146>
147where
148 V: SQLParam + 'a,
149 L: Expr<'a, V>,
150 R: ComparisonOperand<'a, V, L::SQLType>,
151 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
152{
153 SQLExpr::new(binary_op(left, Token::NE, right))
154}
155
156#[allow(clippy::type_complexity)]
164pub fn gt<'a, V, L, R>(
165 left: L,
166 right: R,
167) -> SQLExpr<
168 'a,
169 V,
170 <V::DialectMarker as DialectTypes>::Bool,
171 NonNull,
172 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
173>
174where
175 V: SQLParam + 'a,
176 L: Expr<'a, V>,
177 R: ComparisonOperand<'a, V, L::SQLType>,
178 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
179{
180 SQLExpr::new(binary_op(left, Token::GT, right))
181}
182
183#[allow(clippy::type_complexity)]
187pub fn gte<'a, V, L, R>(
188 left: L,
189 right: R,
190) -> SQLExpr<
191 'a,
192 V,
193 <V::DialectMarker as DialectTypes>::Bool,
194 NonNull,
195 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
196>
197where
198 V: SQLParam + 'a,
199 L: Expr<'a, V>,
200 R: ComparisonOperand<'a, V, L::SQLType>,
201 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
202{
203 SQLExpr::new(binary_op(left, Token::GE, right))
204}
205
206#[allow(clippy::type_complexity)]
210pub fn lt<'a, V, L, R>(
211 left: L,
212 right: R,
213) -> SQLExpr<
214 'a,
215 V,
216 <V::DialectMarker as DialectTypes>::Bool,
217 NonNull,
218 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
219>
220where
221 V: SQLParam + 'a,
222 L: Expr<'a, V>,
223 R: ComparisonOperand<'a, V, L::SQLType>,
224 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
225{
226 SQLExpr::new(binary_op(left, Token::LT, right))
227}
228
229#[allow(clippy::type_complexity)]
233pub fn lte<'a, V, L, R>(
234 left: L,
235 right: R,
236) -> SQLExpr<
237 'a,
238 V,
239 <V::DialectMarker as DialectTypes>::Bool,
240 NonNull,
241 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
242>
243where
244 V: SQLParam + 'a,
245 L: Expr<'a, V>,
246 R: ComparisonOperand<'a, V, L::SQLType>,
247 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
248{
249 SQLExpr::new(binary_op(left, Token::LE, right))
250}
251
252#[allow(clippy::type_complexity)]
272pub fn like<'a, V, L, R>(
273 left: L,
274 pattern: R,
275) -> SQLExpr<
276 'a,
277 V,
278 <V::DialectMarker as DialectTypes>::Bool,
279 NonNull,
280 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
281>
282where
283 V: SQLParam + 'a,
284 L: Expr<'a, V>,
285 R: ComparisonOperand<'a, V, L::SQLType>,
286 L::SQLType: Textual,
287 <R as ComparisonOperand<'a, V, L::SQLType>>::SQLType: Textual,
288 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
289{
290 SQLExpr::new(
291 operand_sql(left)
292 .push(Token::LIKE)
293 .append(pattern.into_comparison_sql()),
294 )
295}
296
297#[allow(clippy::type_complexity)]
301pub fn not_like<'a, V, L, R>(
302 left: L,
303 pattern: R,
304) -> SQLExpr<
305 'a,
306 V,
307 <V::DialectMarker as DialectTypes>::Bool,
308 NonNull,
309 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
310>
311where
312 V: SQLParam + 'a,
313 L: Expr<'a, V>,
314 R: ComparisonOperand<'a, V, L::SQLType>,
315 L::SQLType: Textual,
316 <R as ComparisonOperand<'a, V, L::SQLType>>::SQLType: Textual,
317 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
318{
319 SQLExpr::new(
320 operand_sql(left)
321 .push(Token::NOT)
322 .push(Token::LIKE)
323 .append(pattern.into_comparison_sql()),
324 )
325}
326
327#[allow(clippy::type_complexity)]
336pub fn between<'a, V, E, L, H>(
337 expr: E,
338 low: L,
339 high: H,
340) -> SQLExpr<
341 'a,
342 V,
343 <V::DialectMarker as DialectTypes>::Bool,
344 NonNull,
345 <<E::Aggregate as AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output as AggOr<<H as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output,
346>
347where
348 V: SQLParam + 'a,
349 E: Expr<'a, V>,
350 L: ComparisonOperand<'a, V, E::SQLType>,
351 H: ComparisonOperand<'a, V, E::SQLType>,
352 E::Aggregate: AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>,
353 <E::Aggregate as AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output:
354 AggOr<<H as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>,
355{
356 SQLExpr::new(
357 SQL::from(Token::LPAREN)
358 .append(operand_sql(expr))
359 .push(Token::BETWEEN)
360 .append(low.into_comparison_sql())
361 .push(Token::AND)
362 .append(high.into_comparison_sql())
363 .push(Token::RPAREN),
364 )
365}
366
367#[allow(clippy::type_complexity)]
371pub fn not_between<'a, V, E, L, H>(
372 expr: E,
373 low: L,
374 high: H,
375) -> SQLExpr<
376 'a,
377 V,
378 <V::DialectMarker as DialectTypes>::Bool,
379 NonNull,
380 <<E::Aggregate as AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output as AggOr<<H as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output,
381>
382where
383 V: SQLParam + 'a,
384 E: Expr<'a, V>,
385 L: ComparisonOperand<'a, V, E::SQLType>,
386 H: ComparisonOperand<'a, V, E::SQLType>,
387 E::Aggregate: AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>,
388 <E::Aggregate as AggOr<<L as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>>::Output:
389 AggOr<<H as ComparisonOperand<'a, V, E::SQLType>>::Aggregate>,
390{
391 SQLExpr::new(
392 SQL::from(Token::LPAREN)
393 .append(operand_sql(expr))
394 .push(Token::NOT)
395 .push(Token::BETWEEN)
396 .append(low.into_comparison_sql())
397 .push(Token::AND)
398 .append(high.into_comparison_sql())
399 .push(Token::RPAREN),
400 )
401}
402
403pub fn is_null<'a, V, E>(
412 expr: E,
413) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, E::Aggregate>
414where
415 V: SQLParam + 'a,
416 E: Expr<'a, V>,
417{
418 SQLExpr::new(operand_sql(expr).push(Token::IS).push(Token::NULL))
419}
420
421pub fn is_not_null<'a, V, E>(
426 expr: E,
427) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, E::Aggregate>
428where
429 V: SQLParam + 'a,
430 E: Expr<'a, V>,
431{
432 SQLExpr::new(
433 operand_sql(expr)
434 .push(Token::IS)
435 .push(Token::NOT)
436 .push(Token::NULL),
437 )
438}
439
440#[allow(clippy::type_complexity)]
453pub fn is_distinct_from<'a, V, L, R>(
454 left: L,
455 right: R,
456) -> SQLExpr<
457 'a,
458 V,
459 <V::DialectMarker as DialectTypes>::Bool,
460 NonNull,
461 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
462>
463where
464 V: SQLParam + 'a,
465 L: Expr<'a, V>,
466 R: ComparisonOperand<'a, V, L::SQLType>,
467 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
468{
469 SQLExpr::new(
470 operand_sql(left)
471 .push(Token::IS)
472 .push(Token::DISTINCT)
473 .push(Token::FROM)
474 .append(right.into_comparison_sql()),
475 )
476}
477
478#[allow(clippy::type_complexity)]
486pub fn is_not_distinct_from<'a, V, L, R>(
487 left: L,
488 right: R,
489) -> SQLExpr<
490 'a,
491 V,
492 <V::DialectMarker as DialectTypes>::Bool,
493 NonNull,
494 <L::Aggregate as AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>>::Output,
495>
496where
497 V: SQLParam + 'a,
498 L: Expr<'a, V>,
499 R: ComparisonOperand<'a, V, L::SQLType>,
500 L::Aggregate: AggOr<<R as ComparisonOperand<'a, V, L::SQLType>>::Aggregate>,
501{
502 SQLExpr::new(
503 operand_sql(left)
504 .push(Token::IS)
505 .push(Token::NOT)
506 .push(Token::DISTINCT)
507 .push(Token::FROM)
508 .append(right.into_comparison_sql()),
509 )
510}
511
512pub fn is_true<'a, V, E>(
523 expr: E,
524) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, E::Aggregate>
525where
526 V: SQLParam + 'a,
527 E: Expr<'a, V>,
528{
529 SQLExpr::new(operand_sql(expr).push(Token::IS).append(SQL::raw("TRUE")))
530}
531
532pub fn is_false<'a, V, E>(
539 expr: E,
540) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, E::Aggregate>
541where
542 V: SQLParam + 'a,
543 E: Expr<'a, V>,
544{
545 SQLExpr::new(operand_sql(expr).push(Token::IS).append(SQL::raw("FALSE")))
546}
547
548pub trait ExprExt<'a, V: SQLParam>: Expr<'a, V> + Sized {
568 #[allow(clippy::type_complexity)]
576 fn eq<R>(
577 self,
578 other: R,
579 ) -> SQLExpr<
580 'a,
581 V,
582 <V::DialectMarker as DialectTypes>::Bool,
583 NonNull,
584 <Self::Aggregate as AggOr<
585 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
586 >>::Output,
587 >
588 where
589 R: ComparisonOperand<'a, V, Self::SQLType>,
590 Self::Aggregate:
591 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
592 {
593 eq(self, other)
594 }
595
596 #[allow(clippy::type_complexity)]
604 fn ne<R>(
605 self,
606 other: R,
607 ) -> SQLExpr<
608 'a,
609 V,
610 <V::DialectMarker as DialectTypes>::Bool,
611 NonNull,
612 <Self::Aggregate as AggOr<
613 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
614 >>::Output,
615 >
616 where
617 R: ComparisonOperand<'a, V, Self::SQLType>,
618 Self::Aggregate:
619 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
620 {
621 neq(self, other)
622 }
623
624 #[allow(clippy::type_complexity)]
632 fn gt<R>(
633 self,
634 other: R,
635 ) -> SQLExpr<
636 'a,
637 V,
638 <V::DialectMarker as DialectTypes>::Bool,
639 NonNull,
640 <Self::Aggregate as AggOr<
641 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
642 >>::Output,
643 >
644 where
645 R: ComparisonOperand<'a, V, Self::SQLType>,
646 Self::Aggregate:
647 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
648 {
649 gt(self, other)
650 }
651
652 #[allow(clippy::type_complexity)]
660 fn ge<R>(
661 self,
662 other: R,
663 ) -> SQLExpr<
664 'a,
665 V,
666 <V::DialectMarker as DialectTypes>::Bool,
667 NonNull,
668 <Self::Aggregate as AggOr<
669 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
670 >>::Output,
671 >
672 where
673 R: ComparisonOperand<'a, V, Self::SQLType>,
674 Self::Aggregate:
675 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
676 {
677 gte(self, other)
678 }
679
680 #[allow(clippy::type_complexity)]
688 fn lt<R>(
689 self,
690 other: R,
691 ) -> SQLExpr<
692 'a,
693 V,
694 <V::DialectMarker as DialectTypes>::Bool,
695 NonNull,
696 <Self::Aggregate as AggOr<
697 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
698 >>::Output,
699 >
700 where
701 R: ComparisonOperand<'a, V, Self::SQLType>,
702 Self::Aggregate:
703 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
704 {
705 lt(self, other)
706 }
707
708 #[allow(clippy::type_complexity)]
716 fn le<R>(
717 self,
718 other: R,
719 ) -> SQLExpr<
720 'a,
721 V,
722 <V::DialectMarker as DialectTypes>::Bool,
723 NonNull,
724 <Self::Aggregate as AggOr<
725 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
726 >>::Output,
727 >
728 where
729 R: ComparisonOperand<'a, V, Self::SQLType>,
730 Self::Aggregate:
731 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
732 {
733 lte(self, other)
734 }
735
736 #[allow(clippy::type_complexity)]
744 fn like<R>(
745 self,
746 pattern: R,
747 ) -> SQLExpr<
748 'a,
749 V,
750 <V::DialectMarker as DialectTypes>::Bool,
751 NonNull,
752 <Self::Aggregate as AggOr<
753 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
754 >>::Output,
755 >
756 where
757 R: ComparisonOperand<'a, V, Self::SQLType>,
758 Self::SQLType: Textual,
759 <R as ComparisonOperand<'a, V, Self::SQLType>>::SQLType: Textual,
760 Self::Aggregate:
761 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
762 {
763 like(self, pattern)
764 }
765
766 #[allow(clippy::type_complexity)]
774 fn not_like<R>(
775 self,
776 pattern: R,
777 ) -> SQLExpr<
778 'a,
779 V,
780 <V::DialectMarker as DialectTypes>::Bool,
781 NonNull,
782 <Self::Aggregate as AggOr<
783 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
784 >>::Output,
785 >
786 where
787 R: ComparisonOperand<'a, V, Self::SQLType>,
788 Self::SQLType: Textual,
789 <R as ComparisonOperand<'a, V, Self::SQLType>>::SQLType: Textual,
790 Self::Aggregate:
791 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
792 {
793 not_like(self, pattern)
794 }
795
796 #[allow(clippy::wrong_self_convention)]
804 fn is_null(
805 self,
806 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate> {
807 is_null(self)
808 }
809
810 #[allow(clippy::wrong_self_convention)]
818 fn is_not_null(
819 self,
820 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate> {
821 is_not_null(self)
822 }
823
824 #[allow(clippy::type_complexity)]
834 fn between<L, H>(
835 self,
836 low: L,
837 high: H,
838 ) -> SQLExpr<
839 'a,
840 V,
841 <V::DialectMarker as DialectTypes>::Bool,
842 NonNull,
843 <<Self::Aggregate as AggOr<
844 <L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
845 >>::Output as AggOr<
846 <H as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
847 >>::Output,
848 >
849 where
850 L: ComparisonOperand<'a, V, Self::SQLType>,
851 H: ComparisonOperand<'a, V, Self::SQLType>,
852 Self::Aggregate:
853 AggOr<<L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
854 <Self::Aggregate as AggOr<
855 <L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
856 >>::Output:
857 AggOr<<H as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
858 {
859 between(self, low, high)
860 }
861
862 #[allow(clippy::type_complexity)]
872 fn not_between<L, H>(
873 self,
874 low: L,
875 high: H,
876 ) -> SQLExpr<
877 'a,
878 V,
879 <V::DialectMarker as DialectTypes>::Bool,
880 NonNull,
881 <<Self::Aggregate as AggOr<
882 <L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
883 >>::Output as AggOr<
884 <H as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
885 >>::Output,
886 >
887 where
888 L: ComparisonOperand<'a, V, Self::SQLType>,
889 H: ComparisonOperand<'a, V, Self::SQLType>,
890 Self::Aggregate:
891 AggOr<<L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
892 <Self::Aggregate as AggOr<
893 <L as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
894 >>::Output:
895 AggOr<<H as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
896 {
897 not_between(self, low, high)
898 }
899
900 fn in_array<I, R>(
911 self,
912 values: I,
913 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate>
914 where
915 I: IntoIterator<Item = R>,
916 R: Expr<'a, V>,
917 Self::SQLType: Compatible<R::SQLType>,
918 {
919 crate::expr::in_array(self, values)
920 }
921
922 fn not_in_array<I, R>(
933 self,
934 values: I,
935 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate>
936 where
937 I: IntoIterator<Item = R>,
938 R: Expr<'a, V>,
939 Self::SQLType: Compatible<R::SQLType>,
940 {
941 crate::expr::not_in_array(self, values)
942 }
943
944 fn in_subquery<S>(
946 self,
947 subquery: S,
948 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate>
949 where
950 S: Expr<'a, V>,
951 Self::SQLType: Compatible<S::SQLType>,
952 {
953 crate::expr::in_subquery(self, subquery)
954 }
955
956 fn not_in_subquery<S>(
958 self,
959 subquery: S,
960 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate>
961 where
962 S: Expr<'a, V>,
963 Self::SQLType: Compatible<S::SQLType>,
964 {
965 crate::expr::not_in_subquery(self, subquery)
966 }
967
968 #[allow(clippy::type_complexity, clippy::wrong_self_convention)]
977 fn is_distinct_from<R>(
978 self,
979 other: R,
980 ) -> SQLExpr<
981 'a,
982 V,
983 <V::DialectMarker as DialectTypes>::Bool,
984 NonNull,
985 <Self::Aggregate as AggOr<
986 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
987 >>::Output,
988 >
989 where
990 R: ComparisonOperand<'a, V, Self::SQLType>,
991 Self::Aggregate:
992 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
993 {
994 is_distinct_from(self, other)
995 }
996
997 #[allow(clippy::type_complexity, clippy::wrong_self_convention)]
1006 fn is_not_distinct_from<R>(
1007 self,
1008 other: R,
1009 ) -> SQLExpr<
1010 'a,
1011 V,
1012 <V::DialectMarker as DialectTypes>::Bool,
1013 NonNull,
1014 <Self::Aggregate as AggOr<
1015 <R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate,
1016 >>::Output,
1017 >
1018 where
1019 R: ComparisonOperand<'a, V, Self::SQLType>,
1020 Self::Aggregate:
1021 AggOr<<R as ComparisonOperand<'a, V, Self::SQLType>>::Aggregate>,
1022 {
1023 is_not_distinct_from(self, other)
1024 }
1025
1026 #[allow(clippy::wrong_self_convention)]
1035 fn is_true(
1036 self,
1037 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate> {
1038 is_true(self)
1039 }
1040
1041 #[allow(clippy::wrong_self_convention)]
1050 fn is_false(
1051 self,
1052 ) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Bool, NonNull, Self::Aggregate> {
1053 is_false(self)
1054 }
1055}
1056
1057impl<'a, V: SQLParam, E: Expr<'a, V>> ExprExt<'a, V> for E {}