mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-27 04:54:21 +01:00
Merge 'Add zeroblob(N) scalar function' from Lauri Virtanen
Relates to issue #144 Closes #352
This commit is contained in:
@@ -117,7 +117,7 @@ This document describes the SQLite compatibility status of Limbo:
|
||||
| unicode(X) | Yes | |
|
||||
| unlikely(X) | No | |
|
||||
| upper(X) | Yes | |
|
||||
| zeroblob(N) | No | |
|
||||
| zeroblob(N) | Yes | |
|
||||
|
||||
### Aggregate functions
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ pub enum ScalarFunc {
|
||||
SqliteVersion,
|
||||
UnixEpoch,
|
||||
Hex,
|
||||
ZeroBlob,
|
||||
}
|
||||
|
||||
impl Display for ScalarFunc {
|
||||
@@ -112,6 +113,7 @@ impl Display for ScalarFunc {
|
||||
ScalarFunc::SqliteVersion => "sqlite_version".to_string(),
|
||||
ScalarFunc::UnixEpoch => "unixepoch".to_string(),
|
||||
ScalarFunc::Hex => "hex".to_string(),
|
||||
ScalarFunc::ZeroBlob => "zeroblob".to_string(),
|
||||
};
|
||||
write!(f, "{}", str)
|
||||
}
|
||||
@@ -182,6 +184,7 @@ impl Func {
|
||||
"json" => Ok(Func::Json(JsonFunc::Json)),
|
||||
"unixepoch" => Ok(Func::Scalar(ScalarFunc::UnixEpoch)),
|
||||
"hex" => Ok(Func::Scalar(ScalarFunc::Hex)),
|
||||
"zeroblob" => Ok(Func::Scalar(ScalarFunc::ZeroBlob)),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,7 +1006,8 @@ pub fn translate_expr(
|
||||
| ScalarFunc::Typeof
|
||||
| ScalarFunc::Unicode
|
||||
| ScalarFunc::Quote
|
||||
| ScalarFunc::Sign => {
|
||||
| ScalarFunc::Sign
|
||||
| ScalarFunc::ZeroBlob => {
|
||||
let args = if let Some(args) = args {
|
||||
if args.len() != 1 {
|
||||
crate::bail_parse_error!(
|
||||
|
||||
@@ -1531,7 +1531,8 @@ impl Program {
|
||||
| ScalarFunc::Typeof
|
||||
| ScalarFunc::Unicode
|
||||
| ScalarFunc::Quote
|
||||
| ScalarFunc::Sign => {
|
||||
| ScalarFunc::Sign
|
||||
| ScalarFunc::ZeroBlob => {
|
||||
let reg_value = state.registers[*start_reg].borrow_mut();
|
||||
let result = match scalar_func {
|
||||
ScalarFunc::Sign => exec_sign(reg_value),
|
||||
@@ -1542,6 +1543,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::ZeroBlob => Some(exec_zeroblob(reg_value)),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
state.registers[*dest] = result.unwrap_or(OwnedValue::Null);
|
||||
@@ -2264,6 +2266,16 @@ fn exec_rtrim(reg: &OwnedValue, pattern: Option<OwnedValue>) -> OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_zeroblob(req: &OwnedValue) -> OwnedValue {
|
||||
let length: i64 = match req {
|
||||
OwnedValue::Integer(i) => *i,
|
||||
OwnedValue::Float(f) => *f as i64,
|
||||
OwnedValue::Text(s) => s.parse().unwrap_or(0),
|
||||
_ => 0,
|
||||
};
|
||||
OwnedValue::Blob(Rc::new(vec![0; length.max(0) as usize]))
|
||||
}
|
||||
|
||||
// exec_if returns whether you should jump
|
||||
fn exec_if(reg: &OwnedValue, null_reg: &OwnedValue, not: bool) -> bool {
|
||||
match reg {
|
||||
@@ -2292,7 +2304,7 @@ 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_unicode, exec_upper,
|
||||
exec_sign, exec_substring, exec_trim, exec_typeof, exec_unicode, exec_upper, exec_zeroblob,
|
||||
execute_sqlite_version, get_new_rowid, AggContext, Cursor, CursorResult, LimboError,
|
||||
OwnedRecord, OwnedValue, Result,
|
||||
};
|
||||
@@ -2925,6 +2937,45 @@ mod tests {
|
||||
assert_eq!(exec_sign(&input), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exec_zeroblob() {
|
||||
let input = OwnedValue::Integer(0);
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Null;
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Integer(4);
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![0; 4]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Integer(-1);
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Text(Rc::new("5".to_string()));
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![0; 5]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Text(Rc::new("-5".to_string()));
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Text(Rc::new("text".to_string()));
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Float(2.6);
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![0; 2]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
|
||||
let input = OwnedValue::Blob(Rc::new(vec![1]));
|
||||
let expected = OwnedValue::Blob(Rc::new(vec![]));
|
||||
assert_eq!(exec_zeroblob(&input), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_sqlite_version() {
|
||||
let version_integer = 3046001;
|
||||
|
||||
@@ -514,3 +514,23 @@ do_execsql_test sign-text-non-numeric {
|
||||
do_execsql_test sign-null {
|
||||
SELECT sign(NULL);
|
||||
} {}
|
||||
|
||||
do_execsql_test zeroblob-int-0 {
|
||||
SELECT zeroblob(0) = x'';
|
||||
} {1}
|
||||
|
||||
do_execsql_test zeroblob-int-1 {
|
||||
SELECT zeroblob(1) = x'00';
|
||||
} {1}
|
||||
|
||||
do_execsql_test zeroblob-str-3 {
|
||||
SELECT zeroblob('3') = x'000000';
|
||||
} {1}
|
||||
|
||||
do_execsql_test zeroblob-str-a {
|
||||
SELECT zeroblob('a') = x'';
|
||||
} {1}
|
||||
|
||||
do_execsql_test zeroblob-blob {
|
||||
SELECT zeroblob(x'01') = x'';
|
||||
} {1}
|
||||
|
||||
Reference in New Issue
Block a user