mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-03 00:14:21 +01:00
Merge 'Add randomblob(N) scalar function' from Lauri Virtanen
Relates to issue #144 Closes #355
This commit is contained in:
@@ -91,7 +91,7 @@ This document describes the SQLite compatibility status of Limbo:
|
||||
| printf(FORMAT,...) | No | |
|
||||
| quote(X) | Yes | |
|
||||
| random() | Yes | |
|
||||
| randomblob(N) | No | |
|
||||
| randomblob(N) | Yes | |
|
||||
| replace(X,Y,Z) | No | |
|
||||
| round(X) | Yes | |
|
||||
| round(X,Y) | Yes | |
|
||||
|
||||
@@ -58,6 +58,7 @@ pub enum ScalarFunc {
|
||||
Upper,
|
||||
Lower,
|
||||
Random,
|
||||
RandomBlob,
|
||||
Trim,
|
||||
LTrim,
|
||||
RTrim,
|
||||
@@ -95,6 +96,7 @@ impl Display for ScalarFunc {
|
||||
ScalarFunc::Upper => "upper".to_string(),
|
||||
ScalarFunc::Lower => "lower".to_string(),
|
||||
ScalarFunc::Random => "random".to_string(),
|
||||
ScalarFunc::RandomBlob => "randomblob".to_string(),
|
||||
ScalarFunc::Trim => "trim".to_string(),
|
||||
ScalarFunc::LTrim => "ltrim".to_string(),
|
||||
ScalarFunc::RTrim => "rtrim".to_string(),
|
||||
@@ -169,6 +171,7 @@ impl Func {
|
||||
"upper" => Ok(Func::Scalar(ScalarFunc::Upper)),
|
||||
"lower" => Ok(Func::Scalar(ScalarFunc::Lower)),
|
||||
"random" => Ok(Func::Scalar(ScalarFunc::Random)),
|
||||
"randomblob" => Ok(Func::Scalar(ScalarFunc::RandomBlob)),
|
||||
"trim" => Ok(Func::Scalar(ScalarFunc::Trim)),
|
||||
"ltrim" => Ok(Func::Scalar(ScalarFunc::LTrim)),
|
||||
"rtrim" => Ok(Func::Scalar(ScalarFunc::RTrim)),
|
||||
|
||||
@@ -1006,6 +1006,7 @@ pub fn translate_expr(
|
||||
| ScalarFunc::Typeof
|
||||
| ScalarFunc::Unicode
|
||||
| ScalarFunc::Quote
|
||||
| ScalarFunc::RandomBlob
|
||||
| ScalarFunc::Sign
|
||||
| ScalarFunc::ZeroBlob => {
|
||||
let args = if let Some(args) = args {
|
||||
|
||||
@@ -1531,6 +1531,7 @@ impl Program {
|
||||
| ScalarFunc::Typeof
|
||||
| ScalarFunc::Unicode
|
||||
| ScalarFunc::Quote
|
||||
| ScalarFunc::RandomBlob
|
||||
| ScalarFunc::Sign
|
||||
| ScalarFunc::ZeroBlob => {
|
||||
let reg_value = state.registers[*start_reg].borrow_mut();
|
||||
@@ -1543,6 +1544,7 @@ impl Program {
|
||||
ScalarFunc::Typeof => Some(exec_typeof(reg_value)),
|
||||
ScalarFunc::Unicode => Some(exec_unicode(reg_value)),
|
||||
ScalarFunc::Quote => Some(exec_quote(reg_value)),
|
||||
ScalarFunc::RandomBlob => Some(exec_randomblob(reg_value)),
|
||||
ScalarFunc::ZeroBlob => Some(exec_zeroblob(reg_value)),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@@ -2007,6 +2009,20 @@ fn exec_random() -> OwnedValue {
|
||||
OwnedValue::Integer(random_number)
|
||||
}
|
||||
|
||||
fn exec_randomblob(reg: &OwnedValue) -> OwnedValue {
|
||||
let length = match reg {
|
||||
OwnedValue::Integer(i) => *i,
|
||||
OwnedValue::Float(f) => *f as i64,
|
||||
OwnedValue::Text(t) => t.parse().unwrap_or(1),
|
||||
_ => 1,
|
||||
}
|
||||
.max(1) as usize;
|
||||
|
||||
let mut blob: Vec<u8> = vec![0; length];
|
||||
getrandom::getrandom(&mut blob).expect("Failed to generate random blob");
|
||||
OwnedValue::Blob(Rc::new(blob))
|
||||
}
|
||||
|
||||
fn exec_quote(value: &OwnedValue) -> OwnedValue {
|
||||
match value {
|
||||
OwnedValue::Null => OwnedValue::Text(OwnedValue::Null.to_string().into()),
|
||||
@@ -2323,10 +2339,10 @@ mod tests {
|
||||
|
||||
use super::{
|
||||
exec_abs, exec_char, exec_hex, exec_if, exec_length, exec_like, exec_lower, exec_ltrim,
|
||||
exec_max, exec_min, exec_nullif, exec_quote, exec_random, exec_round, exec_rtrim,
|
||||
exec_sign, exec_substring, exec_trim, exec_typeof, exec_unhex, exec_unicode, exec_upper,
|
||||
exec_zeroblob, execute_sqlite_version, get_new_rowid, AggContext, Cursor, CursorResult,
|
||||
LimboError, OwnedRecord, OwnedValue, Result,
|
||||
exec_max, exec_min, exec_nullif, exec_quote, exec_random, exec_randomblob, exec_round,
|
||||
exec_rtrim, exec_sign, exec_substring, exec_trim, exec_typeof, exec_unhex, exec_unicode,
|
||||
exec_upper, exec_zeroblob, execute_sqlite_version, get_new_rowid, AggContext, Cursor,
|
||||
CursorResult, LimboError, OwnedRecord, OwnedValue, Result,
|
||||
};
|
||||
use mockall::{mock, predicate};
|
||||
use rand::{rngs::mock::StepRng, thread_rng};
|
||||
@@ -2779,6 +2795,67 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_randomblob() {
|
||||
struct TestCase {
|
||||
input: OwnedValue,
|
||||
expected_len: usize,
|
||||
}
|
||||
|
||||
let test_cases = vec![
|
||||
TestCase {
|
||||
input: OwnedValue::Integer(5),
|
||||
expected_len: 5,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Integer(0),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Integer(-1),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Text(Rc::new(String::from(""))),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Text(Rc::new(String::from("5"))),
|
||||
expected_len: 5,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Text(Rc::new(String::from("0"))),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Text(Rc::new(String::from("-1"))),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Float(2.9),
|
||||
expected_len: 2,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Float(-3.14),
|
||||
expected_len: 1,
|
||||
},
|
||||
TestCase {
|
||||
input: OwnedValue::Null,
|
||||
expected_len: 1,
|
||||
},
|
||||
];
|
||||
|
||||
for test_case in &test_cases {
|
||||
let result = exec_randomblob(&test_case.input);
|
||||
match result {
|
||||
OwnedValue::Blob(blob) => {
|
||||
assert_eq!(blob.len(), test_case.expected_len);
|
||||
}
|
||||
_ => panic!("exec_randomblob did not return a Blob variant"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_round() {
|
||||
let input_val = OwnedValue::Float(123.456);
|
||||
|
||||
@@ -539,6 +539,22 @@ do_execsql_test sign-null {
|
||||
SELECT sign(NULL);
|
||||
} {}
|
||||
|
||||
do_execsql_test randomblob-int-2 {
|
||||
SELECT length(randomblob(2));
|
||||
} {2}
|
||||
|
||||
do_execsql_test randomblob-int-0 {
|
||||
SELECT length(randomblob(0));
|
||||
} {1}
|
||||
|
||||
do_execsql_test randomblob-int-negative {
|
||||
SELECT length(randomblob(-2));
|
||||
} {1}
|
||||
|
||||
do_execsql_test randomblob-str-2 {
|
||||
SELECT length(randomblob('2'));
|
||||
} {2}
|
||||
|
||||
do_execsql_test zeroblob-int-0 {
|
||||
SELECT zeroblob(0) = x'';
|
||||
} {1}
|
||||
|
||||
Reference in New Issue
Block a user