feat: added likely scalar function

This commit is contained in:
Duncan Lutz
2025-04-06 23:14:30 -06:00
parent 6eb89ca2a1
commit aa7c64cb19
5 changed files with 83 additions and 2 deletions

View File

@@ -227,7 +227,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
| like(X,Y) | Yes | | | like(X,Y) | Yes | |
| like(X,Y,Z) | Yes | | | like(X,Y,Z) | Yes | |
| likelihood(X,Y) | No | | | likelihood(X,Y) | No | |
| likely(X) | No | | | likely(X) | Yes | |
| load_extension(X) | Yes | sqlite3 extensions not yet supported | | load_extension(X) | Yes | sqlite3 extensions not yet supported |
| load_extension(X,Y) | No | | | load_extension(X,Y) | No | |
| lower(X) | Yes | | | lower(X) | Yes | |

View File

@@ -292,6 +292,7 @@ pub enum ScalarFunc {
LoadExtension, LoadExtension,
StrfTime, StrfTime,
Printf, Printf,
Likely,
} }
impl Display for ScalarFunc { impl Display for ScalarFunc {
@@ -346,6 +347,7 @@ impl Display for ScalarFunc {
Self::LoadExtension => "load_extension".to_string(), Self::LoadExtension => "load_extension".to_string(),
Self::StrfTime => "strftime".to_string(), Self::StrfTime => "strftime".to_string(),
Self::Printf => "printf".to_string(), Self::Printf => "printf".to_string(),
Self::Likely => "likely".to_string(),
}; };
write!(f, "{}", str) write!(f, "{}", str)
} }
@@ -596,6 +598,7 @@ impl Func {
"sqlite_version" => Ok(Self::Scalar(ScalarFunc::SqliteVersion)), "sqlite_version" => Ok(Self::Scalar(ScalarFunc::SqliteVersion)),
"sqlite_source_id" => Ok(Self::Scalar(ScalarFunc::SqliteSourceId)), "sqlite_source_id" => Ok(Self::Scalar(ScalarFunc::SqliteSourceId)),
"replace" => Ok(Self::Scalar(ScalarFunc::Replace)), "replace" => Ok(Self::Scalar(ScalarFunc::Replace)),
"likely" => Ok(Self::Scalar(ScalarFunc::Likely)),
#[cfg(feature = "json")] #[cfg(feature = "json")]
"json" => Ok(Self::Json(JsonFunc::Json)), "json" => Ok(Self::Json(JsonFunc::Json)),
#[cfg(feature = "json")] #[cfg(feature = "json")]

View File

@@ -1571,6 +1571,33 @@ pub fn translate_expr(
target_register, target_register,
func_ctx, func_ctx,
), ),
ScalarFunc::Likely => {
let args = if let Some(args) = args {
if args.len() != 1 {
crate::bail_parse_error!(
"likely function must have exactly 1 argument",
);
}
args
} else {
crate::bail_parse_error!("likely function with no arguments",);
};
let start_reg = program.alloc_register();
translate_and_mark(
program,
referenced_tables,
&args[0],
start_reg,
resolver,
)?;
program.emit_insn(Insn::Function {
constant_mask: 0,
start_reg,
dest: target_register,
func: func_ctx,
});
Ok(target_register)
}
} }
} }
Func::Math(math_func) => match math_func.arity() { Func::Math(math_func) => match math_func.arity() {

View File

@@ -3448,6 +3448,11 @@ pub fn op_function(
let result = exec_printf(&state.registers[*start_reg..*start_reg + arg_count])?; let result = exec_printf(&state.registers[*start_reg..*start_reg + arg_count])?;
state.registers[*dest] = Register::OwnedValue(result); state.registers[*dest] = Register::OwnedValue(result);
} }
ScalarFunc::Likely => {
let value = &state.registers[*start_reg].borrow_mut();
let result = exec_likely(value.get_owned_value());
state.registers[*dest] = Register::OwnedValue(result);
}
}, },
crate::function::Func::Vector(vector_func) => match vector_func { crate::function::Func::Vector(vector_func) => match vector_func {
VectorFunc::Vector => { VectorFunc::Vector => {
@@ -5220,9 +5225,16 @@ fn exec_math_log(arg: &OwnedValue, base: Option<&OwnedValue>) -> OwnedValue {
OwnedValue::Float(result) OwnedValue::Float(result)
} }
fn exec_likely(reg: &OwnedValue) -> OwnedValue {
reg.clone()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::vdbe::{execute::exec_replace, Bitfield, Register}; use crate::vdbe::{
execute::{exec_likely, exec_replace},
Bitfield, Register,
};
use super::{ use super::{
exec_abs, exec_char, exec_hex, exec_if, exec_instr, exec_length, exec_like, exec_lower, exec_abs, exec_char, exec_hex, exec_if, exec_instr, exec_length, exec_like, exec_lower,
@@ -6114,6 +6126,29 @@ mod tests {
); );
} }
#[test]
fn test_likely() {
let input = OwnedValue::build_text("limbo");
let expected = OwnedValue::build_text("limbo");
assert_eq!(exec_likely(&input), expected);
let input = OwnedValue::Integer(100);
let expected = OwnedValue::Integer(100);
assert_eq!(exec_likely(&input), expected);
let input = OwnedValue::Float(12.34);
let expected = OwnedValue::Float(12.34);
assert_eq!(exec_likely(&input), expected);
let input = OwnedValue::Null;
let expected = OwnedValue::Null;
assert_eq!(exec_likely(&input), expected);
let input = OwnedValue::Blob(vec![1, 2, 3, 4]);
let expected = OwnedValue::Blob(vec![1, 2, 3, 4]);
assert_eq!(exec_likely(&input), expected);
}
#[test] #[test]
fn test_bitfield() { fn test_bitfield() {
let mut bitfield = Bitfield::<4>::new(); let mut bitfield = Bitfield::<4>::new();

View File

@@ -195,6 +195,22 @@ do_execsql_test hex-null {
select hex(null) select hex(null)
} {} } {}
do_execsql_test likely {
select likely('limbo')
} {limbo}
do_execsql_test likely-int {
select likely(100)
} {100}
do_execsql_test likely-decimal {
select likely(12.34)
} {12.34}
do_execsql_test likely-null {
select likely(NULL)
} {}
do_execsql_test unhex-str-ab { do_execsql_test unhex-str-ab {
SELECT unhex('6162'); SELECT unhex('6162');
} {ab} } {ab}