Skip to content

Commit d67e1b6

Browse files
committed
Merge 'Added 'likelihood' scalar function' from Sachin Kumar Singh
The `likelihood(X,Y)` function returns argument X unchanged. The value Y in likelihood(X,Y) must be a floating point constant between 0.0 and 1.0, inclusive. ``` sqlite> explain SELECT likelihood(42, 0.0); addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 6 0 0 Start at 6 1 Once 0 3 0 0 2 Integer 42 2 0 0 r[2]=42 3 Copy 2 1 0 0 r[1]=r[2] 4 ResultRow 1 1 0 0 output=r[1] 5 Halt 0 0 0 0 6 Goto 0 1 0 0 ``` ``` limbo> explain SELECT likelihood(42, 0.0); addr opcode p1 p2 p3 p4 p5 comment ---- ----------------- ---- ---- ---- ------------- -- ------- 0 Init 0 4 0 0 Start at 4 1 Copy 2 1 0 0 r[1]=r[2] 2 ResultRow 1 1 0 0 output=r[1] 3 Halt 0 0 0 0 4 Integer 42 2 0 0 r[2]=42 5 Goto 0 1 0 0 ``` Closes #1303
2 parents 13516fd + 01fa023 commit d67e1b6

File tree

5 files changed

+134
-2
lines changed

5 files changed

+134
-2
lines changed

