[Feat] aligns DEFINE resource creation (already exists) (#4148)
This commit is contained in:
parent
2201b6d26d
commit
2913917284
26 changed files with 1572 additions and 2069 deletions
|
@ -899,7 +899,7 @@ pub enum Error {
|
|||
},
|
||||
|
||||
/// The requested user already exists
|
||||
#[error("The user '{value}' already exists")]
|
||||
#[error("The root user '{value}' already exists")]
|
||||
UserRootAlreadyExists {
|
||||
value: String,
|
||||
},
|
||||
|
|
|
@ -66,10 +66,14 @@ impl DefineAccessStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if access method already exists
|
||||
if self.if_not_exists && run.get_ns_access(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::AccessNsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_ns_access(opt.ns(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::AccessNsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::ac::new(opt.ns(), &self.name);
|
||||
|
@ -91,12 +95,14 @@ impl DefineAccessStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if access method already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_access(opt.ns(), opt.db(), &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::AccessDbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db_access(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::AccessDbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::ac::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -39,10 +39,14 @@ impl DefineAnalyzerStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if analyzer already exists
|
||||
if self.if_not_exists && run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::AzAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::AzAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::az::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -38,10 +38,14 @@ impl DefineDatabaseStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if database already exists
|
||||
if self.if_not_exists && run.get_db(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::DbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db(opt.ns(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::DbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::db::new(opt.ns(), &self.name);
|
||||
|
|
|
@ -39,12 +39,14 @@ impl DefineEventStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if event already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::EvAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::EvAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::table::ev::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
|
|
|
@ -51,11 +51,14 @@ impl DefineFieldStatement {
|
|||
run.clear_cache();
|
||||
// Check if field already exists
|
||||
let fd = self.name.to_string();
|
||||
if self.if_not_exists && run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd).await.is_ok()
|
||||
{
|
||||
return Err(Error::FdAlreadyExists {
|
||||
value: fd,
|
||||
});
|
||||
if run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::FdAlreadyExists {
|
||||
value: fd,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
|
|
|
@ -42,10 +42,14 @@ impl DefineFunctionStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if function already exists
|
||||
if self.if_not_exists && run.get_db_function(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::FcAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db_function(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::FcAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::fc::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -44,12 +44,14 @@ impl DefineIndexStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if index already exists
|
||||
let index_exists =
|
||||
run.get_tb_index(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok();
|
||||
if self.if_not_exists && index_exists {
|
||||
return Err(Error::IxAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_tb_index(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::IxAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// If we are strict, check that the table exists
|
||||
run.check_ns_db_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?;
|
||||
|
@ -74,11 +76,6 @@ impl DefineIndexStatement {
|
|||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
// Clear the index store cache
|
||||
if index_exists {
|
||||
ctx.get_index_stores().index_removed(opt, &mut run, &self.what, &self.name).await?;
|
||||
}
|
||||
|
||||
// Process the statement
|
||||
let key = crate::key::table::ix::new(opt.ns(), opt.db(), &self.what, &self.name);
|
||||
run.add_ns(opt.ns(), opt.strict).await?;
|
||||
|
|
|
@ -63,12 +63,14 @@ impl DefineModelStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if model already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_model(opt.ns(), opt.db(), &self.name, &self.version).await.is_ok()
|
||||
{
|
||||
return Err(Error::MlAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db_model(opt.ns(), opt.db(), &self.name, &self.version).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::MlAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version);
|
||||
|
|
|
@ -39,10 +39,14 @@ impl DefineNamespaceStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if namespace already exists
|
||||
if self.if_not_exists && run.get_ns(&self.name).await.is_ok() {
|
||||
return Err(Error::NsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_ns(&self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::NsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
if self.id.is_none() {
|
||||
// Set the id
|
||||
|
|
|
@ -41,10 +41,14 @@ impl DefineParamStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if param already exists
|
||||
if self.if_not_exists && run.get_db_param(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::PaAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_db_param(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::PaAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::pa::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -55,10 +55,14 @@ impl DefineTableStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if table already exists
|
||||
if self.if_not_exists && run.get_tb(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
return Err(Error::TbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_tb(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::TbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -113,10 +113,14 @@ impl DefineUserStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists && run.get_root_user(&self.name).await.is_ok() {
|
||||
return Err(Error::UserRootAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
if run.get_root_user(&self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::UserRootAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::root::us::new(&self.name);
|
||||
|
@ -138,11 +142,15 @@ impl DefineUserStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists && run.get_ns_user(opt.ns(), &self.name).await.is_ok() {
|
||||
return Err(Error::UserNsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
});
|
||||
if run.get_ns_user(opt.ns(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::UserNsAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::namespace::us::new(opt.ns(), &self.name);
|
||||
|
@ -165,14 +173,16 @@ impl DefineUserStatement {
|
|||
// Clear the cache
|
||||
run.clear_cache();
|
||||
// Check if user already exists
|
||||
if self.if_not_exists
|
||||
&& run.get_db_user(opt.ns(), opt.db(), &self.name).await.is_ok()
|
||||
{
|
||||
return Err(Error::UserDbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
db: opt.db().into(),
|
||||
});
|
||||
if run.get_db_user(opt.ns(), opt.db(), &self.name).await.is_ok() {
|
||||
if self.if_not_exists {
|
||||
return Ok(Value::None);
|
||||
} else {
|
||||
return Err(Error::UserDbAlreadyExists {
|
||||
value: self.name.to_string(),
|
||||
ns: opt.ns().into(),
|
||||
db: opt.db().into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// Process the statement
|
||||
let key = crate::key::database::us::new(opt.ns(), opt.db(), &self.name);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Tests for exporting and importing data
|
||||
// Supported by the storage engines and the HTTP protocol
|
||||
|
||||
use surrealdb_core::sql::Table;
|
||||
use tokio::fs::remove_file;
|
||||
|
||||
#[test_log::test(tokio::test)]
|
||||
|
@ -22,6 +23,7 @@ async fn export_import() {
|
|||
|
||||
let res = async {
|
||||
db.export(&file).await?;
|
||||
db.query("REMOVE TABLE user").await?;
|
||||
db.import(&file).await?;
|
||||
Result::<(), Error>::Ok(())
|
||||
}
|
||||
|
|
|
@ -210,8 +210,8 @@ async fn create_with_custom_function() -> Result<(), Error> {
|
|||
#[tokio::test]
|
||||
async fn create_or_insert_with_permissions() -> Result<(), Error> {
|
||||
let sql = "
|
||||
CREATE user:test;
|
||||
DEFINE TABLE user SCHEMAFULL PERMISSIONS FULL;
|
||||
CREATE user:test;
|
||||
DEFINE TABLE demo SCHEMAFULL PERMISSIONS FOR select, create, update WHERE user = $auth.id;
|
||||
DEFINE FIELD user ON TABLE demo VALUE $auth.id;
|
||||
";
|
||||
|
|
1164
lib/tests/define.rs
1164
lib/tests/define.rs
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use crate::helpers::Test;
|
||||
use helpers::new_ds;
|
||||
use helpers::with_enough_stack;
|
||||
use surrealdb::dbs::Session;
|
||||
|
@ -926,27 +927,15 @@ async fn field_definition_flexible_array_any() -> Result<(), Error> {
|
|||
let sql = "
|
||||
DEFINE TABLE user SCHEMAFULL;
|
||||
DEFINE FIELD custom ON user TYPE option<array>;
|
||||
REMOVE FIELD custom.* ON user;
|
||||
DEFINE FIELD custom.* ON user FLEXIBLE TYPE any;
|
||||
CREATE user:one CONTENT { custom: ['sometext'] };
|
||||
CREATE user:two CONTENT { custom: [ ['sometext'] ] };
|
||||
CREATE user:three CONTENT { custom: [ { key: 'sometext' } ] };
|
||||
";
|
||||
let dbs = new_ds().await?.with_auth_enabled(true);
|
||||
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;
|
||||
assert!(tmp.is_ok());
|
||||
//
|
||||
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(
|
||||
let mut t = Test::new(sql).await?;
|
||||
t.skip_ok(4)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
custom: [
|
||||
|
@ -955,11 +944,8 @@ async fn field_definition_flexible_array_any() -> Result<(), Error> {
|
|||
id: user:one
|
||||
},
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
custom: [
|
||||
|
@ -970,11 +956,8 @@ async fn field_definition_flexible_array_any() -> Result<(), Error> {
|
|||
id: user:two
|
||||
},
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
custom: [
|
||||
|
@ -985,8 +968,6 @@ async fn field_definition_flexible_array_any() -> Result<(), Error> {
|
|||
id: user:three
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -598,7 +598,7 @@ async fn select_array_group_group_by() -> Result<(), Error> {
|
|||
let mut res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(&mut res, 4);
|
||||
skip_ok(&mut res, 4)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -636,7 +636,7 @@ async fn select_array_count_subquery_group_by() -> Result<(), Error> {
|
|||
let mut res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
|
|
@ -197,19 +197,24 @@ pub fn with_enough_stack(
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn skip_ok_pos(res: &mut Vec<Response>, pos: usize) -> Result<(), Error> {
|
||||
assert!(!res.is_empty(), "At position {pos} - No more result!");
|
||||
let r = res.remove(0).result;
|
||||
let _ = r.is_err_and(|e| {
|
||||
panic!("At position {pos} - Statement fails with: {e}");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Skip the specified number of successful results from a vector of responses.
|
||||
/// This function will panic if there are not enough results in the vector or if an error occurs.
|
||||
#[allow(dead_code)]
|
||||
pub fn skip_ok(res: &mut Vec<Response>, skip: usize) {
|
||||
pub fn skip_ok(res: &mut Vec<Response>, skip: usize) -> Result<(), Error> {
|
||||
for i in 0..skip {
|
||||
if res.is_empty() {
|
||||
panic!("No more result #{i}");
|
||||
}
|
||||
let r = res.remove(0).result;
|
||||
let _ = r.is_err_and(|e| {
|
||||
panic!("Statement #{i} fails with: {e}");
|
||||
});
|
||||
skip_ok_pos(res, i)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Struct representing a test scenario.
|
||||
|
@ -238,14 +243,7 @@ impl Test {
|
|||
/// Arguments `sql` - A string slice representing the SQL query.
|
||||
/// Panics if an error occurs.
|
||||
#[allow(dead_code)]
|
||||
pub async fn new(sql: &str) -> Self {
|
||||
Self::try_new(sql).await.unwrap_or_else(|e| panic!("{e}"))
|
||||
}
|
||||
|
||||
/// Create a new instance of the Test struct and execute the given SQL statement.
|
||||
///
|
||||
#[allow(dead_code)]
|
||||
pub async fn try_new(sql: &str) -> Result<Self, Error> {
|
||||
pub async fn new(sql: &str) -> Result<Self, Error> {
|
||||
let ds = new_ds().await?;
|
||||
let session = Session::owner().with_ns("test").with_db("test");
|
||||
let responses = ds.execute(sql, &session, None).await?;
|
||||
|
@ -260,52 +258,50 @@ impl Test {
|
|||
/// Checks if the number of responses matches the expected size.
|
||||
/// Panics if the number of responses does not match the expected size
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_size(&mut self, expected: usize) -> &mut Self {
|
||||
pub fn expect_size(&mut self, expected: usize) -> Result<&mut Self, Error> {
|
||||
assert_eq!(
|
||||
self.responses.len(),
|
||||
expected,
|
||||
"Unexpected number of results: {} - Expected: {expected}",
|
||||
self.responses.len()
|
||||
);
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Retrieves the next response from the responses list.
|
||||
/// This method will panic if the responses list is empty, indicating that there are no more responses to retrieve.
|
||||
/// The panic message will include the last position in the responses list before it was emptied.
|
||||
#[allow(dead_code)]
|
||||
pub fn next(&mut self) -> Response {
|
||||
if self.responses.is_empty() {
|
||||
panic!("No response left - last position: {}", self.pos);
|
||||
}
|
||||
pub fn next(&mut self) -> Result<Response, Error> {
|
||||
assert!(!self.responses.is_empty(), "No response left - last position: {}", self.pos);
|
||||
self.pos += 1;
|
||||
self.responses.remove(0)
|
||||
Ok(self.responses.remove(0))
|
||||
}
|
||||
|
||||
/// Retrieves the next value from the responses list.
|
||||
/// This method will panic if the responses list is empty, indicating that there are no more responses to retrieve.
|
||||
/// The panic message will include the last position in the responses list before it was emptied.
|
||||
pub fn next_value(&mut self) -> Value {
|
||||
self.next()
|
||||
.result
|
||||
.unwrap_or_else(|e| panic!("Unexpected error: {e} - last position: {}", self.pos))
|
||||
pub fn next_value(&mut self) -> Result<Value, Error> {
|
||||
self.next()?.result
|
||||
}
|
||||
|
||||
/// Skips a specified number of elements from the beginning of the `responses` vector
|
||||
/// and updates the position.
|
||||
#[allow(dead_code)]
|
||||
pub fn skip_ok(&mut self, skip: usize) -> &mut Self {
|
||||
skip_ok(&mut self.responses, skip);
|
||||
self.pos += skip;
|
||||
self
|
||||
pub fn skip_ok(&mut self, skip: usize) -> Result<&mut Self, Error> {
|
||||
for _ in 0..skip {
|
||||
skip_ok_pos(&mut self.responses, self.pos)?;
|
||||
self.pos += 1;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expects the next value to be equal to the provided value.
|
||||
/// Panics if the expected value is not equal to the actual value.
|
||||
/// Compliant with NaN and Constants.
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_value(&mut self, val: Value) -> &mut Self {
|
||||
let tmp = self.next_value();
|
||||
pub fn expect_value(&mut self, val: Value) -> Result<&mut Self, Error> {
|
||||
let tmp = self.next_value()?;
|
||||
// Then check they are indeed the same values
|
||||
//
|
||||
// If it is a constant we need to transform it as a number
|
||||
|
@ -320,55 +316,65 @@ impl Test {
|
|||
assert_eq!(tmp, val, "{tmp:#}");
|
||||
}
|
||||
//
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expect values in the given slice to be present in the responses, following the same order.
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_values(&mut self, values: &[Value]) -> &mut Self {
|
||||
pub fn expect_values(&mut self, values: &[Value]) -> Result<&mut Self, Error> {
|
||||
for value in values {
|
||||
self.expect_value(value.clone());
|
||||
self.expect_value(value.clone())?;
|
||||
}
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expect the given value to be equals to the next response.
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_val(&mut self, val: &str) -> &mut Self {
|
||||
pub fn expect_val(&mut self, val: &str) -> Result<&mut Self, Error> {
|
||||
self.expect_value(value(val).unwrap())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Expect values in the given slice to be present in the responses, following the same order.
|
||||
pub fn expect_vals(&mut self, vals: &[&str]) -> &mut Self {
|
||||
pub fn expect_vals(&mut self, vals: &[&str]) -> Result<&mut Self, Error> {
|
||||
for val in vals {
|
||||
self.expect_val(val);
|
||||
self.expect_val(val)?;
|
||||
}
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expects the next result to be an error with the specified error message.
|
||||
/// Expects the next result to be an error with the given check function returning true.
|
||||
/// This function will panic if the next result is not an error or if the error
|
||||
/// message does not match the specified error.
|
||||
/// message does not pass the check.
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_error(&mut self, error: &str) -> &mut Self {
|
||||
let tmp = self.next().result;
|
||||
assert!(
|
||||
matches!(
|
||||
&tmp,
|
||||
Err(e) if e.to_string() == error
|
||||
),
|
||||
"{tmp:?} didn't match {error}"
|
||||
);
|
||||
self
|
||||
pub fn expect_error_func<F: Fn(&Error) -> bool>(
|
||||
&mut self,
|
||||
check: F,
|
||||
) -> Result<&mut Self, Error> {
|
||||
let tmp = self.next()?.result;
|
||||
match &tmp {
|
||||
Ok(val) => {
|
||||
panic!("At position {} - Expect error, but got OK: {val}", self.pos);
|
||||
}
|
||||
Err(e) => {
|
||||
assert!(check(e), "At position {} - Err didn't match: {e}", self.pos)
|
||||
}
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_errors(&mut self, errors: &[&str]) -> &mut Self {
|
||||
/// Expects the next result to be an error with the specified error message.
|
||||
pub fn expect_error(&mut self, error: &str) -> Result<&mut Self, Error> {
|
||||
self.expect_error_func(|e| e.to_string() == error)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_errors(&mut self, errors: &[&str]) -> Result<&mut Self, Error> {
|
||||
for error in errors {
|
||||
self.expect_error(error);
|
||||
self.expect_error(error)?;
|
||||
}
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Expects the next value to be a floating-point number and compares it with the given value.
|
||||
|
@ -383,8 +389,8 @@ impl Test {
|
|||
/// Panics if the next value is not a number or if the difference
|
||||
/// between the expected and actual value exceeds the precision.
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_float(&mut self, val: f64, precision: f64) -> &mut Self {
|
||||
let tmp = self.next_value();
|
||||
pub fn expect_float(&mut self, val: f64, precision: f64) -> Result<&mut Self, Error> {
|
||||
let tmp = self.next_value()?;
|
||||
if let Value::Number(Number::Float(n)) = tmp {
|
||||
let diff = (n - val).abs();
|
||||
assert!(
|
||||
|
@ -394,15 +400,15 @@ impl Test {
|
|||
} else {
|
||||
panic!("At position {}: Value {tmp} is not a number", self.pos);
|
||||
}
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_floats(&mut self, vals: &[f64], precision: f64) -> &mut Self {
|
||||
pub fn expect_floats(&mut self, vals: &[f64], precision: f64) -> Result<&mut Self, Error> {
|
||||
for val in vals {
|
||||
self.expect_float(*val, precision);
|
||||
self.expect_float(*val, precision)?;
|
||||
}
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ async fn select_where_matches_using_index() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(res, 3);
|
||||
skip_ok(res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -74,7 +74,7 @@ async fn select_where_matches_without_using_index_iterator() -> Result<(), Error
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
skip_ok(res, 4);
|
||||
skip_ok(res, 4)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -133,7 +133,7 @@ async fn select_where_matches_using_index_and_arrays(parallel: bool) -> Result<(
|
|||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(res, 3);
|
||||
skip_ok(res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -204,7 +204,7 @@ async fn select_where_matches_partial_highlight() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
skip_ok(res, 3);
|
||||
skip_ok(res, 3)?;
|
||||
//
|
||||
for i in 0..2 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -289,7 +289,7 @@ async fn select_where_matches_partial_highlight_ngram() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 10);
|
||||
//
|
||||
skip_ok(res, 3);
|
||||
skip_ok(res, 3)?;
|
||||
//
|
||||
for i in 0..3 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -375,7 +375,7 @@ async fn select_where_matches_using_index_and_objects(parallel: bool) -> Result<
|
|||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(res, 3);
|
||||
skip_ok(res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -443,7 +443,7 @@ async fn select_where_matches_using_index_offsets() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(res, 4);
|
||||
skip_ok(res, 4)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -480,7 +480,7 @@ async fn select_where_matches_using_index_and_score() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
skip_ok(res, 6);
|
||||
skip_ok(res, 6)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -517,7 +517,7 @@ async fn select_where_matches_without_using_index_and_score() -> Result<(), Erro
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
//
|
||||
skip_ok(res, 7);
|
||||
skip_ok(res, 7)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -565,7 +565,7 @@ async fn select_where_matches_without_complex_query() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 10);
|
||||
//
|
||||
skip_ok(res, 6);
|
||||
skip_ok(res, 6)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val_docs = Value::parse(
|
||||
|
@ -654,7 +654,7 @@ async fn select_where_matches_mixing_indexes() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
skip_ok(res, 5);
|
||||
skip_ok(res, 5)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
|
|
@ -12,7 +12,7 @@ use surrealdb::sql::Value;
|
|||
async fn select_where_iterate_three_multi_index() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &three_multi_index_query("", ""), 12).await?;
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }, { name: 'Lizzie' }]")?;
|
||||
// OR results
|
||||
check_result(&mut res, THREE_MULTI_INDEX_EXPLAIN)?;
|
||||
|
@ -26,7 +26,7 @@ async fn select_where_iterate_three_multi_index() -> Result<(), Error> {
|
|||
async fn select_where_iterate_three_multi_index_parallel() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &three_multi_index_query("", "PARALLEL"), 12).await?;
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }, { name: 'Lizzie' }]")?;
|
||||
check_result(&mut res, THREE_MULTI_INDEX_EXPLAIN)?;
|
||||
|
@ -45,7 +45,7 @@ async fn select_where_iterate_three_multi_index_with_all_index() -> Result<(), E
|
|||
12,
|
||||
)
|
||||
.await?;
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }, { name: 'Lizzie' }]")?;
|
||||
check_result(&mut res, THREE_MULTI_INDEX_EXPLAIN)?;
|
||||
|
@ -60,7 +60,7 @@ async fn select_where_iterate_three_multi_index_with_one_ft_index() -> Result<()
|
|||
let dbs = new_ds().await?;
|
||||
let mut res =
|
||||
execute_test(&dbs, &three_multi_index_query("WITH INDEX ft_company", ""), 12).await?;
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Lizzie' }, { name: 'Tobie' } ]")?;
|
||||
|
@ -76,7 +76,7 @@ async fn select_where_iterate_three_multi_index_with_one_index() -> Result<(), E
|
|||
let dbs = new_ds().await?;
|
||||
let mut res =
|
||||
execute_test(&dbs, &three_multi_index_query("WITH INDEX uniq_name", ""), 12).await?;
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Lizzie' }, { name: 'Tobie' } ]")?;
|
||||
|
@ -91,7 +91,7 @@ async fn select_where_iterate_three_multi_index_with_one_index() -> Result<(), E
|
|||
async fn select_where_iterate_two_multi_index() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &two_multi_index_query("", ""), 9).await?;
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }]")?;
|
||||
check_result(&mut res, TWO_MULTI_INDEX_EXPLAIN)?;
|
||||
|
@ -105,7 +105,7 @@ async fn select_where_iterate_two_multi_index() -> Result<(), Error> {
|
|||
async fn select_where_iterate_two_multi_index_with_one_index() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &two_multi_index_query("WITH INDEX idx_genre", ""), 9).await?;
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }]")?;
|
||||
check_result(&mut res, &table_explain(2))?;
|
||||
|
@ -120,7 +120,7 @@ async fn select_where_iterate_two_multi_index_with_two_index() -> Result<(), Err
|
|||
let dbs = new_ds().await?;
|
||||
let mut res =
|
||||
execute_test(&dbs, &two_multi_index_query("WITH INDEX idx_genre,uniq_name", ""), 9).await?;
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }]")?;
|
||||
check_result(&mut res, TWO_MULTI_INDEX_EXPLAIN)?;
|
||||
|
@ -134,7 +134,7 @@ async fn select_where_iterate_two_multi_index_with_two_index() -> Result<(), Err
|
|||
async fn select_where_iterate_two_no_index() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &two_multi_index_query("WITH NOINDEX", ""), 9).await?;
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
// OR results
|
||||
check_result(&mut res, "[{ name: 'Jaime' }, { name: 'Tobie' }]")?;
|
||||
check_result(&mut res, &table_explain_no_index(2))?;
|
||||
|
@ -547,7 +547,7 @@ async fn select_range(
|
|||
) -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &range_test(unique, from_incl, to_incl), 8).await?;
|
||||
skip_ok(&mut res, 6);
|
||||
skip_ok(&mut res, 6)?;
|
||||
{
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(explain);
|
||||
|
@ -790,7 +790,7 @@ async fn select_single_range_operator(
|
|||
) -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, &single_range_operator_test(unique, op), 6).await?;
|
||||
skip_ok(&mut res, 4);
|
||||
skip_ok(&mut res, 4)?;
|
||||
{
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(explain);
|
||||
|
@ -990,7 +990,7 @@ async fn select_with_idiom_param_value() -> Result<(), Error> {
|
|||
.to_owned();
|
||||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
r#"[
|
||||
|
@ -1079,7 +1079,7 @@ async fn test_contains(
|
|||
let val = Value::parse(result);
|
||||
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
|
||||
}
|
||||
skip_ok(&mut res, 1);
|
||||
skip_ok(&mut res, 1)?;
|
||||
{
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(index_explain);
|
||||
|
@ -1097,7 +1097,7 @@ async fn test_contains(
|
|||
async fn select_contains() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, CONTAINS_CONTENT, 3).await?;
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
|
||||
const SQL: &str = r#"
|
||||
SELECT id FROM student WHERE marks.*.subject CONTAINS "english" EXPLAIN;
|
||||
|
@ -1142,7 +1142,7 @@ async fn select_contains() -> Result<(), Error> {
|
|||
async fn select_contains_all() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, CONTAINS_CONTENT, 3).await?;
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
const SQL: &str = r#"
|
||||
SELECT id FROM student WHERE marks.*.subject CONTAINSALL ["hindi", "maths"] EXPLAIN;
|
||||
SELECT id FROM student WHERE marks.*.subject CONTAINSALL ["hindi", "maths"];
|
||||
|
@ -1185,7 +1185,7 @@ async fn select_contains_all() -> Result<(), Error> {
|
|||
async fn select_contains_any() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, CONTAINS_CONTENT, 3).await?;
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
const SQL: &str = r#"
|
||||
SELECT id FROM student WHERE marks.*.subject CONTAINSANY ["tamil", "french"] EXPLAIN;
|
||||
SELECT id FROM student WHERE marks.*.subject CONTAINSANY ["tamil", "french"];
|
||||
|
@ -1233,7 +1233,7 @@ const CONTAINS_UNIQUE_CONTENT: &str = r#"
|
|||
async fn select_unique_contains() -> Result<(), Error> {
|
||||
let dbs = new_ds().await?;
|
||||
let mut res = execute_test(&dbs, CONTAINS_UNIQUE_CONTENT, 3).await?;
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
|
||||
const SQL: &str = r#"
|
||||
SELECT id FROM student WHERE subject CONTAINS "english" EXPLAIN;
|
||||
|
@ -1291,7 +1291,7 @@ async fn select_with_datetime_value() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 8);
|
||||
skip_ok(&mut res, 4);
|
||||
skip_ok(&mut res, 4)?;
|
||||
|
||||
for _ in 0..2 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -1354,7 +1354,7 @@ async fn select_with_uuid_value() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 7);
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
|
||||
for _ in 0..2 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -1415,7 +1415,7 @@ async fn select_with_in_operator() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 7);
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
|
||||
for _ in 0..2 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -1476,7 +1476,7 @@ async fn select_with_in_operator_uniq_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 8);
|
||||
skip_ok(&mut res, 2);
|
||||
skip_ok(&mut res, 2)?;
|
||||
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(r#"[]"#);
|
||||
|
@ -1549,7 +1549,7 @@ async fn select_with_in_operator_multiple_indexes() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 17);
|
||||
skip_ok(&mut res, 9);
|
||||
skip_ok(&mut res, 9)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -1933,7 +1933,7 @@ async fn select_with_record_id_link_no_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 8);
|
||||
skip_ok(&mut res, 6);
|
||||
skip_ok(&mut res, 6)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -1992,7 +1992,7 @@ async fn select_with_record_id_link_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 10);
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
//
|
||||
let expected = Value::parse(
|
||||
r#"[
|
||||
|
@ -2057,7 +2057,7 @@ async fn select_with_record_id_link_unique_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 10);
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
//
|
||||
let expected = Value::parse(
|
||||
r#"[
|
||||
|
@ -2121,7 +2121,7 @@ async fn select_with_record_id_link_unique_remote_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 10);
|
||||
skip_ok(&mut res, 8);
|
||||
skip_ok(&mut res, 8)?;
|
||||
//
|
||||
let expected = Value::parse(
|
||||
r#"[
|
||||
|
@ -2188,7 +2188,7 @@ async fn select_with_record_id_link_full_text_index() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 9);
|
||||
skip_ok(&mut res, 7);
|
||||
skip_ok(&mut res, 7)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -2245,7 +2245,7 @@ async fn select_with_record_id_link_full_text_no_record_index() -> Result<(), Er
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
|
||||
assert_eq!(res.len(), 8);
|
||||
skip_ok(&mut res, 6);
|
||||
skip_ok(&mut res, 6)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -2313,7 +2313,7 @@ async fn select_with_record_id_index() -> Result<(), Error> {
|
|||
);
|
||||
//
|
||||
assert_eq!(res.len(), 15);
|
||||
skip_ok(&mut res, 2);
|
||||
skip_ok(&mut res, 2)?;
|
||||
//
|
||||
for t in ["CONTAINS", "CONTAINSANY", "IN"] {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
@ -2345,7 +2345,7 @@ async fn select_with_record_id_index() -> Result<(), Error> {
|
|||
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
|
||||
}
|
||||
//
|
||||
skip_ok(&mut res, 1);
|
||||
skip_ok(&mut res, 1)?;
|
||||
// CONTAINS
|
||||
let tmp = res.remove(0).result?;
|
||||
assert_eq!(format!("{:#}", tmp), format!("{:#}", expected));
|
||||
|
@ -2450,7 +2450,7 @@ async fn select_with_exact_operator() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 8);
|
||||
skip_ok(&mut res, 4);
|
||||
skip_ok(&mut res, 4)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -2553,7 +2553,7 @@ async fn select_with_non_boolean_expression() -> Result<(), Error> {
|
|||
let mut res = dbs.execute(&sql, &ses, None).await?;
|
||||
//
|
||||
assert_eq!(res.len(), 15);
|
||||
skip_ok(&mut res, 5);
|
||||
skip_ok(&mut res, 5)?;
|
||||
//
|
||||
for i in 0..5 {
|
||||
let tmp = res.remove(0).result?;
|
||||
|
|
|
@ -133,7 +133,7 @@ async fn define_foreign_table_no_doubles() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
skip_ok(res, 5);
|
||||
skip_ok(res, 5)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -218,11 +218,11 @@ async fn define_foreign_table_group(cond: bool, agr: &str) -> Result<(), Error>
|
|||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 29);
|
||||
//
|
||||
skip_ok(res, 2);
|
||||
skip_ok(res, 2)?;
|
||||
//
|
||||
for i in 0..9 {
|
||||
// Skip the UPDATE or DELETE statement
|
||||
skip_ok(res, 1);
|
||||
skip_ok(res, 1)?;
|
||||
// Get the computed result
|
||||
let comp = res.remove(0).result?;
|
||||
// Get the projected result
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use crate::helpers::Test;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
|
@ -196,127 +197,87 @@ async fn strict_typing_none_null() -> Result<(), Error> {
|
|||
UPDATE person:test SET name = NULL;
|
||||
UPDATE person:test SET name = NONE;
|
||||
--
|
||||
REMOVE TABLE person;
|
||||
DEFINE TABLE person SCHEMAFULL;
|
||||
DEFINE FIELD name ON TABLE person TYPE option<string | null>;
|
||||
UPDATE person:test SET name = 'Tobie';
|
||||
UPDATE person:test SET name = NULL;
|
||||
UPDATE person:test SET name = NONE;
|
||||
--
|
||||
REMOVE TABLE person;
|
||||
DEFINE TABLE person SCHEMAFULL;
|
||||
DEFINE FIELD name ON TABLE person TYPE string | null;
|
||||
UPDATE person:test SET name = 'Tobie';
|
||||
UPDATE person:test SET name = NULL;
|
||||
UPDATE person:test SET name = NONE;
|
||||
";
|
||||
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(), 15);
|
||||
let mut t = Test::new(sql).await?;
|
||||
//
|
||||
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(
|
||||
t.skip_ok(2)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Tobie',
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(
|
||||
tmp.err(),
|
||||
Some(e) if e.to_string() == "Found NULL for field `name`, with record `person:test`, but expected a option<string>"
|
||||
));
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_error(
|
||||
"Found NULL for field `name`, with record `person:test`, but expected a option<string>",
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
)?;
|
||||
//
|
||||
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(
|
||||
t.skip_ok(3)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Tobie',
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: NULL,
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
)?;
|
||||
//
|
||||
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(
|
||||
t.skip_ok(3)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: 'Tobie',
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: person:test,
|
||||
name: NULL,
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(
|
||||
tmp.err(),
|
||||
Some(e) if e.to_string() == "Found NONE for field `name`, with record `person:test`, but expected a string | null"
|
||||
));
|
||||
)?;
|
||||
t.expect_error(
|
||||
"Found NONE for field `name`, with record `person:test`, but expected a string | null",
|
||||
)?;
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use crate::helpers::Test;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
|
@ -175,34 +176,23 @@ async fn update_complex_with_input() -> Result<(), Error> {
|
|||
TYPE array
|
||||
ASSERT array::len($value) > 0
|
||||
;
|
||||
REMOVE FIELD images.* ON product;
|
||||
DEFINE FIELD images.* ON product TYPE string
|
||||
VALUE string::trim($input)
|
||||
ASSERT $input AND string::len($value) > 0
|
||||
;
|
||||
CREATE product:test SET images = [' test.png '];
|
||||
";
|
||||
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(), 3);
|
||||
//
|
||||
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(
|
||||
let mut t = Test::new(sql).await?;
|
||||
t.skip_ok(3)?;
|
||||
t.expect_val(
|
||||
"[
|
||||
{
|
||||
id: product:test,
|
||||
images: ['test.png'],
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ async fn select_where_brute_force_knn() -> Result<(), Error> {
|
|||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
skip_ok(res, 4);
|
||||
skip_ok(res, 4)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -229,8 +229,8 @@ async fn select_where_hnsw_knn() -> Result<(), Error> {
|
|||
SELECT id, vector::distance::knn() AS dist FROM pts WHERE point <|2,EUCLIDEAN|> $pt;
|
||||
SELECT id, vector::distance::knn() AS dist FROM pts WHERE point <|2,EUCLIDEAN|> $pt EXPLAIN;
|
||||
";
|
||||
let mut t = Test::try_new(sql).await?;
|
||||
t.skip_ok(5);
|
||||
let mut t = Test::new(sql).await?;
|
||||
t.skip_ok(5)?;
|
||||
// KNN result with HNSW index
|
||||
t.expect_val(
|
||||
"[
|
||||
|
@ -243,7 +243,7 @@ async fn select_where_hnsw_knn() -> Result<(), Error> {
|
|||
dist: 4f
|
||||
}
|
||||
]",
|
||||
);
|
||||
)?;
|
||||
// Explains KNN with HNSW index
|
||||
t.expect_val(
|
||||
"[
|
||||
|
@ -265,7 +265,7 @@ async fn select_where_hnsw_knn() -> Result<(), Error> {
|
|||
operation: 'Collector'
|
||||
}
|
||||
]",
|
||||
);
|
||||
)?;
|
||||
// KNN result with brute force
|
||||
t.expect_val(
|
||||
"[
|
||||
|
@ -278,7 +278,7 @@ async fn select_where_hnsw_knn() -> Result<(), Error> {
|
|||
dist: 4f
|
||||
}
|
||||
]",
|
||||
);
|
||||
)?;
|
||||
// Explain KNN with brute force
|
||||
t.expect_val(
|
||||
"[
|
||||
|
@ -301,7 +301,7 @@ async fn select_where_hnsw_knn() -> Result<(), Error> {
|
|||
operation: 'Collector'
|
||||
}
|
||||
]",
|
||||
);
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ async fn select_mtree_knn_with_condition() -> Result<(), Error> {
|
|||
let mut res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -403,7 +403,7 @@ async fn select_hnsw_knn_with_condition() -> Result<(), Error> {
|
|||
let mut res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
skip_ok(&mut res, 3);
|
||||
skip_ok(&mut res, 3)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
@ -474,7 +474,7 @@ async fn select_bruteforce_knn_with_condition() -> Result<(), Error> {
|
|||
let mut res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
//
|
||||
skip_ok(&mut res, 2);
|
||||
skip_ok(&mut res, 2)?;
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
|
|
Loading…
Reference in a new issue