Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escape character is ignored in LIKE function #1051

Open
m0hossam opened this issue Feb 22, 2025 · 1 comment
Open

Escape character is ignored in LIKE function #1051

m0hossam opened this issue Feb 22, 2025 · 1 comment

Comments

@m0hossam
Copy link
Contributor

Limbo ignores the escape character in the LIKE scalar function and always generates a regular like(2):

limbo> explain select 'a' like 'a' escape 'a';
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     4     0                    0   Start at 4
1     Function           1     2     1     like(2)        0   r[1]=func(r[2..3])
2     ResultRow          1     1     0                    0   output=r[1]
3     Halt               0     0     0                    0
4     Transaction        0     0     0                    0
5     String8            0     3     0     a              0   r[3]='a'
6     String8            0     2     0     a              0   r[2]='a'
7     Goto               0     1     0                    0

Here is the equivalent in SQLite, notice the like(3):

sqlite> explain select 'a' like 'a' escape 'a';
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     9     0                    0   Start at 9
1     Once           0     6     0                    0
2     String8        0     3     0     a              0   r[3]='a'
3     String8        0     4     0     a              0   r[4]='a'
4     String8        0     5     0     a              0   r[5]='a'
5     Function       7     3     2     like(3)        0   r[2]=func(r[3..5])
6     Copy           2     1     0                    0   r[1]=r[2]
7     ResultRow      1     1     0                    0   output=r[1]
8     Halt           0     0     0                    0
9     Goto           0     1     0                    0

This can be probably traced to core/translate/expr.rs in the translate_like_base() function where the arg_count is always set to 2:

...
program.emit_insn(Insn::Function {
    constant_mask,
    start_reg,
    dest: target_register,
    func: FuncCtx {
        func: Func::Scalar(func),
        arg_count: 2,
    },
});
...

and the earlier lines escape: _ and let start_reg = program.alloc_registers(2); inside the same function.

It's important to note that The VDBE's step() function has support for executing LIKE with an escape character, it's just never used because arg_count is always set to 2 by the bytecode generator:

...
let result = match (pattern, text) {
    (OwnedValue::Text(pattern), OwnedValue::Text(text))
        if arg_count == 3 =>
    {
        let escape = match construct_like_escape_arg(
            &state.registers[*start_reg + 2],
        ) {
            Ok(x) => x,
            Err(e) => return Err(e),
        };

        OwnedValue::Integer(exec_like_with_escape(
            &pattern.as_str(),
            &text.as_str(),
            escape,
        )
            as i64)
    }
...
@m0hossam
Copy link
Contributor Author

This is the current behavior in Limbo:

limbo> create table t (name text);
limbo> insert into t values('moh_amed');
limbo> insert into t values('mohxamed');
limbo> select * from t where name like 'moh\_amed' escape '\';
limbo>

This is the desired behavior in SQLite:

sqlite> create table t (name text);
sqlite> insert into t values('moh_amed');
sqlite> insert into t values('mohxamed');
sqlite> select * from t where name like 'moh\_amed' escape '\';
moh_amed
sqlite>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant