mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-20 23:45:18 +01:00
Implement support for iif().
In sqlite, iif() looks like: sqlite> create table iiftest(a int, b int, c int); sqlite> explain select iif(a,b,c) from iiftest; addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 11 0 0 Start at 11 1 OpenRead 0 2 0 3 0 root=2 iDb=0; iiftest 2 Rewind 0 10 0 0 3 Column 0 0 2 0 r[2]= cursor 0 column 0 4 IfNot 2 7 1 0 5 Column 0 1 1 0 r[1]= cursor 0 column 1 6 Goto 0 8 0 0 7 Column 0 2 1 0 r[1]= cursor 0 column 2 8 ResultRow 1 1 0 0 output=r[1] 9 Next 0 3 0 1 10 Halt 0 0 0 0 11 Transaction 0 0 1 0 1 usesStmtJournal=0 12 Goto 0 1 0 0 And with this change, in limbo it looks like: addr opcode p1 p2 p3 p4 p5 comment ---- ----------------- ---- ---- ---- ------------- -- ------- 0 Init 0 14 0 0 Start at 14 1 OpenReadAsync 0 2 0 0 table=iiftest, root=2 2 OpenReadAwait 0 0 0 0 3 RewindAsync 0 0 0 0 4 RewindAwait 0 13 0 0 Rewind table iiftest 5 Column 0 0 2 0 r[2]=iiftest.a 6 IfNot 2 9 1 0 if !r[2] goto 9 7 Column 0 1 1 0 r[1]=iiftest.b 8 Goto 0 10 0 0 9 Column 0 2 1 0 r[1]=iiftest.c 10 ResultRow 1 1 0 0 output=r[1] 11 NextAsync 0 0 0 0 12 NextAwait 0 5 0 0 13 Halt 0 0 0 0 14 Transaction 0 0 0 0 15 Goto 0 1 0 0
This commit is contained in:
@@ -76,7 +76,7 @@ This document describes the SQLite compatibility status of Limbo:
|
||||
| glob(X,Y) | Yes | |
|
||||
| hex(X) | Yes | |
|
||||
| ifnull(X,Y) | Yes | |
|
||||
| iif(X,Y,Z) | No | |
|
||||
| iif(X,Y,Z) | Yes | |
|
||||
| instr(X,Y) | Yes | |
|
||||
| last_insert_rowid() | No | |
|
||||
| length(X) | Yes | |
|
||||
|
||||
@@ -56,6 +56,7 @@ pub enum ScalarFunc {
|
||||
ConcatWs,
|
||||
Glob,
|
||||
IfNull,
|
||||
Iif,
|
||||
Instr,
|
||||
Like,
|
||||
Abs,
|
||||
@@ -96,6 +97,7 @@ impl Display for ScalarFunc {
|
||||
ScalarFunc::ConcatWs => "concat_ws".to_string(),
|
||||
ScalarFunc::Glob => "glob".to_string(),
|
||||
ScalarFunc::IfNull => "ifnull".to_string(),
|
||||
ScalarFunc::Iif => "iif".to_string(),
|
||||
ScalarFunc::Instr => "instr".to_string(),
|
||||
ScalarFunc::Like => "like(2)".to_string(),
|
||||
ScalarFunc::Abs => "abs".to_string(),
|
||||
@@ -174,6 +176,7 @@ impl Func {
|
||||
"concat_ws" => Ok(Func::Scalar(ScalarFunc::ConcatWs)),
|
||||
"glob" => Ok(Func::Scalar(ScalarFunc::Glob)),
|
||||
"ifnull" => Ok(Func::Scalar(ScalarFunc::IfNull)),
|
||||
"iif" => Ok(Func::Scalar(ScalarFunc::Iif)),
|
||||
"instr" => Ok(Func::Scalar(ScalarFunc::Instr)),
|
||||
"like" => Ok(Func::Scalar(ScalarFunc::Like)),
|
||||
"abs" => Ok(Func::Scalar(ScalarFunc::Abs)),
|
||||
|
||||
@@ -967,6 +967,58 @@ pub fn translate_expr(
|
||||
|
||||
Ok(target_register)
|
||||
}
|
||||
ScalarFunc::Iif => {
|
||||
let args = if args.as_ref().map(|args| args.len() != 3).unwrap_or(true)
|
||||
{
|
||||
crate::bail_parse_error!(
|
||||
"{} requires exactly 3 arguments",
|
||||
srf.to_string()
|
||||
);
|
||||
} else {
|
||||
args.as_ref().unwrap()
|
||||
};
|
||||
let temp_reg = program.alloc_register();
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[0],
|
||||
temp_reg,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
let jump_target_when_false = program.allocate_label();
|
||||
program.emit_insn_with_label_dependency(
|
||||
Insn::IfNot {
|
||||
reg: temp_reg,
|
||||
target_pc: jump_target_when_false,
|
||||
null_reg: 1,
|
||||
},
|
||||
jump_target_when_false,
|
||||
);
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[1],
|
||||
target_register,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
let jump_target_result = program.allocate_label();
|
||||
program.emit_insn_with_label_dependency(
|
||||
Insn::Goto {
|
||||
target_pc: jump_target_result,
|
||||
},
|
||||
jump_target_result,
|
||||
);
|
||||
program.preassign_label_to_next_insn(jump_target_when_false);
|
||||
translate_expr(
|
||||
program,
|
||||
referenced_tables,
|
||||
&args[2],
|
||||
target_register,
|
||||
precomputed_exprs_to_registers,
|
||||
)?;
|
||||
program.preassign_label_to_next_insn(jump_target_result);
|
||||
Ok(target_register)
|
||||
}
|
||||
ScalarFunc::Glob | ScalarFunc::Like => {
|
||||
let args = if let Some(args) = args {
|
||||
if args.len() < 2 {
|
||||
|
||||
@@ -2105,6 +2105,7 @@ impl Program {
|
||||
state.registers[*dest] = result;
|
||||
}
|
||||
ScalarFunc::IfNull => {}
|
||||
ScalarFunc::Iif => {}
|
||||
ScalarFunc::Instr => {
|
||||
let reg_value = &state.registers[*start_reg];
|
||||
let pattern_value = &state.registers[*start_reg + 1];
|
||||
|
||||
@@ -75,6 +75,14 @@ do_execsql_test ifnull-2 {
|
||||
select ifnull(null, 2);
|
||||
} {2}
|
||||
|
||||
do_execsql_test iif-1 {
|
||||
select iif(1, 1, 0);
|
||||
} {1}
|
||||
|
||||
do_execsql_test iif-2 {
|
||||
select iif(0, 1, 0);
|
||||
} {0}
|
||||
|
||||
do_execsql_test instr-str {
|
||||
select instr('limbo', 'im');
|
||||
} {2}
|
||||
|
||||
Reference in New Issue
Block a user