Skip to main content

drizzle_postgres/expr/
regex.rs

1//! `PostgreSQL` regular expression operators.
2//!
3//! Provides type-safe access to `PostgreSQL` regex operators:
4//! - `~` (matches regex, case-sensitive)
5//! - `~*` (matches regex, case-insensitive)
6//! - `!~` (does not match regex, case-sensitive)
7//! - `!~*` (does not match regex, case-insensitive)
8
9use crate::values::PostgresValue;
10use drizzle_core::expr::{Expr, NonNull, SQLExpr, Scalar};
11use drizzle_core::sql::{SQL, SQLChunk};
12use drizzle_types::postgres::types::Boolean;
13
14/// `PostgreSQL` `~` operator - case-sensitive regex match.
15///
16/// # Example
17///
18/// ```
19/// # use drizzle_postgres::expr::regex_match;
20/// # use drizzle_core::{SQL, ToSQL};
21/// # use drizzle_postgres::values::PostgresValue;
22/// let name = SQL::<PostgresValue>::raw("name");
23/// let cond = regex_match(name, "^[A-Z]");
24/// assert!(cond.to_sql().sql().contains("~"));
25/// ```
26pub fn regex_match<'a, E>(
27    expr: E,
28    pattern: &'a str,
29) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar>
30where
31    E: Expr<'a, PostgresValue<'a>>,
32{
33    SQLExpr::new(
34        expr.to_sql()
35            .push(SQLChunk::Raw("~".into()))
36            .append(SQL::param(PostgresValue::Text(pattern.into()))),
37    )
38}
39
40/// `PostgreSQL` `~*` operator - case-insensitive regex match.
41///
42/// # Example
43///
44/// ```
45/// # use drizzle_postgres::expr::regex_match_ci;
46/// # use drizzle_core::{SQL, ToSQL};
47/// # use drizzle_postgres::values::PostgresValue;
48/// let name = SQL::<PostgresValue>::raw("name");
49/// let cond = regex_match_ci(name, "^john");
50/// assert!(cond.to_sql().sql().contains("~*"));
51/// ```
52pub fn regex_match_ci<'a, E>(
53    expr: E,
54    pattern: &'a str,
55) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar>
56where
57    E: Expr<'a, PostgresValue<'a>>,
58{
59    SQLExpr::new(
60        expr.to_sql()
61            .push(SQLChunk::Raw("~*".into()))
62            .append(SQL::param(PostgresValue::Text(pattern.into()))),
63    )
64}
65
66/// `PostgreSQL` `!~` operator - case-sensitive regex non-match.
67///
68/// # Example
69///
70/// ```
71/// # use drizzle_postgres::expr::regex_not_match;
72/// # use drizzle_core::{SQL, ToSQL};
73/// # use drizzle_postgres::values::PostgresValue;
74/// let name = SQL::<PostgresValue>::raw("name");
75/// let cond = regex_not_match(name, "^[0-9]");
76/// assert!(cond.to_sql().sql().contains("!~"));
77/// ```
78pub fn regex_not_match<'a, E>(
79    expr: E,
80    pattern: &'a str,
81) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar>
82where
83    E: Expr<'a, PostgresValue<'a>>,
84{
85    SQLExpr::new(
86        expr.to_sql()
87            .push(SQLChunk::Raw("!~".into()))
88            .append(SQL::param(PostgresValue::Text(pattern.into()))),
89    )
90}
91
92/// `PostgreSQL` `!~*` operator - case-insensitive regex non-match.
93///
94/// # Example
95///
96/// ```
97/// # use drizzle_postgres::expr::regex_not_match_ci;
98/// # use drizzle_core::{SQL, ToSQL};
99/// # use drizzle_postgres::values::PostgresValue;
100/// let name = SQL::<PostgresValue>::raw("name");
101/// let cond = regex_not_match_ci(name, "^admin");
102/// assert!(cond.to_sql().sql().contains("!~*"));
103/// ```
104pub fn regex_not_match_ci<'a, E>(
105    expr: E,
106    pattern: &'a str,
107) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar>
108where
109    E: Expr<'a, PostgresValue<'a>>,
110{
111    SQLExpr::new(
112        expr.to_sql()
113            .push(SQLChunk::Raw("!~*".into()))
114            .append(SQL::param(PostgresValue::Text(pattern.into()))),
115    )
116}
117
118/// Extension trait providing method-based regex operators for `PostgreSQL` expressions.
119pub trait RegexExprExt<'a>: Expr<'a, PostgresValue<'a>> + Sized {
120    /// Case-sensitive regex match (`~` operator).
121    fn regex_match(
122        self,
123        pattern: &'a str,
124    ) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar> {
125        regex_match(self, pattern)
126    }
127
128    /// Case-insensitive regex match (`~*` operator).
129    fn regex_match_ci(
130        self,
131        pattern: &'a str,
132    ) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar> {
133        regex_match_ci(self, pattern)
134    }
135
136    /// Case-sensitive regex non-match (`!~` operator).
137    fn regex_not_match(
138        self,
139        pattern: &'a str,
140    ) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar> {
141        regex_not_match(self, pattern)
142    }
143
144    /// Case-insensitive regex non-match (`!~*` operator).
145    fn regex_not_match_ci(
146        self,
147        pattern: &'a str,
148    ) -> SQLExpr<'a, PostgresValue<'a>, Boolean, NonNull, Scalar> {
149        regex_not_match_ci(self, pattern)
150    }
151}
152
153/// Blanket implementation for all `PostgreSQL` `Expr` types.
154impl<'a, E: Expr<'a, PostgresValue<'a>>> RegexExprExt<'a> for E {}