Add SQL array::slice
function. (#1855)
This commit is contained in:
parent
e6b97ff8ff
commit
38016a0ee6
3 changed files with 49 additions and 0 deletions
|
@ -143,6 +143,27 @@ pub fn reverse((mut array,): (Array,)) -> Result<Value, Error> {
|
||||||
Ok(array.into())
|
Ok(array.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slice((array, beg, lim): (Array, Option<isize>, Option<isize>)) -> Result<Value, Error> {
|
||||||
|
let skip = match beg {
|
||||||
|
Some(v) if v < 0 => array.len().saturating_sub(v.unsigned_abs()),
|
||||||
|
Some(v) => v as usize,
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let take = match lim {
|
||||||
|
Some(v) if v < 0 => array.len().saturating_sub(skip).saturating_sub(v.unsigned_abs()),
|
||||||
|
Some(v) => v as usize,
|
||||||
|
None => usize::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(if skip > 0 || take < usize::MAX {
|
||||||
|
array.into_iter().skip(skip).take(take).collect::<Vec<_>>().into()
|
||||||
|
} else {
|
||||||
|
array
|
||||||
|
}
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sort((mut array, order): (Array, Option<Value>)) -> Result<Value, Error> {
|
pub fn sort((mut array, order): (Array, Option<Value>)) -> Result<Value, Error> {
|
||||||
match order {
|
match order {
|
||||||
// If "asc", sort ascending
|
// If "asc", sort ascending
|
||||||
|
@ -193,3 +214,29 @@ pub mod sort {
|
||||||
Ok(array.into())
|
Ok(array.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::slice;
|
||||||
|
use crate::sql::{Array, Value};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn array_slice() {
|
||||||
|
fn test(initial: &[u8], beg: Option<isize>, lim: Option<isize>, expected: &[u8]) {
|
||||||
|
let initial_values =
|
||||||
|
initial.iter().map(|n| Value::from(*n as i64)).collect::<Vec<_>>().into();
|
||||||
|
let expected_values: Array =
|
||||||
|
expected.iter().map(|n| Value::from(*n as i64)).collect::<Vec<_>>().into();
|
||||||
|
assert_eq!(slice((initial_values, beg, lim)).unwrap(), expected_values.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let array = &[b'a', b'b', b'c', b'd', b'e', b'f', b'g'];
|
||||||
|
test(array, None, None, array);
|
||||||
|
test(array, Some(2), None, &array[2..]);
|
||||||
|
test(array, Some(2), Some(3), &array[2..5]);
|
||||||
|
test(array, Some(2), Some(-1), &[b'c', b'd', b'e', b'f']);
|
||||||
|
test(array, Some(-2), None, &[b'f', b'g']);
|
||||||
|
test(array, Some(-4), Some(2), &[b'd', b'e']);
|
||||||
|
test(array, Some(-4), Some(-1), &[b'd', b'e', b'f']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
||||||
"array::push" => array::push,
|
"array::push" => array::push,
|
||||||
"array::remove" => array::remove,
|
"array::remove" => array::remove,
|
||||||
"array::reverse" => array::reverse,
|
"array::reverse" => array::reverse,
|
||||||
|
"array::slice" => array::slice,
|
||||||
"array::sort" => array::sort,
|
"array::sort" => array::sort,
|
||||||
"array::union" => array::union,
|
"array::union" => array::union,
|
||||||
"array::sort::asc" => array::sort::asc,
|
"array::sort::asc" => array::sort::asc,
|
||||||
|
|
|
@ -358,6 +358,7 @@ fn function_array(i: &str) -> IResult<&str, &str> {
|
||||||
tag("push"),
|
tag("push"),
|
||||||
tag("remove"),
|
tag("remove"),
|
||||||
tag("reverse"),
|
tag("reverse"),
|
||||||
|
tag("slice"),
|
||||||
tag("sort::asc"),
|
tag("sort::asc"),
|
||||||
tag("sort::desc"),
|
tag("sort::desc"),
|
||||||
tag("sort"),
|
tag("sort"),
|
||||||
|
|
Loading…
Reference in a new issue