move is::*
-> string::is::*
, add new type::is::*
fncs (#2603)
This commit is contained in:
parent
7265136c0a
commit
22c36b80c8
16 changed files with 1295 additions and 554 deletions
|
@ -253,7 +253,7 @@ DEFINE TABLE user SCHEMAFULL;
|
|||
DEFINE FIELD name ON TABLE user TYPE object;
|
||||
DEFINE FIELD name.first ON TABLE user TYPE string;
|
||||
DEFINE FIELD name.last ON TABLE user TYPE string;
|
||||
DEFINE FIELD email ON TABLE user TYPE string ASSERT is::email($value);
|
||||
DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);
|
||||
|
||||
-- Add a unique index on the email field preventing duplicate values
|
||||
DEFINE INDEX email ON TABLE user COLUMNS email UNIQUE;
|
||||
|
|
|
@ -187,7 +187,7 @@ DEFINE TABLE user SCHEMAFULL;
|
|||
DEFINE FIELD name ON TABLE user TYPE object;
|
||||
DEFINE FIELD name.first ON TABLE user TYPE string;
|
||||
DEFINE FIELD name.last ON TABLE user TYPE string;
|
||||
DEFINE FIELD email ON TABLE user TYPE string ASSERT is::email($value);
|
||||
DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is::email($value);
|
||||
|
||||
-- Add a unique index on the email field preventing duplicate values
|
||||
DEFINE INDEX email ON TABLE user COLUMNS email UNIQUE;
|
||||
|
|
|
@ -222,21 +222,6 @@
|
|||
"http::post("
|
||||
"http::patch("
|
||||
"http::delete("
|
||||
"is"
|
||||
"is::"
|
||||
"is::alphanum("
|
||||
"is::alpha("
|
||||
"is::ascii("
|
||||
"is::datetime("
|
||||
"is::domain("
|
||||
"is::email("
|
||||
"is::hexadecimal("
|
||||
"is::latitude("
|
||||
"is::longitude("
|
||||
"is::numeric("
|
||||
"is::semver("
|
||||
"is::url("
|
||||
"is::uuid("
|
||||
"math"
|
||||
"math::"
|
||||
"math::abs("
|
||||
|
@ -299,6 +284,19 @@
|
|||
"string::distance::hamming("
|
||||
"string::distance::levenshtein("
|
||||
"string::endsWith("
|
||||
"string::is::alphanum("
|
||||
"string::is::alpha("
|
||||
"string::is::ascii("
|
||||
"string::is::datetime("
|
||||
"string::is::domain("
|
||||
"string::is::email("
|
||||
"string::is::hexadecimal("
|
||||
"string::is::latitude("
|
||||
"string::is::longitude("
|
||||
"string::is::numeric("
|
||||
"string::is::semver("
|
||||
"string::is::url("
|
||||
"string::is::uuid("
|
||||
"string::join("
|
||||
"string::len("
|
||||
"string::lowercase("
|
||||
|
@ -344,6 +342,28 @@
|
|||
"type::duration("
|
||||
"type::float("
|
||||
"type::int("
|
||||
"type::is::array("
|
||||
"type::is::bool("
|
||||
"type::is::bytes("
|
||||
"type::is::collection("
|
||||
"type::is::datetime("
|
||||
"type::is::decimal("
|
||||
"type::is::duration("
|
||||
"type::is::float("
|
||||
"type::is::geometry("
|
||||
"type::is::int("
|
||||
"type::is::line("
|
||||
"type::is::null("
|
||||
"type::is::multiline("
|
||||
"type::is::multipoint("
|
||||
"type::is::multipolygon("
|
||||
"type::is::number("
|
||||
"type::is::object("
|
||||
"type::is::point("
|
||||
"type::is::polygon("
|
||||
"type::is::record("
|
||||
"type::is::string("
|
||||
"type::is::uuid("
|
||||
"type::number("
|
||||
"type::point("
|
||||
"type::string("
|
||||
|
|
|
@ -222,21 +222,6 @@
|
|||
"http::post("
|
||||
"http::patch("
|
||||
"http::delete("
|
||||
"is"
|
||||
"is::"
|
||||
"is::alphanum("
|
||||
"is::alpha("
|
||||
"is::ascii("
|
||||
"is::datetime("
|
||||
"is::domain("
|
||||
"is::email("
|
||||
"is::hexadecimal("
|
||||
"is::latitude("
|
||||
"is::longitude("
|
||||
"is::numeric("
|
||||
"is::semver("
|
||||
"is::url("
|
||||
"is::uuid("
|
||||
"math"
|
||||
"math::"
|
||||
"math::abs("
|
||||
|
@ -298,6 +283,19 @@
|
|||
"string::distance::hamming("
|
||||
"string::distance::levenshtein("
|
||||
"string::endsWith("
|
||||
"string::is::alphanum("
|
||||
"string::is::alpha("
|
||||
"string::is::ascii("
|
||||
"string::is::datetime("
|
||||
"string::is::domain("
|
||||
"string::is::email("
|
||||
"string::is::hexadecimal("
|
||||
"string::is::latitude("
|
||||
"string::is::longitude("
|
||||
"string::is::numeric("
|
||||
"string::is::semver("
|
||||
"string::is::url("
|
||||
"string::is::uuid("
|
||||
"string::join("
|
||||
"string::len("
|
||||
"string::lowercase("
|
||||
|
@ -342,6 +340,28 @@
|
|||
"type::decimal("
|
||||
"type::duration("
|
||||
"type::float("
|
||||
"type::is::array("
|
||||
"type::is::bool("
|
||||
"type::is::bytes("
|
||||
"type::is::collection("
|
||||
"type::is::datetime("
|
||||
"type::is::decimal("
|
||||
"type::is::duration("
|
||||
"type::is::float("
|
||||
"type::is::geometry("
|
||||
"type::is::int("
|
||||
"type::is::line("
|
||||
"type::is::null("
|
||||
"type::is::multiline("
|
||||
"type::is::multipoint("
|
||||
"type::is::multipolygon("
|
||||
"type::is::number("
|
||||
"type::is::object("
|
||||
"type::is::point("
|
||||
"type::is::polygon("
|
||||
"type::is::record("
|
||||
"type::is::string("
|
||||
"type::is::uuid("
|
||||
"type::int("
|
||||
"type::number("
|
||||
"type::point("
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
use chrono::NaiveDateTime;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use semver::Version;
|
||||
use std::char;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[rustfmt::skip] static LATITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
||||
#[rustfmt::skip] static LONGITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
||||
|
||||
#[inline]
|
||||
pub fn alphanum((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_alphanumeric).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn alpha((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_alphabetic).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ascii((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_ascii().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn datetime((arg, fmt): (String, String)) -> Result<Value, Error> {
|
||||
Ok(NaiveDateTime::parse_from_str(&arg, &fmt).is_ok().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn domain((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(addr::parse_domain_name(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn email((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(addr::parse_email_address(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hexadecimal((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(|x| char::is_ascii_hexdigit(&x)).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn latitude((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(LATITUDE_RE.is_match(arg.as_str()).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn longitude((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(LONGITUDE_RE.is_match(arg.as_str()).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn numeric((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_numeric).into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn semver((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(Version::parse(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn url((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(Url::parse(&arg).is_ok().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn uuid((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(match arg {
|
||||
Value::Strand(v) => Uuid::parse_str(v.as_string().as_str()).is_ok(),
|
||||
Value::Uuid(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::sql::value::Value;
|
||||
|
||||
#[test]
|
||||
fn alphanum() {
|
||||
let value = super::alphanum((String::from("abc123"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::alphanum((String::from("y%*"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alpha() {
|
||||
let value = super::alpha((String::from("abc"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::alpha((String::from("1234"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii() {
|
||||
let value = super::ascii((String::from("abc"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::ascii((String::from("中国"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn domain() {
|
||||
let value = super::domain((String::from("食狮.中国"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::domain((String::from("example-.com"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn email() {
|
||||
let input = (String::from("user@[fd79:cdcb:38cc:9dd:f686:e06d:32f3:c123]"),);
|
||||
let value = super::email(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let input = (String::from("john..doe@example.com"),);
|
||||
let value = super::email(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hexadecimal() {
|
||||
let value = super::hexadecimal((String::from("00FF00"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::hexadecimal((String::from("SurrealDB"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn latitude() {
|
||||
let value = super::latitude((String::from("-0.118092"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::latitude((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn longitude() {
|
||||
let value = super::longitude((String::from("51.509865"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::longitude((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric() {
|
||||
let value = super::numeric((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::numeric((String::from("abcde"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn semver() {
|
||||
let value = super::semver((String::from("1.0.0"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::semver((String::from("1.0"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid() {
|
||||
let input = (String::from("123e4567-e89b-12d3-a456-426614174000").into(),);
|
||||
let value = super::uuid(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let input = (String::from("foo-bar").into(),);
|
||||
let value = super::uuid(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ pub mod duration;
|
|||
pub mod encoding;
|
||||
pub mod geo;
|
||||
pub mod http;
|
||||
pub mod is;
|
||||
pub mod math;
|
||||
pub mod meta;
|
||||
pub mod not;
|
||||
|
@ -162,20 +161,6 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
|||
"geo::hash::decode" => geo::hash::decode,
|
||||
"geo::hash::encode" => geo::hash::encode,
|
||||
//
|
||||
"is::alphanum" => is::alphanum,
|
||||
"is::alpha" => is::alpha,
|
||||
"is::ascii" => is::ascii,
|
||||
"is::datetime" => is::datetime,
|
||||
"is::domain" => is::domain,
|
||||
"is::email" => is::email,
|
||||
"is::hexadecimal" => is::hexadecimal,
|
||||
"is::latitude" => is::latitude,
|
||||
"is::longitude" => is::longitude,
|
||||
"is::numeric" => is::numeric,
|
||||
"is::semver" => is::semver,
|
||||
"is::url" => is::url,
|
||||
"is::uuid" => is::uuid,
|
||||
//
|
||||
"math::abs" => math::abs,
|
||||
"math::bottom" => math::bottom,
|
||||
"math::ceil" => math::ceil,
|
||||
|
@ -257,6 +242,19 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
|||
"string::words" => string::words,
|
||||
"string::distance::hamming" => string::distance::hamming,
|
||||
"string::distance::levenshtein" => string::distance::levenshtein,
|
||||
"string::is::alphanum" => string::is::alphanum,
|
||||
"string::is::alpha" => string::is::alpha,
|
||||
"string::is::ascii" => string::is::ascii,
|
||||
"string::is::datetime" => string::is::datetime,
|
||||
"string::is::domain" => string::is::domain,
|
||||
"string::is::email" => string::is::email,
|
||||
"string::is::hexadecimal" => string::is::hexadecimal,
|
||||
"string::is::latitude" => string::is::latitude,
|
||||
"string::is::longitude" => string::is::longitude,
|
||||
"string::is::numeric" => string::is::numeric,
|
||||
"string::is::semver" => string::is::semver,
|
||||
"string::is::url" => string::is::url,
|
||||
"string::is::uuid" => string::is::uuid,
|
||||
"string::similarity::fuzzy" => string::similarity::fuzzy,
|
||||
"string::similarity::jaro" => string::similarity::jaro,
|
||||
"string::similarity::smithwaterman" => string::similarity::smithwaterman,
|
||||
|
@ -297,6 +295,28 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
|
|||
"type::string" => r#type::string,
|
||||
"type::table" => r#type::table,
|
||||
"type::thing" => r#type::thing,
|
||||
"type::is::array" => r#type::is::array,
|
||||
"type::is::bool" => r#type::is::bool,
|
||||
"type::is::bytes" => r#type::is::bytes,
|
||||
"type::is::collection" => r#type::is::collection,
|
||||
"type::is::datetime" => r#type::is::datetime,
|
||||
"type::is::decimal" => r#type::is::decimal,
|
||||
"type::is::duration" => r#type::is::duration,
|
||||
"type::is::float" => r#type::is::float,
|
||||
"type::is::geometry" => r#type::is::geometry,
|
||||
"type::is::int" => r#type::is::int,
|
||||
"type::is::line" => r#type::is::line,
|
||||
"type::is::null" => r#type::is::null,
|
||||
"type::is::multiline" => r#type::is::multiline,
|
||||
"type::is::multipoint" => r#type::is::multipoint,
|
||||
"type::is::multipolygon" => r#type::is::multipolygon,
|
||||
"type::is::number" => r#type::is::number,
|
||||
"type::is::object" => r#type::is::object,
|
||||
"type::is::point" => r#type::is::point,
|
||||
"type::is::polygon" => r#type::is::polygon,
|
||||
"type::is::record" => r#type::is::record,
|
||||
"type::is::string" => r#type::is::string,
|
||||
"type::is::uuid" => r#type::is::uuid,
|
||||
//
|
||||
"vector::add" => vector::add,
|
||||
"vector::angle" => vector::angle,
|
||||
|
|
|
@ -14,7 +14,6 @@ mod duration;
|
|||
mod encoding;
|
||||
mod geo;
|
||||
mod http;
|
||||
mod is;
|
||||
mod math;
|
||||
mod meta;
|
||||
mod parse;
|
||||
|
@ -39,7 +38,6 @@ impl_module_def!(
|
|||
"encoding" => (encoding::Package),
|
||||
"geo" => (geo::Package),
|
||||
"http" => (http::Package),
|
||||
"is" => (is::Package),
|
||||
"math" => (math::Package),
|
||||
"meta" => (meta::Package),
|
||||
"not" => run,
|
||||
|
|
|
@ -2,6 +2,7 @@ use super::run;
|
|||
use crate::fnc::script::modules::impl_module_def;
|
||||
|
||||
mod distance;
|
||||
mod is;
|
||||
mod similarity;
|
||||
pub struct Package;
|
||||
|
||||
|
@ -12,6 +13,7 @@ impl_module_def!(
|
|||
"contains" => run,
|
||||
"distance" => (distance::Package),
|
||||
"endsWith" => run,
|
||||
"is" => (is::Package),
|
||||
"join" => run,
|
||||
"len" => run,
|
||||
"lowercase" => run,
|
||||
|
|
|
@ -5,7 +5,7 @@ pub struct Package;
|
|||
|
||||
impl_module_def!(
|
||||
Package,
|
||||
"is",
|
||||
"string::is",
|
||||
"alphanum" => run,
|
||||
"alpha" => run,
|
||||
"ascii" => run,
|
|
@ -3,6 +3,8 @@ use super::run;
|
|||
use crate::fnc::script::modules::impl_module_def;
|
||||
use js::prelude::Async;
|
||||
|
||||
mod is;
|
||||
|
||||
pub struct Package;
|
||||
|
||||
impl_module_def!(
|
||||
|
@ -16,6 +18,7 @@ impl_module_def!(
|
|||
"fields" => fut Async,
|
||||
"float" => run,
|
||||
"int" => run,
|
||||
"is" => (is::Package),
|
||||
"number" => run,
|
||||
"point" => run,
|
||||
"regex" => run,
|
||||
|
|
31
lib/src/fnc/script/modules/surrealdb/functions/type/is.rs
Normal file
31
lib/src/fnc/script/modules/surrealdb/functions/type/is.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use super::run;
|
||||
use crate::fnc::script::modules::impl_module_def;
|
||||
|
||||
pub struct Package;
|
||||
|
||||
impl_module_def!(
|
||||
Package,
|
||||
"type::is",
|
||||
"array" => run,
|
||||
"bool" => run,
|
||||
"bytes" => run,
|
||||
"collection" => run,
|
||||
"datetime" => run,
|
||||
"decimal" => run,
|
||||
"duration" => run,
|
||||
"float" => run,
|
||||
"geometry" => run,
|
||||
"int" => run,
|
||||
"line" => run,
|
||||
"null" => run,
|
||||
"multiline" => run,
|
||||
"multipoint" => run,
|
||||
"multipolygon" => run,
|
||||
"number" => run,
|
||||
"object" => run,
|
||||
"point" => run,
|
||||
"polygon" => run,
|
||||
"record" => run,
|
||||
"string" => run,
|
||||
"uuid" => run
|
||||
);
|
|
@ -151,6 +151,77 @@ pub mod distance {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod is {
|
||||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
use chrono::NaiveDateTime;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use semver::Version;
|
||||
use std::char;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[rustfmt::skip] static LATITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
||||
#[rustfmt::skip] static LONGITUDE_RE: Lazy<Regex> = Lazy::new(|| Regex::new("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$").unwrap());
|
||||
|
||||
pub fn alphanum((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_alphanumeric).into())
|
||||
}
|
||||
|
||||
pub fn alpha((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_alphabetic).into())
|
||||
}
|
||||
|
||||
pub fn ascii((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_ascii().into())
|
||||
}
|
||||
|
||||
pub fn datetime((arg, fmt): (String, String)) -> Result<Value, Error> {
|
||||
Ok(NaiveDateTime::parse_from_str(&arg, &fmt).is_ok().into())
|
||||
}
|
||||
pub fn domain((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(addr::parse_domain_name(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
pub fn email((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(addr::parse_email_address(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
pub fn hexadecimal((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(|x| char::is_ascii_hexdigit(&x)).into())
|
||||
}
|
||||
|
||||
pub fn latitude((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(LATITUDE_RE.is_match(arg.as_str()).into())
|
||||
}
|
||||
|
||||
pub fn longitude((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(LONGITUDE_RE.is_match(arg.as_str()).into())
|
||||
}
|
||||
|
||||
pub fn numeric((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(arg.chars().all(char::is_numeric).into())
|
||||
}
|
||||
|
||||
pub fn semver((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(Version::parse(arg.as_str()).is_ok().into())
|
||||
}
|
||||
|
||||
pub fn url((arg,): (String,)) -> Result<Value, Error> {
|
||||
Ok(Url::parse(&arg).is_ok().into())
|
||||
}
|
||||
|
||||
pub fn uuid((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(match arg {
|
||||
Value::Strand(v) => Uuid::parse_str(v.as_string().as_str()).is_ok(),
|
||||
Value::Uuid(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod similarity {
|
||||
|
||||
use crate::err::Error;
|
||||
|
@ -216,4 +287,107 @@ mod tests {
|
|||
test("好世界", "世", true);
|
||||
test("好世界", "你好", false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_alphanum() {
|
||||
let value = super::is::alphanum((String::from("abc123"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::alphanum((String::from("y%*"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_alpha() {
|
||||
let value = super::is::alpha((String::from("abc"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::alpha((String::from("1234"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_ascii() {
|
||||
let value = super::is::ascii((String::from("abc"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::ascii((String::from("中国"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_domain() {
|
||||
let value = super::is::domain((String::from("食狮.中国"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::domain((String::from("example-.com"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_email() {
|
||||
let input = (String::from("user@[fd79:cdcb:38cc:9dd:f686:e06d:32f3:c123]"),);
|
||||
let value = super::is::email(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let input = (String::from("john..doe@example.com"),);
|
||||
let value = super::is::email(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_hexadecimal() {
|
||||
let value = super::is::hexadecimal((String::from("00FF00"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::hexadecimal((String::from("SurrealDB"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_latitude() {
|
||||
let value = super::is::latitude((String::from("-0.118092"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::latitude((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_longitude() {
|
||||
let value = super::is::longitude((String::from("51.509865"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::longitude((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_numeric() {
|
||||
let value = super::is::numeric((String::from("12345"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::numeric((String::from("abcde"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_semver() {
|
||||
let value = super::is::semver((String::from("1.0.0"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::semver((String::from("1.0"),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_uuid() {
|
||||
let input = (String::from("123e4567-e89b-12d3-a456-426614174000").into(),);
|
||||
let value = super::is::uuid(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let input = (String::from("foo-bar").into(),);
|
||||
let value = super::is::uuid(input).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,3 +119,111 @@ pub fn thing((arg1, arg2): (Value, Option<Value>)) -> Result<Value, Error> {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub mod is {
|
||||
use crate::err::Error;
|
||||
use crate::sql::value::Value;
|
||||
use crate::sql::Geometry;
|
||||
|
||||
pub fn array((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_array().into())
|
||||
}
|
||||
|
||||
pub fn bool((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_bool().into())
|
||||
}
|
||||
|
||||
pub fn bytes((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_bytes().into())
|
||||
}
|
||||
|
||||
pub fn collection((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::Collection(_))).into())
|
||||
}
|
||||
|
||||
pub fn datetime((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_datetime().into())
|
||||
}
|
||||
|
||||
pub fn decimal((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_decimal().into())
|
||||
}
|
||||
|
||||
pub fn duration((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_duration().into())
|
||||
}
|
||||
|
||||
pub fn float((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_float().into())
|
||||
}
|
||||
|
||||
pub fn geometry((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_geometry().into())
|
||||
}
|
||||
|
||||
pub fn int((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_int().into())
|
||||
}
|
||||
|
||||
pub fn line((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::Line(_))).into())
|
||||
}
|
||||
|
||||
pub fn null((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_null().into())
|
||||
}
|
||||
|
||||
pub fn multiline((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::MultiLine(_))).into())
|
||||
}
|
||||
|
||||
pub fn multipoint((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::MultiPoint(_))).into())
|
||||
}
|
||||
|
||||
pub fn multipolygon((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::MultiPolygon(_))).into())
|
||||
}
|
||||
|
||||
pub fn number((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_number().into())
|
||||
}
|
||||
|
||||
pub fn object((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_object().into())
|
||||
}
|
||||
|
||||
pub fn point((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::Point(_))).into())
|
||||
}
|
||||
|
||||
pub fn polygon((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(matches!(arg, Value::Geometry(Geometry::Polygon(_))).into())
|
||||
}
|
||||
|
||||
pub fn record((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_record().into())
|
||||
}
|
||||
|
||||
pub fn string((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_strand().into())
|
||||
}
|
||||
|
||||
pub fn uuid((arg,): (Value,)) -> Result<Value, Error> {
|
||||
Ok(arg.is_uuid().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::sql::value::Value;
|
||||
|
||||
#[test]
|
||||
fn is_array() {
|
||||
let value = super::is::array((vec!["hello", "world"].into(),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(true));
|
||||
|
||||
let value = super::is::array(("test".into(),)).unwrap();
|
||||
assert_eq!(value, Value::Bool(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,7 +311,6 @@ pub(crate) fn function_names(i: &str) -> IResult<&str, &str> {
|
|||
preceded(tag("encoding::"), cut(function_encoding)),
|
||||
preceded(tag("geo::"), cut(function_geo)),
|
||||
preceded(tag("http::"), cut(function_http)),
|
||||
preceded(tag("is::"), cut(function_is)),
|
||||
// Don't cut in time and math for now since there are also constant's with the same
|
||||
// prefix.
|
||||
preceded(tag("math::"), function_math),
|
||||
|
@ -446,24 +445,6 @@ fn function_http(i: &str) -> IResult<&str, &str> {
|
|||
alt((tag("head"), tag("get"), tag("put"), tag("post"), tag("patch"), tag("delete")))(i)
|
||||
}
|
||||
|
||||
fn function_is(i: &str) -> IResult<&str, &str> {
|
||||
alt((
|
||||
tag("alphanum"),
|
||||
tag("alpha"),
|
||||
tag("ascii"),
|
||||
tag("datetime"),
|
||||
tag("domain"),
|
||||
tag("email"),
|
||||
tag("hexadecimal"),
|
||||
tag("latitude"),
|
||||
tag("longitude"),
|
||||
tag("numeric"),
|
||||
tag("semver"),
|
||||
tag("url"),
|
||||
tag("uuid"),
|
||||
))(i)
|
||||
}
|
||||
|
||||
fn function_math(i: &str) -> IResult<&str, &str> {
|
||||
alt((
|
||||
alt((
|
||||
|
@ -571,6 +552,24 @@ fn function_string(i: &str) -> IResult<&str, &str> {
|
|||
tag("uppercase"),
|
||||
tag("words"),
|
||||
preceded(tag("distance::"), alt((tag("hamming"), tag("levenshtein")))),
|
||||
preceded(
|
||||
tag("is::"),
|
||||
alt((
|
||||
tag("alphanum"),
|
||||
tag("alpha"),
|
||||
tag("ascii"),
|
||||
tag("datetime"),
|
||||
tag("domain"),
|
||||
tag("email"),
|
||||
tag("hexadecimal"),
|
||||
tag("latitude"),
|
||||
tag("longitude"),
|
||||
tag("numeric"),
|
||||
tag("semver"),
|
||||
tag("url"),
|
||||
tag("uuid"),
|
||||
)),
|
||||
),
|
||||
preceded(tag("similarity::"), alt((tag("fuzzy"), tag("jaro"), tag("smithwaterman")))),
|
||||
))(i)
|
||||
}
|
||||
|
@ -616,6 +615,37 @@ fn function_type(i: &str) -> IResult<&str, &str> {
|
|||
tag("string"),
|
||||
tag("table"),
|
||||
tag("thing"),
|
||||
preceded(
|
||||
tag("is::"),
|
||||
alt((
|
||||
alt((
|
||||
tag("array"),
|
||||
tag("bool"),
|
||||
tag("bytes"),
|
||||
tag("collection"),
|
||||
tag("datetime"),
|
||||
tag("decimal"),
|
||||
tag("duration"),
|
||||
tag("float"),
|
||||
tag("geometry"),
|
||||
tag("int"),
|
||||
tag("line"),
|
||||
)),
|
||||
alt((
|
||||
tag("null"),
|
||||
tag("multiline"),
|
||||
tag("multipoint"),
|
||||
tag("multipolygon"),
|
||||
tag("number"),
|
||||
tag("object"),
|
||||
tag("point"),
|
||||
tag("polygon"),
|
||||
tag("record"),
|
||||
tag("string"),
|
||||
tag("uuid"),
|
||||
)),
|
||||
)),
|
||||
),
|
||||
))(i)
|
||||
}
|
||||
|
||||
|
@ -684,11 +714,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn function_arguments() {
|
||||
let sql = "is::numeric(null)";
|
||||
let sql = "string::is::numeric(null)";
|
||||
let res = function(sql);
|
||||
let out = res.unwrap().1;
|
||||
assert_eq!("is::numeric(NULL)", format!("{}", out));
|
||||
assert_eq!(out, Function::Normal(String::from("is::numeric"), vec![Value::Null]));
|
||||
assert_eq!("string::is::numeric(NULL)", format!("{}", out));
|
||||
assert_eq!(out, Function::Normal(String::from("string::is::numeric"), vec![Value::Null]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -12,7 +12,7 @@ async fn field_definition_value_assert_failure() -> Result<(), Error> {
|
|||
let sql = "
|
||||
DEFINE TABLE person SCHEMAFULL;
|
||||
DEFINE FIELD age ON person TYPE number ASSERT $value > 0;
|
||||
DEFINE FIELD email ON person TYPE string ASSERT is::email($value);
|
||||
DEFINE FIELD email ON person TYPE string ASSERT string::is::email($value);
|
||||
DEFINE FIELD name ON person TYPE option<string> VALUE $value OR 'No name';
|
||||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore';
|
||||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore', age = NONE;
|
||||
|
@ -99,7 +99,7 @@ async fn field_definition_value_assert_success() -> Result<(), Error> {
|
|||
let sql = "
|
||||
DEFINE TABLE person SCHEMAFULL;
|
||||
DEFINE FIELD age ON person TYPE number ASSERT $value > 0;
|
||||
DEFINE FIELD email ON person TYPE string ASSERT is::email($value);
|
||||
DEFINE FIELD email ON person TYPE string ASSERT string::is::email($value);
|
||||
DEFINE FIELD name ON person TYPE option<string> VALUE $value OR 'No name';
|
||||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore', age = 22;
|
||||
";
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue