From 3491e1f42e12453ed94f0d6d215877fbe1987924 Mon Sep 17 00:00:00 2001 From: Pavan-Nambi Date: Sun, 12 Oct 2025 22:17:35 +0530 Subject: [PATCH 1/2] add if alais and allow iff to have more arguments --- core/function.rs | 2 +- core/translate/expr.rs | 99 ++++++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/core/function.rs b/core/function.rs index 265816c8d..0a3236856 100644 --- a/core/function.rs +++ b/core/function.rs @@ -752,7 +752,7 @@ impl Func { "total_changes" => Ok(Self::Scalar(ScalarFunc::TotalChanges)), "glob" => Ok(Self::Scalar(ScalarFunc::Glob)), "ifnull" => Ok(Self::Scalar(ScalarFunc::IfNull)), - "iif" => Ok(Self::Scalar(ScalarFunc::Iif)), + "if" | "iif" => Ok(Self::Scalar(ScalarFunc::Iif)), "instr" => Ok(Self::Scalar(ScalarFunc::Instr)), "like" => Ok(Self::Scalar(ScalarFunc::Like)), "abs" => Ok(Self::Scalar(ScalarFunc::Abs)), diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 7bec98832..bcdd3f2c7 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1143,51 +1143,66 @@ pub fn translate_expr( Ok(target_register) } ScalarFunc::Iif => { - if args.len() != 3 { - crate::bail_parse_error!( - "{} requires exactly 3 arguments", - srf.to_string() - ); + let args = expect_arguments_min!(args, 2, srf); + + let iif_end_label = program.allocate_label(); + let condition_reg = program.alloc_register(); + + for pair in args.chunks_exact(2) { + let condition_expr = &pair[0]; + let value_expr = &pair[1]; + let next_check_label = program.allocate_label(); + + translate_expr_no_constant_opt( + program, + referenced_tables, + condition_expr, + condition_reg, + resolver, + NoConstantOptReason::RegisterReuse, + )?; + + program.emit_insn(Insn::IfNot { + reg: condition_reg, + target_pc: next_check_label, + jump_if_null: true, + }); + + translate_expr_no_constant_opt( + program, + referenced_tables, + value_expr, + target_register, + resolver, + NoConstantOptReason::RegisterReuse, + )?; + program.emit_insn(Insn::Goto { + target_pc: iif_end_label, + }); + + program.preassign_label_to_next_insn(next_check_label); } - let temp_reg = program.alloc_register(); - translate_expr_no_constant_opt( - program, - referenced_tables, - &args[0], - temp_reg, - resolver, - NoConstantOptReason::RegisterReuse, - )?; - let jump_target_when_false = program.allocate_label(); - program.emit_insn(Insn::IfNot { - reg: temp_reg, - target_pc: jump_target_when_false, - jump_if_null: true, - }); - translate_expr_no_constant_opt( - program, - referenced_tables, - &args[1], - target_register, - resolver, - NoConstantOptReason::RegisterReuse, - )?; - let jump_target_result = program.allocate_label(); - program.emit_insn(Insn::Goto { - target_pc: jump_target_result, - }); - program.preassign_label_to_next_insn(jump_target_when_false); - translate_expr_no_constant_opt( - program, - referenced_tables, - &args[2], - target_register, - resolver, - NoConstantOptReason::RegisterReuse, - )?; - program.preassign_label_to_next_insn(jump_target_result); + + if args.len() % 2 != 0 { + translate_expr_no_constant_opt( + program, + referenced_tables, + args.last().unwrap(), + target_register, + resolver, + NoConstantOptReason::RegisterReuse, + )?; + } else { + program.emit_insn(Insn::Null { + dest: target_register, + dest_end: None, + }); + } + + program.preassign_label_to_next_insn(iif_end_label); Ok(target_register) } + ScalarFunc::Glob | ScalarFunc::Like => { if args.len() < 2 { crate::bail_parse_error!( From e1f23aeb2cf77b01a59945d0ff2b52a497efa2dc Mon Sep 17 00:00:00 2001 From: Pavan-Nambi Date: Sun, 12 Oct 2025 22:23:04 +0530 Subject: [PATCH 2/2] fmt and add tests --- core/translate/expr.rs | 2 +- testing/scalar-functions.test | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/core/translate/expr.rs b/core/translate/expr.rs index bcdd3f2c7..cb02e2e35 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1187,7 +1187,7 @@ pub fn translate_expr( translate_expr_no_constant_opt( program, referenced_tables, - args.last().unwrap(), + args.last().unwrap(), target_register, resolver, NoConstantOptReason::RegisterReuse, diff --git a/testing/scalar-functions.test b/testing/scalar-functions.test index 963ccc5be..30ba59b83 100755 --- a/testing/scalar-functions.test +++ b/testing/scalar-functions.test @@ -1023,7 +1023,58 @@ do_execsql_test sum-8 { } {1.2} +# https://github.com/tursodatabase/turso/issues/3689 +do_execsql_test iif-3-args-true { + select iif(1 < 2, 'yes', 'no'); +} {yes} + +do_execsql_test iif-3-args-false { + select iif(1 > 2, 'yes', 'no'); +} {no} + +do_execsql_test iif-2-args-true { + select iif(1 < 2, 'yes'); +} {yes} + +do_execsql_test iif-2-args-false-is-null { + select iif(1 > 2, 'yes'); +} {} + +do_execsql_test iif-multi-args-finds-first-true { + select iif(0, 'a', 1, 'b', 2, 'c', 'default'); +} {b} + +do_execsql_test iif-multi-args-falls-to-else { + select iif(0, 'a', 0, 'b', 0, 'c', 'default'); +} {default} + +do_execsql_test if-alias-3-args-true { + select if(1 < 2, 'yes', 'no'); +} {yes} + +do_execsql_test if-alias-3-args-false { + select if(1 > 2, 'yes', 'no'); +} {no} + +do_execsql_test if-alias-2-args-true { + select if(1 < 2, 'ok'); +} {ok} + +do_execsql_test if-alias-multi-args-finds-first-true { + select if(0, 'a', 1, 'b', 'c'); +} {b} + +do_execsql_test if-alias-multi-args-falls-to-else { + select if(0, 'a', 0, 'b', 'c'); +} {c} + +do_execsql_test if-alias-multi-args-no-else-is-null { + select if(0, 'a', 0, 'b'); +} {} + + # TODO: sqlite seems not enable soundex() by default unless build it with SQLITE_SOUNDEX enabled. # do_execsql_test soundex-text { # select soundex('Pfister'), soundex('husobee'), soundex('Tymczak'), soundex('Ashcraft'), soundex('Robert'), soundex('Rupert'), soundex('Rubin'), soundex('Kant'), soundex('Knuth'), soundex('x'), soundex(''); # } {P236|H210|T522|A261|R163|R163|R150|K530|K530|X000|0000} +