1use crate::dialect::DialectTypes;
13use crate::sql::{SQL, Token};
14use crate::traits::{SQLParam, ToSQL};
15use crate::types::{DataType, Integral, Textual};
16use crate::{PostgresDialect, SQLiteDialect};
17use drizzle_types::postgres::types::{
18 Char as PgChar, Int4 as PgInt4, Text as PgText, Varchar as PgVarchar,
19};
20use drizzle_types::sqlite::types::{Integer as SqliteInteger, Text as SqliteText};
21
22use super::{AggOr, AggregateKind, Expr, NonNull, NullOr, Nullability, SQLExpr};
23
24#[diagnostic::on_unimplemented(
25 message = "no length policy for `{Self}` on this dialect",
26 label = "length return type is not defined for this SQL type/dialect"
27)]
28pub trait LengthPolicy<D>: DataType {
29 type Output: DataType;
30}
31
32#[diagnostic::on_unimplemented(
33 message = "this string function is not available for this dialect",
34 label = "use a dialect-specific alternative"
35)]
36pub trait SQLiteStringSupport {}
37
38#[diagnostic::on_unimplemented(
39 message = "this string function is not available for this dialect",
40 label = "use a dialect-specific alternative"
41)]
42pub trait PostgresStringSupport {}
43
44impl LengthPolicy<SQLiteDialect> for SqliteText {
45 type Output = SqliteInteger;
46}
47impl LengthPolicy<SQLiteDialect> for drizzle_types::sqlite::types::Any {
48 type Output = SqliteInteger;
49}
50
51impl LengthPolicy<PostgresDialect> for PgVarchar {
52 type Output = PgInt4;
53}
54impl LengthPolicy<PostgresDialect> for PgText {
55 type Output = PgInt4;
56}
57impl LengthPolicy<PostgresDialect> for PgChar {
58 type Output = PgInt4;
59}
60
61impl SQLiteStringSupport for SQLiteDialect {}
62impl PostgresStringSupport for PostgresDialect {}
63
64pub fn upper<'a, V, E>(
84 expr: E,
85) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
86where
87 V: SQLParam + 'a,
88 E: Expr<'a, V>,
89 E::SQLType: Textual,
90{
91 SQLExpr::new(SQL::func("UPPER", expr.into_sql()))
92}
93
94pub fn lower<'a, V, E>(
109 expr: E,
110) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
111where
112 V: SQLParam + 'a,
113 E: Expr<'a, V>,
114 E::SQLType: Textual,
115{
116 SQLExpr::new(SQL::func("LOWER", expr.into_sql()))
117}
118
119pub fn trim<'a, V, E>(
138 expr: E,
139) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
140where
141 V: SQLParam + 'a,
142 E: Expr<'a, V>,
143 E::SQLType: Textual,
144{
145 SQLExpr::new(SQL::func("TRIM", expr.into_sql()))
146}
147
148pub fn ltrim<'a, V, E>(
152 expr: E,
153) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
154where
155 V: SQLParam + 'a,
156 E: Expr<'a, V>,
157 E::SQLType: Textual,
158{
159 SQLExpr::new(SQL::func("LTRIM", expr.into_sql()))
160}
161
162pub fn rtrim<'a, V, E>(
166 expr: E,
167) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
168where
169 V: SQLParam + 'a,
170 E: Expr<'a, V>,
171 E::SQLType: Textual,
172{
173 SQLExpr::new(SQL::func("RTRIM", expr.into_sql()))
174}
175
176pub fn collate<'a, V, E>(
208 expr: E,
209 name: &'static str,
210) -> SQLExpr<'a, V, E::SQLType, E::Nullable, E::Aggregate>
211where
212 V: SQLParam + 'a,
213 E: Expr<'a, V>,
214 E::SQLType: Textual,
215{
216 let inner = expr.into_sql().parens_if_subquery();
220 SQLExpr::new(
221 SQL::raw("(")
222 .append(inner)
223 .append(SQL::raw(format!(" COLLATE \"{name}\")"))),
224 )
225}
226
227#[allow(clippy::type_complexity)]
246pub fn length<'a, V, E>(
247 expr: E,
248) -> SQLExpr<'a, V, <E::SQLType as LengthPolicy<V::DialectMarker>>::Output, E::Nullable, E::Aggregate>
249where
250 V: SQLParam + 'a,
251 E: Expr<'a, V>,
252 E::SQLType: LengthPolicy<V::DialectMarker>,
253{
254 SQLExpr::new(SQL::func("LENGTH", expr.into_sql()))
255}
256
257#[allow(clippy::type_complexity)]
277pub fn substr<'a, V, E, S, L>(
278 expr: E,
279 start: S,
280 len: L,
281) -> SQLExpr<
282 'a,
283 V,
284 <V::DialectMarker as DialectTypes>::Text,
285 E::Nullable,
286 <<E::Aggregate as AggOr<S::Aggregate>>::Output as AggOr<L::Aggregate>>::Output,
287>
288where
289 V: SQLParam + 'a,
290 E: Expr<'a, V>,
291 E::SQLType: Textual,
292 S: Expr<'a, V>,
293 S::SQLType: Integral,
294 S::Aggregate: AggregateKind,
295 L: Expr<'a, V>,
296 L::SQLType: Integral,
297 L::Aggregate: AggregateKind,
298 E::Aggregate: AggOr<S::Aggregate>,
299 <E::Aggregate as AggOr<S::Aggregate>>::Output: AggOr<L::Aggregate>,
300{
301 SQLExpr::new(SQL::func(
302 "SUBSTR",
303 expr.into_sql()
304 .push(Token::COMMA)
305 .append(start.into_sql())
306 .push(Token::COMMA)
307 .append(len.into_sql()),
308 ))
309}
310
311#[allow(clippy::type_complexity)]
331pub fn replace<'a, V, E, F, T>(
332 expr: E,
333 from: F,
334 to: T,
335) -> SQLExpr<
336 'a,
337 V,
338 <V::DialectMarker as DialectTypes>::Text,
339 E::Nullable,
340 <<E::Aggregate as AggOr<F::Aggregate>>::Output as AggOr<T::Aggregate>>::Output,
341>
342where
343 V: SQLParam + 'a,
344 E: Expr<'a, V>,
345 E::SQLType: Textual,
346 F: Expr<'a, V>,
347 F::SQLType: Textual,
348 F::Aggregate: AggregateKind,
349 T: Expr<'a, V>,
350 T::SQLType: Textual,
351 T::Aggregate: AggregateKind,
352 E::Aggregate: AggOr<F::Aggregate>,
353 <E::Aggregate as AggOr<F::Aggregate>>::Output: AggOr<T::Aggregate>,
354{
355 SQLExpr::new(SQL::func(
356 "REPLACE",
357 expr.into_sql()
358 .push(Token::COMMA)
359 .append(from.into_sql())
360 .push(Token::COMMA)
361 .append(to.into_sql()),
362 ))
363}
364
365#[allow(clippy::type_complexity)]
386pub fn instr<'a, V, E, S>(
387 expr: E,
388 search: S,
389) -> SQLExpr<
390 'a,
391 V,
392 drizzle_types::sqlite::types::Integer,
393 E::Nullable,
394 <E::Aggregate as AggOr<S::Aggregate>>::Output,
395>
396where
397 V: SQLParam + 'a,
398 V::DialectMarker: SQLiteStringSupport,
399 E: Expr<'a, V>,
400 E::SQLType: Textual,
401 S: Expr<'a, V>,
402 S::SQLType: Textual,
403 S::Aggregate: AggregateKind,
404 E::Aggregate: AggOr<S::Aggregate>,
405{
406 SQLExpr::new(SQL::func(
407 "INSTR",
408 expr.into_sql().push(Token::COMMA).append(search.into_sql()),
409 ))
410}
411
412#[allow(clippy::type_complexity)]
414pub fn strpos<'a, V, E, S>(
415 expr: E,
416 search: S,
417) -> SQLExpr<
418 'a,
419 V,
420 drizzle_types::postgres::types::Int4,
421 E::Nullable,
422 <E::Aggregate as AggOr<S::Aggregate>>::Output,
423>
424where
425 V: SQLParam + 'a,
426 V::DialectMarker: PostgresStringSupport,
427 E: Expr<'a, V>,
428 E::SQLType: Textual,
429 S: Expr<'a, V>,
430 S::SQLType: Textual,
431 S::Aggregate: AggregateKind,
432 E::Aggregate: AggOr<S::Aggregate>,
433{
434 SQLExpr::new(SQL::func(
435 "STRPOS",
436 expr.into_sql().push(Token::COMMA).append(search.into_sql()),
437 ))
438}
439
440#[allow(clippy::type_complexity)]
475pub fn concat<'a, V, E1, E2>(
476 expr1: E1,
477 expr2: E2,
478) -> SQLExpr<
479 'a,
480 V,
481 <V::DialectMarker as DialectTypes>::Text,
482 <E1::Nullable as NullOr<E2::Nullable>>::Output,
483 <E1::Aggregate as AggOr<E2::Aggregate>>::Output,
484>
485where
486 V: SQLParam + 'a,
487 E1: Expr<'a, V>,
488 E1::SQLType: Textual,
489 E2: Expr<'a, V>,
490 E2::SQLType: Textual,
491 E1::Nullable: NullOr<E2::Nullable>,
492 E2::Nullable: Nullability,
493 E2::Aggregate: AggregateKind,
494 E1::Aggregate: AggOr<E2::Aggregate>,
495{
496 SQLExpr::new(
497 expr1
498 .into_sql()
499 .push(Token::CONCAT)
500 .append(expr2.into_sql()),
501 )
502}
503
504#[allow(clippy::type_complexity)]
526pub fn concat_ws<'a, V, S, I>(
527 sep: S,
528 values: I,
529) -> SQLExpr<
530 'a,
531 V,
532 <V::DialectMarker as DialectTypes>::Text,
533 S::Nullable,
534 <S::Aggregate as AggOr<<I::Item as Expr<'a, V>>::Aggregate>>::Output,
535>
536where
537 V: SQLParam + 'a,
538 S: Expr<'a, V>,
539 S::SQLType: Textual,
540 I: IntoIterator,
541 I::Item: Expr<'a, V>,
542 <I::Item as Expr<'a, V>>::SQLType: Textual,
543 S::Aggregate: AggOr<<I::Item as Expr<'a, V>>::Aggregate>,
544 <I::Item as Expr<'a, V>>::Aggregate: AggregateKind,
545{
546 let mut sql = sep.into_sql();
547 for value in values {
548 sql = sql.push(Token::COMMA).append(value.into_sql());
549 }
550 SQLExpr::new(SQL::func("CONCAT_WS", sql))
551}
552
553#[allow(clippy::type_complexity)]
572pub fn left<'a, V, E, N>(
573 expr: E,
574 n: N,
575) -> SQLExpr<
576 'a,
577 V,
578 <V::DialectMarker as DialectTypes>::Text,
579 E::Nullable,
580 <E::Aggregate as AggOr<N::Aggregate>>::Output,
581>
582where
583 V: SQLParam + 'a,
584 V::DialectMarker: PostgresStringSupport,
585 E: Expr<'a, V>,
586 E::SQLType: Textual,
587 N: Expr<'a, V>,
588 N::SQLType: Integral,
589 N::Aggregate: AggregateKind,
590 E::Aggregate: AggOr<N::Aggregate>,
591{
592 SQLExpr::new(SQL::func(
593 "LEFT",
594 expr.into_sql().push(Token::COMMA).append(n.into_sql()),
595 ))
596}
597
598#[allow(clippy::type_complexity)]
613pub fn right<'a, V, E, N>(
614 expr: E,
615 n: N,
616) -> SQLExpr<
617 'a,
618 V,
619 <V::DialectMarker as DialectTypes>::Text,
620 E::Nullable,
621 <E::Aggregate as AggOr<N::Aggregate>>::Output,
622>
623where
624 V: SQLParam + 'a,
625 V::DialectMarker: PostgresStringSupport,
626 E: Expr<'a, V>,
627 E::SQLType: Textual,
628 N: Expr<'a, V>,
629 N::SQLType: Integral,
630 N::Aggregate: AggregateKind,
631 E::Aggregate: AggOr<N::Aggregate>,
632{
633 SQLExpr::new(SQL::func(
634 "RIGHT",
635 expr.into_sql().push(Token::COMMA).append(n.into_sql()),
636 ))
637}
638
639#[allow(clippy::type_complexity)]
654pub fn split_part<'a, V, E, D, N>(
655 expr: E,
656 delimiter: D,
657 n: N,
658) -> SQLExpr<
659 'a,
660 V,
661 <V::DialectMarker as DialectTypes>::Text,
662 E::Nullable,
663 <<E::Aggregate as AggOr<D::Aggregate>>::Output as AggOr<N::Aggregate>>::Output,
664>
665where
666 V: SQLParam + 'a,
667 V::DialectMarker: PostgresStringSupport,
668 E: Expr<'a, V>,
669 E::SQLType: Textual,
670 D: Expr<'a, V>,
671 D::SQLType: Textual,
672 D::Aggregate: AggregateKind,
673 N: Expr<'a, V>,
674 N::SQLType: Integral,
675 N::Aggregate: AggregateKind,
676 E::Aggregate: AggOr<D::Aggregate>,
677 <E::Aggregate as AggOr<D::Aggregate>>::Output: AggOr<N::Aggregate>,
678{
679 SQLExpr::new(SQL::func(
680 "SPLIT_PART",
681 expr.into_sql()
682 .push(Token::COMMA)
683 .append(delimiter.into_sql())
684 .push(Token::COMMA)
685 .append(n.into_sql()),
686 ))
687}
688
689#[allow(clippy::type_complexity)]
702pub fn lpad<'a, V, E, L, F>(
703 expr: E,
704 length: L,
705 fill: F,
706) -> SQLExpr<
707 'a,
708 V,
709 <V::DialectMarker as DialectTypes>::Text,
710 E::Nullable,
711 <<E::Aggregate as AggOr<L::Aggregate>>::Output as AggOr<F::Aggregate>>::Output,
712>
713where
714 V: SQLParam + 'a,
715 V::DialectMarker: PostgresStringSupport,
716 E: Expr<'a, V>,
717 E::SQLType: Textual,
718 L: Expr<'a, V>,
719 L::SQLType: Integral,
720 L::Aggregate: AggregateKind,
721 F: Expr<'a, V>,
722 F::SQLType: Textual,
723 F::Aggregate: AggregateKind,
724 E::Aggregate: AggOr<L::Aggregate>,
725 <E::Aggregate as AggOr<L::Aggregate>>::Output: AggOr<F::Aggregate>,
726{
727 SQLExpr::new(SQL::func(
728 "LPAD",
729 expr.into_sql()
730 .push(Token::COMMA)
731 .append(length.into_sql())
732 .push(Token::COMMA)
733 .append(fill.into_sql()),
734 ))
735}
736
737#[allow(clippy::type_complexity)]
750pub fn rpad<'a, V, E, L, F>(
751 expr: E,
752 length: L,
753 fill: F,
754) -> SQLExpr<
755 'a,
756 V,
757 <V::DialectMarker as DialectTypes>::Text,
758 E::Nullable,
759 <<E::Aggregate as AggOr<L::Aggregate>>::Output as AggOr<F::Aggregate>>::Output,
760>
761where
762 V: SQLParam + 'a,
763 V::DialectMarker: PostgresStringSupport,
764 E: Expr<'a, V>,
765 E::SQLType: Textual,
766 L: Expr<'a, V>,
767 L::SQLType: Integral,
768 L::Aggregate: AggregateKind,
769 F: Expr<'a, V>,
770 F::SQLType: Textual,
771 F::Aggregate: AggregateKind,
772 E::Aggregate: AggOr<L::Aggregate>,
773 <E::Aggregate as AggOr<L::Aggregate>>::Output: AggOr<F::Aggregate>,
774{
775 SQLExpr::new(SQL::func(
776 "RPAD",
777 expr.into_sql()
778 .push(Token::COMMA)
779 .append(length.into_sql())
780 .push(Token::COMMA)
781 .append(fill.into_sql()),
782 ))
783}
784
785pub fn initcap<'a, V, E>(
789 expr: E,
790) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
791where
792 V: SQLParam + 'a,
793 V::DialectMarker: PostgresStringSupport,
794 E: Expr<'a, V>,
795 E::SQLType: Textual,
796{
797 SQLExpr::new(SQL::func("INITCAP", expr.into_sql()))
798}
799
800pub fn reverse<'a, V, E>(
804 expr: E,
805) -> SQLExpr<'a, V, <V::DialectMarker as DialectTypes>::Text, E::Nullable, E::Aggregate>
806where
807 V: SQLParam + 'a,
808 V::DialectMarker: PostgresStringSupport,
809 E: Expr<'a, V>,
810 E::SQLType: Textual,
811{
812 SQLExpr::new(SQL::func("REVERSE", expr.into_sql()))
813}
814
815#[allow(clippy::type_complexity)]
828pub fn repeat<'a, V, E, N>(
829 expr: E,
830 n: N,
831) -> SQLExpr<
832 'a,
833 V,
834 <V::DialectMarker as DialectTypes>::Text,
835 E::Nullable,
836 <E::Aggregate as AggOr<N::Aggregate>>::Output,
837>
838where
839 V: SQLParam + 'a,
840 V::DialectMarker: PostgresStringSupport,
841 E: Expr<'a, V>,
842 E::SQLType: Textual,
843 N: Expr<'a, V>,
844 N::SQLType: Integral,
845 N::Aggregate: AggregateKind,
846 E::Aggregate: AggOr<N::Aggregate>,
847{
848 SQLExpr::new(SQL::func(
849 "REPEAT",
850 expr.into_sql().push(Token::COMMA).append(n.into_sql()),
851 ))
852}
853
854#[allow(clippy::type_complexity)]
870pub fn starts_with<'a, V, E, P>(
871 expr: E,
872 prefix: P,
873) -> SQLExpr<
874 'a,
875 V,
876 <V::DialectMarker as DialectTypes>::Bool,
877 NonNull,
878 <E::Aggregate as AggOr<P::Aggregate>>::Output,
879>
880where
881 V: SQLParam + 'a,
882 V::DialectMarker: PostgresStringSupport,
883 E: Expr<'a, V>,
884 E::SQLType: Textual,
885 P: Expr<'a, V>,
886 P::SQLType: Textual,
887 P::Aggregate: AggregateKind,
888 E::Aggregate: AggOr<P::Aggregate>,
889{
890 SQLExpr::new(SQL::func(
891 "STARTS_WITH",
892 expr.into_sql().push(Token::COMMA).append(prefix.into_sql()),
893 ))
894}
895
896pub trait CharLengthPolicy {
904 const CHAR_LENGTH_FN: &'static str;
905}
906
907impl CharLengthPolicy for SQLiteDialect {
908 const CHAR_LENGTH_FN: &'static str = "LENGTH";
909}
910
911impl CharLengthPolicy for PostgresDialect {
912 const CHAR_LENGTH_FN: &'static str = "CHAR_LENGTH";
913}
914
915#[allow(clippy::type_complexity)]
931pub fn char_length<'a, V, E>(
932 expr: E,
933) -> SQLExpr<'a, V, <E::SQLType as LengthPolicy<V::DialectMarker>>::Output, E::Nullable, E::Aggregate>
934where
935 V: SQLParam + 'a,
936 V::DialectMarker: CharLengthPolicy,
937 E: Expr<'a, V>,
938 E::SQLType: LengthPolicy<V::DialectMarker>,
939{
940 SQLExpr::new(SQL::func(
941 <V::DialectMarker as CharLengthPolicy>::CHAR_LENGTH_FN,
942 expr.into_sql(),
943 ))
944}
945
946#[allow(clippy::type_complexity)]
961pub fn octet_length<'a, V, E>(
962 expr: E,
963) -> SQLExpr<'a, V, <E::SQLType as LengthPolicy<V::DialectMarker>>::Output, E::Nullable, E::Aggregate>
964where
965 V: SQLParam + 'a,
966 E: Expr<'a, V>,
967 E::SQLType: LengthPolicy<V::DialectMarker>,
968{
969 SQLExpr::new(SQL::func("OCTET_LENGTH", expr.into_sql()))
970}
971
972#[allow(clippy::type_complexity)]
992pub fn translate<'a, V, E, F, T>(
993 expr: E,
994 from: F,
995 to: T,
996) -> SQLExpr<
997 'a,
998 V,
999 <V::DialectMarker as DialectTypes>::Text,
1000 E::Nullable,
1001 <<E::Aggregate as AggOr<F::Aggregate>>::Output as AggOr<T::Aggregate>>::Output,
1002>
1003where
1004 V: SQLParam + 'a,
1005 V::DialectMarker: PostgresStringSupport,
1006 E: Expr<'a, V>,
1007 E::SQLType: Textual,
1008 F: Expr<'a, V>,
1009 F::SQLType: Textual,
1010 F::Aggregate: AggregateKind,
1011 T: Expr<'a, V>,
1012 T::SQLType: Textual,
1013 T::Aggregate: AggregateKind,
1014 E::Aggregate: AggOr<F::Aggregate>,
1015 <E::Aggregate as AggOr<F::Aggregate>>::Output: AggOr<T::Aggregate>,
1016{
1017 SQLExpr::new(SQL::func(
1018 "TRANSLATE",
1019 expr.into_sql()
1020 .push(Token::COMMA)
1021 .append(from.into_sql())
1022 .push(Token::COMMA)
1023 .append(to.into_sql()),
1024 ))
1025}
1026
1027#[allow(clippy::type_complexity)]
1047pub fn regexp_replace<'a, V, E, P, R>(
1048 expr: E,
1049 pattern: P,
1050 replacement: R,
1051) -> SQLExpr<
1052 'a,
1053 V,
1054 <V::DialectMarker as DialectTypes>::Text,
1055 E::Nullable,
1056 <<E::Aggregate as AggOr<P::Aggregate>>::Output as AggOr<R::Aggregate>>::Output,
1057>
1058where
1059 V: SQLParam + 'a,
1060 V::DialectMarker: PostgresStringSupport,
1061 E: Expr<'a, V>,
1062 E::SQLType: Textual,
1063 P: Expr<'a, V>,
1064 P::SQLType: Textual,
1065 P::Aggregate: AggregateKind,
1066 R: Expr<'a, V>,
1067 R::SQLType: Textual,
1068 R::Aggregate: AggregateKind,
1069 E::Aggregate: AggOr<P::Aggregate>,
1070 <E::Aggregate as AggOr<P::Aggregate>>::Output: AggOr<R::Aggregate>,
1071{
1072 SQLExpr::new(SQL::func(
1073 "REGEXP_REPLACE",
1074 expr.into_sql()
1075 .push(Token::COMMA)
1076 .append(pattern.into_sql())
1077 .push(Token::COMMA)
1078 .append(replacement.into_sql()),
1079 ))
1080}
1081
1082#[allow(clippy::type_complexity)]
1097pub fn regexp_replace_flags<'a, V, E, P, R, F>(
1098 expr: E,
1099 pattern: P,
1100 replacement: R,
1101 flags: F,
1102) -> SQLExpr<
1103 'a,
1104 V,
1105 <V::DialectMarker as DialectTypes>::Text,
1106 E::Nullable,
1107 <<<E::Aggregate as AggOr<P::Aggregate>>::Output as AggOr<R::Aggregate>>::Output as AggOr<
1108 F::Aggregate,
1109 >>::Output,
1110>
1111where
1112 V: SQLParam + 'a,
1113 V::DialectMarker: PostgresStringSupport,
1114 E: Expr<'a, V>,
1115 E::SQLType: Textual,
1116 P: Expr<'a, V>,
1117 P::SQLType: Textual,
1118 P::Aggregate: AggregateKind,
1119 R: Expr<'a, V>,
1120 R::SQLType: Textual,
1121 R::Aggregate: AggregateKind,
1122 F: Expr<'a, V>,
1123 F::SQLType: Textual,
1124 F::Aggregate: AggregateKind,
1125 E::Aggregate: AggOr<P::Aggregate>,
1126 <E::Aggregate as AggOr<P::Aggregate>>::Output: AggOr<R::Aggregate>,
1127 <<E::Aggregate as AggOr<P::Aggregate>>::Output as AggOr<R::Aggregate>>::Output:
1128 AggOr<F::Aggregate>,
1129{
1130 SQLExpr::new(SQL::func(
1131 "REGEXP_REPLACE",
1132 expr.into_sql()
1133 .push(Token::COMMA)
1134 .append(pattern.into_sql())
1135 .push(Token::COMMA)
1136 .append(replacement.into_sql())
1137 .push(Token::COMMA)
1138 .append(flags.into_sql()),
1139 ))
1140}
1141
1142#[allow(clippy::type_complexity)]
1158pub fn regexp_match<'a, V, E, P>(
1159 expr: E,
1160 pattern: P,
1161) -> SQLExpr<
1162 'a,
1163 V,
1164 crate::types::Array<<V::DialectMarker as DialectTypes>::Text>,
1165 super::Null,
1166 <E::Aggregate as AggOr<P::Aggregate>>::Output,
1167>
1168where
1169 V: SQLParam + 'a,
1170 V::DialectMarker: PostgresStringSupport,
1171 E: Expr<'a, V>,
1172 E::SQLType: Textual,
1173 P: Expr<'a, V>,
1174 P::SQLType: Textual,
1175 P::Aggregate: AggregateKind,
1176 E::Aggregate: AggOr<P::Aggregate>,
1177{
1178 SQLExpr::new(SQL::func(
1179 "REGEXP_MATCH",
1180 expr.into_sql()
1181 .push(Token::COMMA)
1182 .append(pattern.into_sql()),
1183 ))
1184}
1185
1186#[allow(clippy::type_complexity)]
1201pub fn regexp_match_flags<'a, V, E, P, F>(
1202 expr: E,
1203 pattern: P,
1204 flags: F,
1205) -> SQLExpr<
1206 'a,
1207 V,
1208 crate::types::Array<<V::DialectMarker as DialectTypes>::Text>,
1209 super::Null,
1210 <<E::Aggregate as AggOr<P::Aggregate>>::Output as AggOr<F::Aggregate>>::Output,
1211>
1212where
1213 V: SQLParam + 'a,
1214 V::DialectMarker: PostgresStringSupport,
1215 E: Expr<'a, V>,
1216 E::SQLType: Textual,
1217 P: Expr<'a, V>,
1218 P::SQLType: Textual,
1219 P::Aggregate: AggregateKind,
1220 F: Expr<'a, V>,
1221 F::SQLType: Textual,
1222 F::Aggregate: AggregateKind,
1223 E::Aggregate: AggOr<P::Aggregate>,
1224 <E::Aggregate as AggOr<P::Aggregate>>::Output: AggOr<F::Aggregate>,
1225{
1226 SQLExpr::new(SQL::func(
1227 "REGEXP_MATCH",
1228 expr.into_sql()
1229 .push(Token::COMMA)
1230 .append(pattern.into_sql())
1231 .push(Token::COMMA)
1232 .append(flags.into_sql()),
1233 ))
1234}