Add support for ifnull scalar function

This commit is contained in:
김선우
2024-08-16 09:25:04 +09:00
parent 39e77bac9f
commit 8fbcd10e0e
6 changed files with 46 additions and 3 deletions

View File

@@ -70,7 +70,7 @@ This document describes the SQLite compatibility status of Limbo:
| format(FORMAT,...) | No | |
| glob(X,Y) | No | |
| hex(X) | No | |
| ifnull(X,Y) | No | |
| ifnull(X,Y) | Yes | |
| iif(X,Y,Z) | No | |
| instr(X,Y) | No | |
| last_insert_rowid() | No | |

View File

@@ -41,6 +41,7 @@ impl AggFunc {
#[derive(Debug, Clone, PartialEq)]
pub enum ScalarFunc {
Coalesce,
IfNull,
Like,
Abs,
Upper,
@@ -63,6 +64,7 @@ impl ToString for ScalarFunc {
fn to_string(&self) -> String {
match self {
ScalarFunc::Coalesce => "coalesce".to_string(),
ScalarFunc::IfNull => "ifnull".to_string(),
ScalarFunc::Like => "like(2)".to_string(),
ScalarFunc::Abs => "abs".to_string(),
ScalarFunc::Upper => "upper".to_string(),
@@ -104,6 +106,7 @@ impl Func {
"sum" => Ok(Func::Agg(AggFunc::Sum)),
"total" => Ok(Func::Agg(AggFunc::Total)),
"coalesce" => Ok(Func::Scalar(ScalarFunc::Coalesce)),
"ifnull" => Ok(Func::Scalar(ScalarFunc::IfNull)),
"like" => Ok(Func::Scalar(ScalarFunc::Like)),
"abs" => Ok(Func::Scalar(ScalarFunc::Abs)),
"upper" => Ok(Func::Scalar(ScalarFunc::Upper)),

View File

@@ -205,6 +205,35 @@ pub fn translate_expr(
Ok(target_register)
}
ScalarFunc::IfNull => {
let args = match args {
Some(args) if args.len() == 2 => args,
Some(_) => crate::bail_parse_error!(
"{} function requires exactly 2 arguments",
srf.to_string()
),
None => crate::bail_parse_error!(
"{} function requires arguments",
srf.to_string()
),
};
let temp_reg = program.alloc_register();
translate_expr(program, select, &args[0], temp_reg, cursor_hint)?;
program.emit_insn(Insn::NotNull {
reg: temp_reg,
target_pc: program.offset() + 2,
});
translate_expr(program, select, &args[1], temp_reg, cursor_hint)?;
program.emit_insn(Insn::Copy {
src_reg: temp_reg,
dst_reg: target_register,
amount: 0,
});
Ok(target_register)
}
ScalarFunc::Like => {
let args = if let Some(args) = args {
if args.len() < 2 {

View File

@@ -53,7 +53,7 @@ pub fn insn_to_str(
0,
OwnedValue::Text(Rc::new("".to_string())),
0,
format!("r[{}] -> {}", reg, target_pc),
format!("r[{}]!=NULL -> goto {}", reg, target_pc),
),
Insn::IfPos {
reg,
@@ -678,7 +678,7 @@ pub fn insn_to_str(
*amount as i32,
OwnedValue::Text(Rc::new("".to_string())),
0,
"".to_string(),
format!("r[{}]=r[{}]", dst_reg, src_reg),
),
};
format!(

View File

@@ -1186,6 +1186,7 @@ impl Program {
state.pc += 1;
}
Func::Scalar(ScalarFunc::Coalesce) => {}
Func::Scalar(ScalarFunc::IfNull) => {}
Func::Scalar(ScalarFunc::Like) => {
let start_reg = *start_reg;
assert!(

View File

@@ -19,6 +19,16 @@ do_execsql_test abs-null {
select abs(null);
} {}
db null {}
do_execsql_test ifnull-1 {
select ifnull(1, 2);
} {1}
do_execsql_test ifnull-2 {
select ifnull(null, 2);
} {2}
do_execsql_test upper {
select upper('Limbo')
} {LIMBO}