feat: add random function

This commit is contained in:
JeanArhancet
2024-07-19 17:45:20 +02:00
parent 15bdeaba9a
commit 6a5d6847c0
6 changed files with 47 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 | |

1
Cargo.lock generated
View File

@@ -1005,6 +1005,7 @@ dependencies = [
"ordered-multimap",
"polling",
"pprof",
"rand",
"regex",
"rstest",
"rusqlite",

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"
rand = "0.8.5"
regex = "1.10.5"
[target.'cfg(not(target_family = "windows"))'.dev-dependencies]

View File

@@ -353,6 +353,21 @@ pub fn translate_expr(
func: SingleRowFunc::Lower,
});
Ok(target_register)
}
SingleRowFunc::Random => {
if args.is_some() {
anyhow::bail!("Parse error: random function withargumentst");
}
dbg!("random args", &args);
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

@@ -5,6 +5,7 @@ use crate::schema::Table;
use crate::types::{AggContext, Cursor, CursorResult, OwnedRecord, OwnedValue, Record};
use anyhow::Result;
use rand::Rng;
use regex::Regex;
use std::borrow::BorrowMut;
use std::cell::RefCell;
@@ -1289,6 +1290,10 @@ impl Program {
}
state.pc += 1;
}
SingleRowFunc::Random => {
state.registers[*dest] = exec_random();
state.pc += 1;
}
},
}
}
@@ -1861,6 +1866,12 @@ fn exec_abs(reg: &OwnedValue) -> Option<OwnedValue> {
}
}
fn exec_random() -> OwnedValue {
let mut rng = rand::thread_rng();
let random_number: i64 = rng.gen();
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);