Merge pull request #183 from JeanArhancet/feat/add-random-function

This commit is contained in:
Pekka Enberg
2024-07-19 22:48:33 +03:00
committed by GitHub
6 changed files with 48 additions and 2 deletions

View File

@@ -90,7 +90,7 @@ This document describes the SQLite compatibility status of Limbo:
| octet_length(X) | No | |
| printf(FORMAT,...) | No | |
| quote(X) | No | |
| random() | No | |
| random() | Yes | |
| randomblob(N) | No | |
| replace(X,Y,Z) | No | |
| round(X) | No | |

3
Cargo.lock generated
View File

@@ -737,8 +737,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
@@ -997,6 +999,7 @@ dependencies = [
"cfg_block",
"criterion",
"fallible-iterator 0.3.0",
"getrandom",
"io-uring",
"libc",
"log",

View File

@@ -38,6 +38,7 @@ ordered-multimap = "0.7.1"
sieve-cache = "0.1.4"
sqlite3-parser = "0.11.0"
thiserror = "1.0.61"
getrandom = { version = "0.2.15", features = ["js"] }
regex = "1.10.5"
[target.'cfg(not(target_family = "windows"))'.dev-dependencies]

View File

@@ -353,6 +353,20 @@ pub fn translate_expr(
func: SingleRowFunc::Lower,
});
Ok(target_register)
}
SingleRowFunc::Random => {
if args.is_some() {
anyhow::bail!("Parse error: random function with arguments");
}
let regs = program.alloc_register();
program.emit_insn(Insn::Function {
start_reg: regs,
dest: target_register,
func: SingleRowFunc::Random,
});
Ok(target_register)
}
}

View File

@@ -34,6 +34,7 @@ pub enum SingleRowFunc {
Abs,
Upper,
Lower,
Random,
}
impl ToString for SingleRowFunc {
@@ -44,6 +45,7 @@ impl ToString for SingleRowFunc {
SingleRowFunc::Abs => "abs".to_string(),
SingleRowFunc::Upper => "upper".to_string(),
SingleRowFunc::Lower => "lower".to_string(),
SingleRowFunc::Random => "random".to_string(),
}
}
}
@@ -71,6 +73,7 @@ impl FromStr for Func {
"abs" => Ok(Func::SingleRow(SingleRowFunc::Abs)),
"upper" => Ok(Func::SingleRow(SingleRowFunc::Upper)),
"lower" => Ok(Func::SingleRow(SingleRowFunc::Lower)),
"random" => Ok(Func::SingleRow(SingleRowFunc::Random)),
_ => Err(()),
}
}

View File

@@ -1289,6 +1289,10 @@ impl Program {
}
state.pc += 1;
}
SingleRowFunc::Random => {
state.registers[*dest] = exec_random();
state.pc += 1;
}
},
}
}
@@ -1861,6 +1865,13 @@ fn exec_abs(reg: &OwnedValue) -> Option<OwnedValue> {
}
}
fn exec_random() -> OwnedValue {
let mut buf = [0u8; 8];
getrandom::getrandom(&mut buf).unwrap();
let random_number = i64::from_ne_bytes(buf);
OwnedValue::Integer(random_number)
}
// Implements LIKE pattern matching.
fn exec_like(pattern: &str, text: &str) -> bool {
let re = Regex::new(&pattern.replace('%', ".*").replace('_', ".").to_string()).unwrap();
@@ -1883,7 +1894,7 @@ fn exec_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
#[cfg(test)]
mod tests {
use super::{exec_abs, exec_if, exec_like, exec_lower, exec_upper, OwnedValue};
use super::{exec_abs, exec_if, exec_like, exec_lower, exec_random, exec_upper, OwnedValue};
use std::rc::Rc;
#[test]
@@ -1935,6 +1946,20 @@ mod tests {
assert!(!exec_like("%a.ab", "aaaa"));
}
#[test]
fn test_random() {
match exec_random() {
OwnedValue::Integer(value) => {
// Check that the value is within the range of i64
assert!(
value >= i64::MIN && value <= i64::MAX,
"Random number out of range"
);
}
_ => panic!("exec_random did not return an Integer variant"),
}
}
#[test]
fn test_exec_if() {
let reg = OwnedValue::Integer(0);