Feature: Add function string::contains
(#1906)
This commit is contained in:
parent
c3c6613e7a
commit
1cd00cf3fc
7 changed files with 117 additions and 1 deletions
|
@ -274,6 +274,7 @@
|
|||
# "sleep("
|
||||
"string"
|
||||
"string::concat("
|
||||
"string::contains("
|
||||
"string::endsWith("
|
||||
"string::join("
|
||||
"string::len("
|
||||
|
|
|
@ -273,6 +273,7 @@
|
|||
"sleep("
|
||||
"string"
|
||||
"string::concat("
|
||||
"string::contains("
|
||||
"string::endsWith("
|
||||
"string::join("
|
||||
"string::len("
|
||||
|
|
|
@ -201,6 +201,7 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
|||
"session::token" => session::token(ctx),
|
||||
//
|
||||
"string::concat" => string::concat,
|
||||
"string::contains" => string::contains,
|
||||
"string::endsWith" => string::ends_with,
|
||||
"string::join" => string::join,
|
||||
"string::len" => string::len,
|
||||
|
|
|
@ -19,6 +19,7 @@ impl ModuleDef for Package {
|
|||
fn load<'js>(_ctx: Ctx<'js>, module: &Module<'js, Created>) -> Result<()> {
|
||||
module.add("default")?;
|
||||
module.add("concat")?;
|
||||
module.add("contains")?;
|
||||
module.add("endsWith")?;
|
||||
module.add("join")?;
|
||||
module.add("len")?;
|
||||
|
@ -39,6 +40,7 @@ impl ModuleDef for Package {
|
|||
fn eval<'js>(ctx: Ctx<'js>, module: &Module<'js, Loaded<Native>>) -> Result<()> {
|
||||
// Set specific exports
|
||||
module.set("concat", Func::from(|v: Any| run("string::concat", v.0)))?;
|
||||
module.set("contains", Func::from(|v: Any| run("string::contains", v.0)))?;
|
||||
module.set("endsWith", Func::from(|v: Any| run("string::endsWith", v.0)))?;
|
||||
module.set("join", Func::from(|v: Any| run("string::join", v.0)))?;
|
||||
module.set("len", Func::from(|v: Any| run("string::len", v.0)))?;
|
||||
|
@ -56,6 +58,7 @@ impl ModuleDef for Package {
|
|||
// Set default export
|
||||
let default = Object::new(ctx)?;
|
||||
default.set("concat", Func::from(|v: Any| run("string::concat", v.0)))?;
|
||||
default.set("contains", Func::from(|v: Any| run("string::contains", v.0)))?;
|
||||
default.set("endsWith", Func::from(|v: Any| run("string::endsWith", v.0)))?;
|
||||
default.set("join", Func::from(|v: Any| run("string::join", v.0)))?;
|
||||
default.set("len", Func::from(|v: Any| run("string::len", v.0)))?;
|
||||
|
|
|
@ -6,6 +6,10 @@ pub fn concat(args: Vec<Value>) -> Result<Value, Error> {
|
|||
Ok(args.into_iter().map(|x| x.as_string()).collect::<Vec<_>>().concat().into())
|
||||
}
|
||||
|
||||
pub fn contains((val, check): (String, String)) -> Result<Value, Error> {
|
||||
Ok(val.contains(&check).into())
|
||||
}
|
||||
|
||||
pub fn ends_with((val, chr): (String, String)) -> Result<Value, Error> {
|
||||
Ok(val.ends_with(&chr).into())
|
||||
}
|
||||
|
@ -107,7 +111,7 @@ pub fn words((string,): (String,)) -> Result<Value, Error> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::slice;
|
||||
use super::{contains, slice};
|
||||
use crate::sql::Value;
|
||||
|
||||
#[test]
|
||||
|
@ -131,4 +135,22 @@ mod tests {
|
|||
test(string, Some(-1), None, "界");
|
||||
test(string, Some(-2), Some(1), "世");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_contains() {
|
||||
fn test(base: &str, contained: &str, expected: bool) {
|
||||
assert_eq!(
|
||||
contains((base.to_string(), contained.to_string())).unwrap(),
|
||||
Value::from(expected)
|
||||
);
|
||||
}
|
||||
|
||||
test("", "", true);
|
||||
test("", "a", false);
|
||||
test("a", "", true);
|
||||
test("abcde", "bcd", true);
|
||||
test("abcde", "cbcd", false);
|
||||
test("好世界", "世", true);
|
||||
test("好世界", "你好", false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -485,6 +485,7 @@ fn function_session(i: &str) -> IResult<&str, &str> {
|
|||
fn function_string(i: &str) -> IResult<&str, &str> {
|
||||
alt((
|
||||
tag("concat"),
|
||||
tag("contains"),
|
||||
tag("endsWith"),
|
||||
tag("join"),
|
||||
tag("len"),
|
||||
|
|
|
@ -2947,6 +2947,93 @@ async fn function_string_concat() -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_string_contains() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
RETURN string::contains("", "");
|
||||
RETURN string::contains("a", "");
|
||||
RETURN string::contains("abcdefg", "");
|
||||
RETURN string::contains("abcdefg", "bcd");
|
||||
RETURN string::contains("abcdefg", "abcd");
|
||||
RETURN string::contains("abcdefg", "xxabcd");
|
||||
RETURN string::contains("abcdefg", "hij");
|
||||
RETURN string::contains("ประเทศไทย中华", "ประเ");
|
||||
RETURN string::contains("ประเทศไทย中华", "ะเ");
|
||||
RETURN string::contains("ประเทศไทย中华", "ไท华");
|
||||
RETURN string::contains("1234567ah012345678901ah", "hah");
|
||||
RETURN string::contains("00abc01234567890123456789abc", "bcabc");
|
||||
RETURN string::contains("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaba");
|
||||
RETURN string::contains("* \t", " ");
|
||||
RETURN string::contains("* \t", "?");
|
||||
"#;
|
||||
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, false).await?;
|
||||
assert_eq!(res.len(), 15);
|
||||
// 1
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 2
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 3
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 4
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 5
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 6
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 7
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 8
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 9
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 10
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 11
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 12
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 13
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
// 14
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(true);
|
||||
assert_eq!(tmp, val);
|
||||
// 15
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::Bool(false);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn function_string_ends_with() -> Result<(), Error> {
|
||||
let sql = r#"
|
||||
|
|
Loading…
Reference in a new issue