Skip ASSERT
for type option<T>
and value NONE
(#4483)
Co-authored-by: Tobie Morgan Hitchcock <tobie@surrealdb.com>
This commit is contained in:
parent
c5a6e08225
commit
3f5ef43248
2 changed files with 79 additions and 14 deletions
|
@ -6,6 +6,7 @@ use crate::err::Error;
|
||||||
use crate::iam::Action;
|
use crate::iam::Action;
|
||||||
use crate::sql::permission::Permission;
|
use crate::sql::permission::Permission;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
use crate::sql::Kind;
|
||||||
use reblessive::tree::Stk;
|
use reblessive::tree::Stk;
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
impl<'a> Document<'a> {
|
||||||
|
@ -110,6 +111,13 @@ impl<'a> Document<'a> {
|
||||||
}
|
}
|
||||||
// Check for a ASSERT clause
|
// Check for a ASSERT clause
|
||||||
if let Some(expr) = &fd.assert {
|
if let Some(expr) = &fd.assert {
|
||||||
|
match (&val, &fd.kind) {
|
||||||
|
// The field TYPE is optional, and the field
|
||||||
|
// value was not set or a NONE value was
|
||||||
|
// specified, so let's ignore the ASSERT clause
|
||||||
|
(Value::None, Some(Kind::Option(_))) => (),
|
||||||
|
// Otherwise let's process the ASSERT clause
|
||||||
|
_ => {
|
||||||
// Configure the context
|
// Configure the context
|
||||||
let mut ctx = Context::new(ctx);
|
let mut ctx = Context::new(ctx);
|
||||||
ctx.add_value("input", &inp);
|
ctx.add_value("input", &inp);
|
||||||
|
@ -117,7 +125,8 @@ impl<'a> Document<'a> {
|
||||||
ctx.add_value("after", &val);
|
ctx.add_value("after", &val);
|
||||||
ctx.add_value("before", &old);
|
ctx.add_value("before", &old);
|
||||||
// Process the ASSERT clause
|
// Process the ASSERT clause
|
||||||
if !expr.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy() {
|
if !expr.compute(stk, &ctx, opt, Some(&self.current)).await?.is_truthy()
|
||||||
|
{
|
||||||
return Err(Error::FieldValue {
|
return Err(Error::FieldValue {
|
||||||
thing: rid.to_string(),
|
thing: rid.to_string(),
|
||||||
field: fd.name.clone(),
|
field: fd.name.clone(),
|
||||||
|
@ -126,6 +135,8 @@ impl<'a> Document<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Check for a PERMISSIONS clause
|
// Check for a PERMISSIONS clause
|
||||||
if opt.check_perms(Action::Edit)? {
|
if opt.check_perms(Action::Edit)? {
|
||||||
// Get the permission clause
|
// Get the permission clause
|
||||||
|
|
|
@ -138,6 +138,60 @@ async fn field_definition_value_assert_success() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn field_definition_option_kind_assert() -> Result<(), Error> {
|
||||||
|
let sql = "
|
||||||
|
DEFINE TABLE person SCHEMAFULL;
|
||||||
|
DEFINE FIELD name ON TABLE person TYPE option<string> ASSERT string::len($value) > 3;
|
||||||
|
CREATE person:test;
|
||||||
|
CREATE person:mark SET name = 'mark';
|
||||||
|
CREATE person:bob SET name = 'bob';
|
||||||
|
";
|
||||||
|
let dbs = new_ds().await?;
|
||||||
|
let ses = Session::owner().with_ns("test").with_db("test");
|
||||||
|
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||||
|
assert_eq!(res.len(), 5);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result;
|
||||||
|
assert!(tmp.is_ok());
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result;
|
||||||
|
assert!(tmp.is_ok());
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result?;
|
||||||
|
let val = Value::parse(
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
id: person:test
|
||||||
|
}
|
||||||
|
]",
|
||||||
|
);
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result?;
|
||||||
|
let val = Value::parse(
|
||||||
|
"[
|
||||||
|
{
|
||||||
|
id: person:mark,
|
||||||
|
name: 'mark'
|
||||||
|
}
|
||||||
|
]",
|
||||||
|
);
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result;
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
&tmp,
|
||||||
|
Err(e) if e.to_string() == "Found 'bob' for field `name`, with record `person:bob`, but field must conform to: string::len($value) > 3"
|
||||||
|
),
|
||||||
|
"{}",
|
||||||
|
tmp.unwrap_err().to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn field_definition_empty_nested_objects() -> Result<(), Error> {
|
async fn field_definition_empty_nested_objects() -> Result<(), Error> {
|
||||||
let sql = "
|
let sql = "
|
||||||
|
|
Loading…
Reference in a new issue