From 48d3c05fb0ccb33f7265d6bc9875c8c14a913e94 Mon Sep 17 00:00:00 2001 From: Kim Seon Woo <69591622+seonwoo960000@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:40:30 +0900 Subject: [PATCH] Rebase --- COMPAT.md | 4 ++-- core/function.rs | 3 +++ core/translate/expr.rs | 20 ++++++++++++++++++++ core/vdbe/mod.rs | 19 +++++++++++++++++++ testing/scalar-functions.test | 16 ++++++++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/COMPAT.md b/COMPAT.md index 71041c777..93f943238 100644 --- a/COMPAT.md +++ b/COMPAT.md @@ -65,7 +65,7 @@ This document describes the SQLite compatibility status of Limbo: | changes() | No | | | char(X1,X2,...,XN) | Yes | | | coalesce(X,Y,...) | Yes | | -| concat(X,...) | No | | +| concat(X,...) | Yes | | | concat_ws(SEP,X,...) | No | | | format(FORMAT,...) | No | | | glob(X,Y) | No | | @@ -165,7 +165,7 @@ This document describes the SQLite compatibility status of Limbo: | json_insert(json,path,value,...) | | | | jsonb_insert(json,path,value,...) | | | | json_object(label1,value1,...) | | | -| jsonb_object(label1,value1,...)   | | | +| jsonb_object(label1,value1,...) | | | | json_patch(json1,json2) | | | | jsonb_patch(json1,json2) | | | | json_pretty(json) | | | diff --git a/core/function.rs b/core/function.rs index 54691efce..532f89234 100644 --- a/core/function.rs +++ b/core/function.rs @@ -42,6 +42,7 @@ impl AggFunc { pub enum ScalarFunc { Char, Coalesce, + Concat, IfNull, Like, Abs, @@ -67,6 +68,7 @@ impl ToString for ScalarFunc { match self { ScalarFunc::Char => "char".to_string(), ScalarFunc::Coalesce => "coalesce".to_string(), + ScalarFunc::Concat => "concat".to_string(), ScalarFunc::IfNull => "ifnull".to_string(), ScalarFunc::Like => "like(2)".to_string(), ScalarFunc::Abs => "abs".to_string(), @@ -111,6 +113,7 @@ impl Func { "total" => Ok(Func::Agg(AggFunc::Total)), "char" => Ok(Func::Scalar(ScalarFunc::Char)), "coalesce" => Ok(Func::Scalar(ScalarFunc::Coalesce)), + "concat" => Ok(Func::Scalar(ScalarFunc::Concat)), "ifnull" => Ok(Func::Scalar(ScalarFunc::IfNull)), "like" => Ok(Func::Scalar(ScalarFunc::Like)), "abs" => Ok(Func::Scalar(ScalarFunc::Abs)), diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 0e96180d2..c18a4c7ab 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -220,6 +220,26 @@ pub fn translate_expr( Ok(target_register) } + ScalarFunc::Concat => { + let args = if let Some(args) = args { + args + } else { + crate::bail_parse_error!( + "{} function with no arguments", + srf.to_string() + ); + }; + for arg in args.iter() { + let reg = program.alloc_register(); + translate_expr(program, select, arg, reg, cursor_hint)?; + } + program.emit_insn(Insn::Function { + start_reg: target_register, + dest: target_register, + func: crate::vdbe::Func::Scalar(srf), + }); + Ok(target_register) + } ScalarFunc::IfNull => { let args = match args { Some(args) if args.len() == 2 => args, diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 78c6d1bd7..77fc82454 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -1192,6 +1192,12 @@ impl Program { state.pc += 1; } Func::Scalar(ScalarFunc::Coalesce) => {} + Func::Scalar(ScalarFunc::Concat) => { + let start_reg = *start_reg; + let result = exec_concat(&state.registers[start_reg..]); + state.registers[*dest] = result; + state.pc += 1; + } Func::Scalar(ScalarFunc::IfNull) => {} Func::Scalar(ScalarFunc::Like) => { let start_reg = *start_reg; @@ -1615,6 +1621,19 @@ fn exec_upper(reg: &OwnedValue) -> Option { } } +fn exec_concat(registers: &[OwnedValue]) -> OwnedValue { + let mut result = String::new(); + for reg in registers { + match reg { + OwnedValue::Text(text) => result.push_str(text), + OwnedValue::Integer(i) => result.push_str(&i.to_string()), + OwnedValue::Float(f) => result.push_str(&f.to_string()), + _ => continue, + } + } + OwnedValue::Text(Rc::new(result)) +} + fn exec_abs(reg: &OwnedValue) -> Option { match reg { OwnedValue::Integer(x) => { diff --git a/testing/scalar-functions.test b/testing/scalar-functions.test index 0dbe8ee07..c1de40ebe 100755 --- a/testing/scalar-functions.test +++ b/testing/scalar-functions.test @@ -3,6 +3,22 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +do_execsql_test concat-1 { + select concat('l', 'i'); +} {li} + +do_execsql_test concat-2 { + select concat('l', 1); +} {l1} + +do_execsql_test concat-3 { + select concat('l', 1.5); +} {l1.5} + +do_execsql_test concat-4 { + select concat('l', null, 'i'); +} {li} + do_execsql_test char { select char(108, 105) } {li}