Ensure incorrect data causes error (#2559)
This commit is contained in:
parent
c64ccf7cf2
commit
abb5ce00db
6 changed files with 127 additions and 24 deletions
|
@ -47,7 +47,11 @@ macro_rules! into_future {
|
|||
None => resource?.into(),
|
||||
};
|
||||
let mut conn = Client::new(method);
|
||||
conn.$method(router?, Param::new(vec![param, content?])).await
|
||||
let params = match content? {
|
||||
Value::None | Value::Null => vec![param],
|
||||
content => vec![param, content],
|
||||
};
|
||||
conn.$method(router?, Param::new(params)).await
|
||||
})
|
||||
}
|
||||
};
|
||||
|
|
|
@ -124,6 +124,18 @@ pub enum Error {
|
|||
sql: String,
|
||||
},
|
||||
|
||||
/// There was an error with the SQL query
|
||||
#[error("Can not use {value} in a CONTENT clause")]
|
||||
InvalidContent {
|
||||
value: Value,
|
||||
},
|
||||
|
||||
/// There was an error with the SQL query
|
||||
#[error("Can not use {value} in a MERGE clause")]
|
||||
InvalidMerge {
|
||||
value: Value,
|
||||
},
|
||||
|
||||
/// There was an error with the provided JSON Patch
|
||||
#[error("The JSON Patch contains invalid operations. {message}")]
|
||||
InvalidPatch {
|
||||
|
|
|
@ -3,12 +3,17 @@ use crate::sql::value::Value;
|
|||
|
||||
impl Value {
|
||||
pub(crate) fn merge(&mut self, val: Value) -> Result<(), Error> {
|
||||
if val.is_object() {
|
||||
for k in val.every(None, false, false).iter() {
|
||||
match val.pick(k) {
|
||||
Value::None => self.cut(k),
|
||||
v => self.put(k, v),
|
||||
}
|
||||
// If this value is not an object, then error
|
||||
if !val.is_object() {
|
||||
return Err(Error::InvalidMerge {
|
||||
value: val,
|
||||
});
|
||||
}
|
||||
// Otherwise loop through every object field
|
||||
for k in val.every(None, false, false).iter() {
|
||||
match val.pick(k) {
|
||||
Value::None => self.cut(k),
|
||||
v => self.put(k, v),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -32,18 +37,13 @@ mod tests {
|
|||
},
|
||||
}",
|
||||
);
|
||||
let mrg = Value::None;
|
||||
let val = Value::parse(
|
||||
"{
|
||||
name: {
|
||||
first: 'Tobie',
|
||||
last: 'Morgan Hitchcock',
|
||||
initials: 'TMH',
|
||||
},
|
||||
}",
|
||||
);
|
||||
res.merge(mrg).unwrap();
|
||||
assert_eq!(res, val);
|
||||
let none = Value::None;
|
||||
match res.merge(none.clone()).unwrap_err() {
|
||||
Error::InvalidMerge {
|
||||
value,
|
||||
} => assert_eq!(value, none),
|
||||
error => panic!("unexpected error: {error:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
@ -3,9 +3,14 @@ use crate::sql::value::Value;
|
|||
|
||||
impl Value {
|
||||
pub(crate) fn replace(&mut self, val: Value) -> Result<(), Error> {
|
||||
if val.is_object() {
|
||||
*self = val;
|
||||
// If this value is not an object, then error
|
||||
if !val.is_object() {
|
||||
return Err(Error::InvalidContent {
|
||||
value: val,
|
||||
});
|
||||
}
|
||||
// Otherwise replace the current value
|
||||
*self = val;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,76 @@ use surrealdb::err::Error;
|
|||
use surrealdb::iam::Role;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_merge_and_content() -> Result<(), Error> {
|
||||
let sql = "
|
||||
CREATE person:test CONTENT { name: 'Tobie' };
|
||||
UPDATE person:test CONTENT { name: 'Jaime' };
|
||||
UPDATE person:test CONTENT 'some content';
|
||||
UPDATE person:test REPLACE 'some content';
|
||||
UPDATE person:test MERGE { age: 50 };
|
||||
UPDATE person:test MERGE 'some content';
|
||||
";
|
||||
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(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Tobie',
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Jaime',
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(
|
||||
tmp.err(),
|
||||
Some(e) if e.to_string() == r#"Can not use 'some content' in a CONTENT clause"#
|
||||
));
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(
|
||||
tmp.err(),
|
||||
Some(e) if e.to_string() == r#"Can not use 'some content' in a CONTENT clause"#
|
||||
));
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Jaime',
|
||||
age: 50,
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(
|
||||
tmp.err(),
|
||||
Some(e) if e.to_string() == r#"Can not use 'some content' in a MERGE clause"#
|
||||
));
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_simple_with_input() -> Result<(), Error> {
|
||||
let sql = "
|
||||
|
|
|
@ -357,7 +357,11 @@ impl Processor {
|
|||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "CREATE $what CONTENT $data RETURN AFTER";
|
||||
let sql = if data.is_none_or_null() {
|
||||
"CREATE $what RETURN AFTER"
|
||||
} else {
|
||||
"CREATE $what CONTENT $data RETURN AFTER"
|
||||
};
|
||||
// Specify the query parameters
|
||||
let var = Some(map! {
|
||||
String::from("what") => what.could_be_table(),
|
||||
|
@ -385,7 +389,11 @@ impl Processor {
|
|||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "UPDATE $what CONTENT $data RETURN AFTER";
|
||||
let sql = if data.is_none_or_null() {
|
||||
"UPDATE $what RETURN AFTER"
|
||||
} else {
|
||||
"UPDATE $what CONTENT $data RETURN AFTER"
|
||||
};
|
||||
// Specify the query parameters
|
||||
let var = Some(map! {
|
||||
String::from("what") => what.could_be_table(),
|
||||
|
@ -413,7 +421,11 @@ impl Processor {
|
|||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Specify the SQL query string
|
||||
let sql = "UPDATE $what MERGE $data RETURN AFTER";
|
||||
let sql = if data.is_none_or_null() {
|
||||
"UPDATE $what RETURN AFTER"
|
||||
} else {
|
||||
"UPDATE $what MERGE $data RETURN AFTER"
|
||||
};
|
||||
// Specify the query parameters
|
||||
let var = Some(map! {
|
||||
String::from("what") => what.could_be_table(),
|
||||
|
|
Loading…
Reference in a new issue