COMPAT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ Feature support of [sqlite expr syntax](https://www.sqlite.org/lang_expr.html).
226226
| length(X) | Yes | |
227227
| like(X,Y) | Yes | |
228228
| like(X,Y,Z) | Yes | |
229-
| likelihood(X,Y) | No | |
229+
| likelihood(X,Y) | Yes | |
230230
| likely(X) | Yes | |
231231
| load_extension(X) | Yes | sqlite3 extensions not yet supported |
232232
| load_extension(X,Y) | No | |

core/function.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ pub enum ScalarFunc {
294294
Printf,
295295
Likely,
296296
TimeDiff,
297+
Likelihood,
297298
}
298299

299300
impl Display for ScalarFunc {
@@ -350,6 +351,7 @@ impl Display for ScalarFunc {
350351
Self::Printf => "printf".to_string(),
351352
Self::Likely => "likely".to_string(),
352353
Self::TimeDiff => "timediff".to_string(),
354+
Self::Likelihood => "likelihood".to_string(),
353355
};
354356
write!(f, "{}", str)
355357
}
@@ -607,6 +609,7 @@ impl Func {
607609
"sqlite_source_id" => Ok(Self::Scalar(ScalarFunc::SqliteSourceId)),
608610
"replace" => Ok(Self::Scalar(ScalarFunc::Replace)),
609611
"likely" => Ok(Self::Scalar(ScalarFunc::Likely)),
612+
"likelihood" => Ok(Self::Scalar(ScalarFunc::Likelihood)),
610613
#[cfg(feature = "json")]
611614
"json" => Ok(Self::Json(JsonFunc::Json)),
612615
#[cfg(feature = "json")]

core/translate/expr.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,58 @@ pub fn translate_expr(
16251625
});
16261626
Ok(target_register)
16271627
}
1628+
ScalarFunc::Likelihood => {
1629+
let args = if let Some(args) = args {
1630+
if args.len() != 2 {
1631+
crate::bail_parse_error!(
1632+
"likelihood() function must have exactly 2 arguments",
1633+
);
1634+
}
1635+
args
1636+
} else {
1637+
crate::bail_parse_error!("likelihood() function with no arguments",);
1638+
};
1639+
1640+
if let ast::Expr::Literal(ast::Literal::Numeric(ref value)) = args[1] {
1641+
if let Ok(probability) = value.parse::<f64>() {
1642+
if !(0.0..=1.0).contains(&probability) {
1643+
crate::bail_parse_error!(
1644+
"second argument of likelihood() must be between 0.0 and 1.0",
1645+
);
1646+
}
1647+
if !value.contains('.') {
1648+
crate::bail_parse_error!(
1649+
"second argument of likelihood() must be a floating point number with decimal point",
1650+
);
1651+
}
1652+
} else {
1653+
crate::bail_parse_error!(
1654+
"second argument of likelihood() must be a floating point constant",
1655+
);
1656+
}
1657+
} else {
1658+
crate::bail_parse_error!(
1659+
"second argument of likelihood() must be a numeric literal",
1660+
);
1661+
}
1662+
1663+
let start_reg = program.alloc_register();
1664+
translate_and_mark(
1665+
program,
1666+
referenced_tables,
1667+
&args[0],
1668+
start_reg,
1669+
resolver,
1670+
)?;
1671+
1672+
program.emit_insn(Insn::Copy {
1673+
src_reg: start_reg,
1674+
dst_reg: target_register,
1675+
amount: 0,
1676+
});
1677+
1678+
Ok(target_register)
1679+
}
16281680
}
16291681
}
16301682
Func::Math(math_func) => match math_func.arity() {

core/vdbe/execute.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3520,6 +3520,14 @@ pub fn op_function(
35203520
let result = exec_likely(value.get_owned_value());
35213521
state.registers[*dest] = Register::OwnedValue(result);
35223522
}
3523+
ScalarFunc::Likelihood => {
3524+
assert_eq!(arg_count, 2);
3525+
let value = &state.registers[*start_reg];
3526+
let probability = &state.registers[*start_reg + 1];
3527+
let result =
3528+
exec_likelihood(value.get_owned_value(), probability.get_owned_value());
3529+
state.registers[*dest] = Register::OwnedValue(result);
3530+
}
35233531
},
35243532
crate::function::Func::Vector(vector_func) => match vector_func {
35253533
VectorFunc::Vector => {
@@ -5380,6 +5388,10 @@ fn exec_likely(reg: &OwnedValue) -> OwnedValue {
53805388
reg.clone()
53815389
}
53825390

5391+
fn exec_likelihood(reg: &OwnedValue, _probability: &OwnedValue) -> OwnedValue {
5392+
reg.clone()
5393+
}
5394+
53835395
pub fn exec_add(lhs: &OwnedValue, rhs: &OwnedValue) -> OwnedValue {
53845396
let result = match (lhs, rhs) {
53855397
(OwnedValue::Integer(lhs), OwnedValue::Integer(rhs)) => {
@@ -6263,7 +6275,7 @@ mod tests {
62636275
}
62646276

62656277
use crate::vdbe::{
6266-
execute::{exec_likely, exec_replace},
6278+
execute::{exec_likelihood, exec_likely, exec_replace},
62676279
Bitfield, Register,
62686280
};
62696281

@@ -7180,6 +7192,39 @@ mod tests {
71807192
assert_eq!(exec_likely(&input), expected);
71817193
}
71827194

7195+
#[test]
7196+
fn test_likelihood() {
7197+
let value = OwnedValue::build_text("limbo");
7198+
let prob = OwnedValue::Float(0.5);
7199+
assert_eq!(exec_likelihood(&value, &prob), value);
7200+
7201+
let value = OwnedValue::build_text("database");
7202+
let prob = OwnedValue::Float(0.9375);
7203+
assert_eq!(exec_likelihood(&value, &prob), value);
7204+
7205+
let value = OwnedValue::Integer(100);
7206+
let prob = OwnedValue::Float(1.0);
7207+
assert_eq!(exec_likelihood(&value, &prob), value);
7208+
7209+
let value = OwnedValue::Float(12.34);
7210+
let prob = OwnedValue::Float(0.5);
7211+
assert_eq!(exec_likelihood(&value, &prob), value);
7212+
7213+
let value = OwnedValue::Null;
7214+
let prob = OwnedValue::Float(0.5);
7215+
assert_eq!(exec_likelihood(&value, &prob), value);
7216+
7217+
let value = OwnedValue::Blob(vec![1, 2, 3, 4]);
7218+
let prob = OwnedValue::Float(0.5);
7219+
assert_eq!(exec_likelihood(&value, &prob), value);
7220+
7221+
let prob = OwnedValue::build_text("0.5");
7222+
assert_eq!(exec_likelihood(&value, &prob), value);
7223+
7224+
let prob = OwnedValue::Null;
7225+
assert_eq!(exec_likelihood(&value, &prob), value);
7226+
}
7227+
71837228
#[test]
71847229
fn test_bitfield() {
71857230
let mut bitfield = Bitfield::<4>::new();

testing/scalar-functions.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,38 @@ do_execsql_test likely-null {
211211
select likely(NULL)
212212
} {}
213213

214+
do_execsql_test likelihood-string {
215+
SELECT likelihood('limbo', 0.5);
216+
} {limbo}
217+
218+
do_execsql_test likelihood-string-high-probability {
219+
SELECT likelihood('database', 0.9375);
220+
} {database}
221+
222+
do_execsql_test likelihood-integer {
223+
SELECT likelihood(100, 0.0625);
224+
} {100}
225+
226+
do_execsql_test likelihood-integer-probability-1 {
227+
SELECT likelihood(42, 1.0);
228+
} {42}
229+
230+
do_execsql_test likelihood-decimal {
231+
SELECT likelihood(12.34, 0.5);
232+
} {12.34}
233+
234+
do_execsql_test likelihood-null {
235+
SELECT likelihood(NULL, 0.5);
236+
} {}
237+
238+
do_execsql_test likelihood-blob {
239+
SELECT hex(likelihood(x'01020304', 0.5));
240+
} {01020304}
241+
242+
do_execsql_test likelihood-zero-probability {
243+
SELECT likelihood(999, 0.0);
244+
} {999}
245+
214246
do_execsql_test unhex-str-ab {
215247
SELECT unhex('6162');
216248
} {ab}

0 commit comments

Comments
 (0)