@@ -162,49 +162,50 @@ pub(super) trait DialectHandler: Any + Debug {
162
162
true
163
163
}
164
164
165
- fn regex_function ( & self ) -> Option < & ' static str > {
166
- Some ( "REGEXP" )
167
- }
168
-
169
165
fn translate_regex (
170
166
& self ,
171
167
search : sql_ast:: Expr ,
172
168
target : sql_ast:: Expr ,
173
169
) -> anyhow:: Result < sql_ast:: Expr > {
174
- // When
175
- // https://github.com/sqlparser-rs/sqlparser-rs/issues/863#issuecomment-1537272570
176
- // is fixed, we can implement the infix for the other dialects. Until
177
- // then, we still only have the `regex_function` implementations. (But
178
- // I'd done the work to allow any Expr to be created before realizing
179
- // sqlparser-rs didn't support custom operators, so may as well leave it
180
- // in for when they do / we find another approach.)
181
-
182
- let Some ( regex_function) = self . regex_function ( ) else {
183
- // TODO: name the dialect, but not immediately obvious how to actually
184
- // get the dialect string from a `DialectHandler` (though we could
185
- // add it to each impl...)
186
- //
187
- // MSSQL doesn't support them, MySQL & SQLite have a different construction.
188
- return Err ( Error :: new (
189
- crate :: Reason :: Simple ( "regex functions are not supported by this dialect (or PRQL doesn't yet implement this dialect)" . to_string ( ) )
190
- ) . into ( ) )
191
- } ;
170
+ self . translate_regex_with_function ( search, target, "REGEXP" )
171
+ }
192
172
173
+ fn translate_regex_with_function (
174
+ // This `self` isn't actually used, but it's require because of object
175
+ // safety (open to better ways of doing this...)
176
+ & self ,
177
+ search : sql_ast:: Expr ,
178
+ target : sql_ast:: Expr ,
179
+ function_name : & str ,
180
+ ) -> anyhow:: Result < sql_ast:: Expr > {
193
181
let args = [ search, target]
194
182
. into_iter ( )
195
183
. map ( FunctionArgExpr :: Expr )
196
184
. map ( FunctionArg :: Unnamed )
197
185
. collect ( ) ;
198
186
199
187
Ok ( sql_ast:: Expr :: Function ( Function {
200
- name : ObjectName ( vec ! [ sql_ast:: Ident :: new( regex_function ) ] ) ,
188
+ name : ObjectName ( vec ! [ sql_ast:: Ident :: new( function_name ) ] ) ,
201
189
args,
202
190
over : None ,
203
191
distinct : false ,
204
192
special : false ,
205
193
order_by : vec ! [ ] ,
206
194
} ) )
207
195
}
196
+
197
+ fn translate_regex_with_operator (
198
+ & self ,
199
+ search : sql_ast:: Expr ,
200
+ target : sql_ast:: Expr ,
201
+ operator : sql_ast:: BinaryOperator ,
202
+ ) -> anyhow:: Result < sql_ast:: Expr > {
203
+ Ok ( sql_ast:: Expr :: BinaryOp {
204
+ left : Box :: new ( search) ,
205
+ op : operator,
206
+ right : Box :: new ( target) ,
207
+ } )
208
+ }
208
209
}
209
210
210
211
impl dyn DialectHandler {
@@ -220,8 +221,12 @@ impl DialectHandler for PostgresDialect {
220
221
fn requires_quotes_intervals ( & self ) -> bool {
221
222
true
222
223
}
223
- fn regex_function ( & self ) -> std:: option:: Option < & ' static str > {
224
- Some ( "REGEXP_LIKE" )
224
+ fn translate_regex (
225
+ & self ,
226
+ search : sql_ast:: Expr ,
227
+ target : sql_ast:: Expr ,
228
+ ) -> anyhow:: Result < sql_ast:: Expr > {
229
+ self . translate_regex_with_operator ( search, target, sql_ast:: BinaryOperator :: PGRegexMatch )
225
230
}
226
231
}
227
232
@@ -242,21 +247,32 @@ impl DialectHandler for SQLiteDialect {
242
247
false
243
248
}
244
249
245
- fn regex_function ( & self ) -> Option < & ' static str > {
246
- // Sqlite has a different construction, using `REGEXP` as an operator.
247
- // (`foo REGEXP 'bar').
248
- //
249
- // TODO: change the construction of the function to allow this.
250
- None
250
+ fn translate_regex (
251
+ & self ,
252
+ search : sql_ast:: Expr ,
253
+ target : sql_ast:: Expr ,
254
+ ) -> anyhow:: Result < sql_ast:: Expr > {
255
+ self . translate_regex_with_operator (
256
+ search,
257
+ target,
258
+ sql_ast:: BinaryOperator :: Custom ( "REGEXP" . to_string ( ) ) ,
259
+ )
251
260
}
252
261
}
253
262
254
263
impl DialectHandler for MsSqlDialect {
255
264
fn use_top ( & self ) -> bool {
256
265
true
257
266
}
258
- fn regex_function ( & self ) -> Option < & ' static str > {
259
- None
267
+
268
+ fn translate_regex (
269
+ & self ,
270
+ _search : sql_ast:: Expr ,
271
+ _target : sql_ast:: Expr ,
272
+ ) -> anyhow:: Result < sql_ast:: Expr > {
273
+ Err ( Error :: new ( crate :: Reason :: Simple (
274
+ "regex functions are not supported by MsSql" . to_string ( ) ,
275
+ ) ) ) ?
260
276
}
261
277
262
278
// https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-ver16
@@ -279,12 +295,16 @@ impl DialectHandler for MySqlDialect {
279
295
true
280
296
}
281
297
282
- fn regex_function ( & self ) -> Option < & ' static str > {
283
- // MySQL has a different construction, using `REGEXP` as an operator.
284
- // (`foo REGEXP 'bar'). So
285
- //
286
- // TODO: change the construction of the function to allow this.
287
- None
298
+ fn translate_regex (
299
+ & self ,
300
+ search : sql_ast:: Expr ,
301
+ target : sql_ast:: Expr ,
302
+ ) -> anyhow:: Result < sql_ast:: Expr > {
303
+ self . translate_regex_with_operator (
304
+ search,
305
+ target,
306
+ sql_ast:: BinaryOperator :: Custom ( "REGEXP" . to_string ( ) ) ,
307
+ )
288
308
}
289
309
}
290
310
@@ -311,8 +331,12 @@ impl DialectHandler for BigQueryDialect {
311
331
true
312
332
}
313
333
314
- fn regex_function ( & self ) -> Option < & ' static str > {
315
- Some ( "REGEXP_CONTAINS" )
334
+ fn translate_regex (
335
+ & self ,
336
+ search : sql_ast:: Expr ,
337
+ target : sql_ast:: Expr ,
338
+ ) -> anyhow:: Result < sql_ast:: Expr > {
339
+ self . translate_regex_with_function ( search, target, "REGEXP_CONTAINS" )
316
340
}
317
341
}
318
342
@@ -339,8 +363,12 @@ impl DialectHandler for DuckDbDialect {
339
363
false
340
364
}
341
365
342
- fn regex_function ( & self ) -> Option < & ' static str > {
343
- Some ( "REGEXP_MATCHES" )
366
+ fn translate_regex (
367
+ & self ,
368
+ search : sql_ast:: Expr ,
369
+ target : sql_ast:: Expr ,
370
+ ) -> anyhow:: Result < sql_ast:: Expr > {
371
+ self . translate_regex_with_function ( search, target, "REGEXP_MATCHES" )
344
372
}
345
373
}
346
374
0 commit comments