Add first, last functions to array (#2285)
This commit is contained in:
parent
87dee375a8
commit
eef9b755cb
7 changed files with 103 additions and 1 deletions
|
@ -163,11 +163,13 @@
|
|||
"array::distinct("
|
||||
"array::filter_index("
|
||||
"array::find_index("
|
||||
"array::first("
|
||||
"array::flatten("
|
||||
"array::group("
|
||||
"array::insert("
|
||||
"array::intersect("
|
||||
"array::join("
|
||||
"array::last("
|
||||
"array::len("
|
||||
"array::logical_and("
|
||||
"array::logical_or("
|
||||
|
|
|
@ -163,11 +163,13 @@
|
|||
"array::distinct("
|
||||
"array::filter_index("
|
||||
"array::find_index("
|
||||
"array::first("
|
||||
"array::flatten("
|
||||
"array::group("
|
||||
"array::insert("
|
||||
"array::intersect("
|
||||
"array::join("
|
||||
"array::last("
|
||||
"array::len("
|
||||
"array::logical_and("
|
||||
"array::logical_or("
|
||||
|
|
|
@ -136,6 +136,14 @@ pub fn find_index((array, value): (Array, Value)) -> Result<Value, Error> {
|
|||
.map_or(Value::Null, |(i, _v)| i.into()))
|
||||
}
|
||||
|
||||
pub fn first((array,): (Array,)) -> Result<Value, Error> {
|
||||
if let [first, ..] = &array[0..] {
|
||||
Ok(first.to_owned())
|
||||
} else {
|
||||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flatten((array,): (Array,)) -> Result<Value, Error> {
|
||||
Ok(array.flatten().into())
|
||||
}
|
||||
|
@ -175,6 +183,14 @@ pub fn join((arr, sep): (Array, String)) -> Result<Value, Error> {
|
|||
Ok(arr.into_iter().map(Value::as_raw_string).collect::<Vec<_>>().join(&sep).into())
|
||||
}
|
||||
|
||||
pub fn last((array,): (Array,)) -> Result<Value, Error> {
|
||||
if let [.., last] = &array[0..] {
|
||||
Ok(last.to_owned())
|
||||
} else {
|
||||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len((array,): (Array,)) -> Result<Value, Error> {
|
||||
Ok(array.len().into())
|
||||
}
|
||||
|
@ -375,7 +391,7 @@ pub mod sort {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{join, slice};
|
||||
use super::{first, join, last, slice};
|
||||
use crate::sql::{Array, Value};
|
||||
|
||||
#[test]
|
||||
|
@ -419,4 +435,24 @@ mod tests {
|
|||
"3.56f is not 2.72f is not 1.61f",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_first() {
|
||||
fn test(arr: Array, expected: Value) {
|
||||
assert_eq!(first((arr,)).unwrap(), expected);
|
||||
}
|
||||
|
||||
test(vec!["hello", "world"].into(), "hello".into());
|
||||
test(Array::new(), Value::None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_last() {
|
||||
fn test(arr: Array, expected: Value) {
|
||||
assert_eq!(last((arr,)).unwrap(), expected);
|
||||
}
|
||||
|
||||
test(vec!["hello", "world"].into(), "world".into());
|
||||
test(Array::new(), Value::None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,11 +94,13 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
|||
"array::distinct" => array::distinct,
|
||||
"array::filter_index" => array::filter_index,
|
||||
"array::find_index" => array::find_index,
|
||||
"array::first" => array::first,
|
||||
"array::flatten" => array::flatten,
|
||||
"array::group" => array::group,
|
||||
"array::insert" => array::insert,
|
||||
"array::intersect" => array::intersect,
|
||||
"array::join" => array::join,
|
||||
"array::last" => array::last,
|
||||
"array::len" => array::len,
|
||||
"array::logical_and" => array::logical_and,
|
||||
"array::logical_or" => array::logical_or,
|
||||
|
|
|
@ -23,11 +23,13 @@ impl_module_def!(
|
|||
"distinct" => run,
|
||||
"filter_index" => run,
|
||||
"find_index" => run,
|
||||
"first" => run,
|
||||
"flatten" => run,
|
||||
"group" => run,
|
||||
"insert" => run,
|
||||
"intersect" => run,
|
||||
"join" => run,
|
||||
"last" => run,
|
||||
"len" => run,
|
||||
"logical_and" => run,
|
||||
"logical_or" => run,
|
||||
|
|
|
@ -104,7 +104,9 @@ impl Function {
|
|||
pub fn is_aggregate(&self) -> bool {
|
||||
match self {
|
||||
Self::Normal(f, _) if f == "array::distinct" => true,
|
||||
Self::Normal(f, _) if f == "array::first" => true,
|
||||
Self::Normal(f, _) if f == "array::group" => true,
|
||||
Self::Normal(f, _) if f == "array::last" => true,
|
||||
Self::Normal(f, _) if f == "count" => true,
|
||||
Self::Normal(f, _) if f == "math::bottom" => true,
|
||||
Self::Normal(f, _) if f == "math::interquartile" => true,
|
||||
|
@ -291,6 +293,7 @@ fn function_array(i: &str) -> IResult<&str, &str> {
|
|||
tag("distinct"),
|
||||
tag("filter_index"),
|
||||
tag("find_index"),
|
||||
tag("first"),
|
||||
tag("flatten"),
|
||||
tag("group"),
|
||||
tag("insert"),
|
||||
|
@ -298,6 +301,7 @@ fn function_array(i: &str) -> IResult<&str, &str> {
|
|||
alt((
|
||||
tag("intersect"),
|
||||
tag("join"),
|
||||
tag("last"),
|
||||
tag("len"),
|
||||
tag("logical_and"),
|
||||
tag("logical_or"),
|
||||
|
|
|
@ -450,6 +450,33 @@ RETURN array::find_index([0, 1, 2], 3);"#;
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_array_first() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
RETURN array::first(["hello", "world"]);
|
||||
RETURN array::first([["hello", "world"], 10]);
|
||||
RETURN array::first([]);
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Strand("hello".into());
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Array(vec!["hello", "world"].into());
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::None;
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_array_flatten() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
|
@ -615,6 +642,33 @@ async fn function_string_join_arr() -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_array_last() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
RETURN array::last(["hello", "world"]);
|
||||
RETURN array::last([["hello", "world"], 10]);
|
||||
RETURN array::last([]);
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Strand("world".into());
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = 10.into();
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::None;
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_array_len() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
|
|
Loading…
Reference in a new issue