Add in expr optimization at the parser level instead of translation.

lhs IN () and lhs NOT IN () can be translated to false and true.
This commit is contained in:
Diego Reis
2025-10-06 21:34:54 -03:00
parent 70fc509046
commit 52ed0f7997
2 changed files with 17 additions and 14 deletions

View File

@@ -191,15 +191,6 @@ fn translate_in_list(
dest_if_null: BranchOffset,
resolver: &Resolver,
) -> Result<()> {
// Disclamer: SQLite does this opt during parsing (https://github.com/sqlite/sqlite/blob/833fb1ef59b1c62fb2b00c7a121a5b5171f8a85e/src/parse.y#L1425)
// But we're the cool kids so we gotta do during translation :)
if rhs.is_empty() {
program.emit_insn(Insn::Goto {
target_pc: dest_if_false,
});
return Ok(());
}
let lhs_reg = expr_code_vector(program, lhs);
let _ = translate_expr(program, referenced_tables, lhs, lhs_reg, resolver)?;
let mut check_null_reg = 0;

View File

@@ -1723,11 +1723,23 @@ impl<'a> Parser<'a> {
_ => {
let exprs = self.parse_expr_list()?;
eat_expect!(self, TK_RP);
Box::new(Expr::InList {
lhs: result,
not,
rhs: exprs,
})
// Expressions in the form:
// lhs IN ()
// lhs NOT IN ()
// can be simplified to constants 0 (false) and 1 (true), respectively.
//
// todo: should check if lhs has a function. If so, this optimization cannot
// be done.
if exprs.is_empty() {
let name = if not { "1" } else { "0" };
Box::new(Expr::Literal(Literal::Numeric(name.into())))
} else {
Box::new(Expr::InList {
lhs: result,
not,
rhs: exprs,
})
}
}
}
}