jayzhan211 opened a new issue, #25021:
URL: https://github.com/apache/datafusion/issues/25021

   ### Describe the bug
   
   An empty flags string (`''`) is rejected by `regexp_match` and by 
`regexp_like` (when the flags argument is not a literal), while `regexp_count`, 
`regexp_instr` and — as of #24987 — `regexp_replace` all accept it and treat it 
as "no flags".
   
   The flags string is spliced into the pattern as `(?{flags})`, so an empty 
string produces the invalid regex `(?)`:
   
   ```
   DataFusion error: Arrow error: Compute error: Regular expression did not 
compile: Syntax(
   regex parse error:
       (?)b..
        ^
   error: repetition operator missing expression
   )
   ```
   
   Postgres accepts an empty flags string for all of these functions and treats 
it as no flags.
   
   There is a second, related inconsistency inside `regexp_like` itself: a 
*literal* `''` works, because `derive_operator` maps `""` to 
`Operator::RegexMatch` and the simplifier rewrites the call to a `~` operator 
before execution 
([`regexplike.rs#L246-L252`](https://github.com/apache/datafusion/blob/main/datafusion/functions/src/regex/regexplike.rs#L246-L252)).
 A non-literal `''` reaches the kernel and errors. So the same value produces 
different results depending only on whether constant folding applied.
   
   ### To Reproduce
   
   ```sql
   -- errors
   SELECT regexp_match('foobarbaz', 'b..', '');
   
   -- errors (flags is a column, so the simplifier cannot fold it)
   SELECT regexp_like('foobarbaz', 'b..', flags) FROM (VALUES ('')) t(flags);
   
   -- works today: literal '' is simplified into the `~` operator
   SELECT regexp_like('foobarbaz', 'b..', '');
   
   -- works today
   SELECT regexp_count('foobarbaz', 'b..', 1, '');
   SELECT regexp_instr('foobarbaz', 'b..', 1, 1, '');
   SELECT regexp_replace('foobarbaz', 'b..', 'X', '');  -- fixed by #24987
   ```
   
   ### Expected behavior
   
   `''` behaves the same as omitting the flags argument, for every `regexp_*` 
function and regardless of whether the argument is a literal:
   
   ```sql
   SELECT regexp_match('foobarbaz', 'b..', '');  -- [bar]
   SELECT regexp_like('foobarbaz', 'b..', flags) FROM (VALUES ('')) t(flags);  
-- true
   ```
   
   ### Additional context
   
   The functions that already work do so because `compile_regex` special-cases 
the empty string:
   
   
https://github.com/apache/datafusion/blob/main/datafusion/functions/src/regex/mod.rs#L165-L177
   
   ```rust
   let pattern = match flags {
       None | Some("") => regex.to_string(),
       ...
   };
   ```
   
   `regexp_like` and `regexp_match` do not go through `compile_regex`. They 
delegate to the arrow-rs kernels, which build the pattern unconditionally 
(`arrow-string-59.2.0/src/regexp.rs`, e.g. lines 97, 186, 218, 477):
   
   ```rust
   let pattern = match flag {
       Some(flag) => format!("(?{flag}){regex}"),
       None => regex.to_string(),
   };
   ```
   
   Call sites in DataFusion:
   
   - `datafusion/functions/src/regex/regexplike.rs:380,384,388` — 
`regexp_is_match_scalar`
   - `datafusion/functions/src/regex/regexplike.rs:444-500` — `regexp_is_match`
   - `datafusion/functions/src/regex/regexplike.rs:416` — `regexp_like_scalar` 
builds `(?{flagz}){pattern}` itself
   - `datafusion/functions/src/regex/regexpmatch.rs:197,240` — 
`regexp::regexp_match`
   
   Two possible fixes:
   
   1. Normalize in DataFusion — map an empty flags value to `None` before 
calling the kernels (and in `regexp_like_scalar`). Self-contained, no upstream 
dependency.
   2. Fix upstream in arrow-rs so `Some("")` is treated as `None`, and drop the 
workaround later.
   
   Option 1 seems preferable as the immediate fix, since it also covers 
`regexp_like_scalar`, which does its own formatting.
   
   Follow-up to #24987, which fixed the same class of bug in `regexp_replace`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to