Return error when selecting from non-existent table in strict mode
Closes #13
This commit is contained in:
parent
bac8aa31a3
commit
af45b33fa0
4 changed files with 63 additions and 5 deletions
|
@ -30,6 +30,8 @@ impl Iterable {
|
|||
chn.send((None, val)).await?;
|
||||
}
|
||||
Iterable::Thing(v) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -42,6 +44,8 @@ impl Iterable {
|
|||
chn.send((Some(v), val)).await?;
|
||||
}
|
||||
Iterable::Mergeable(v, o) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -56,6 +60,8 @@ impl Iterable {
|
|||
chn.send((Some(v), val)).await?;
|
||||
}
|
||||
Iterable::Relatable(f, v, w) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -70,6 +76,8 @@ impl Iterable {
|
|||
chn.send((Some(v), val)).await?;
|
||||
}
|
||||
Iterable::Table(v) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v, opt.strict).await?;
|
||||
// Prepare the start and end keys
|
||||
let beg = thing::prefix(opt.ns(), opt.db(), &v);
|
||||
let end = thing::suffix(opt.ns(), opt.db(), &v);
|
||||
|
|
|
@ -30,6 +30,8 @@ impl Iterable {
|
|||
ite.process(ctx, opt, txn, stm, None, val).await;
|
||||
}
|
||||
Iterable::Thing(v) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -42,6 +44,8 @@ impl Iterable {
|
|||
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||
}
|
||||
Iterable::Mergeable(v, o) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -56,6 +60,8 @@ impl Iterable {
|
|||
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||
}
|
||||
Iterable::Relatable(f, v, w) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
|
||||
// Fetch the data from the store
|
||||
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||
let val = txn.clone().lock().await.get(key).await?;
|
||||
|
@ -70,6 +76,8 @@ impl Iterable {
|
|||
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||
}
|
||||
Iterable::Table(v) => {
|
||||
// Check that the table exists
|
||||
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v, opt.strict).await?;
|
||||
// Prepare the start and end keys
|
||||
let beg = thing::prefix(opt.ns(), opt.db(), &v);
|
||||
let end = thing::suffix(opt.ns(), opt.db(), &v);
|
||||
|
|
|
@ -1134,6 +1134,26 @@ impl Transaction {
|
|||
Ok(v) => Ok(v),
|
||||
}
|
||||
}
|
||||
/// Retrieve and cache a specific table definition.
|
||||
pub async fn check_ns_db_tb(
|
||||
&mut self,
|
||||
ns: &str,
|
||||
db: &str,
|
||||
tb: &str,
|
||||
strict: bool,
|
||||
) -> Result<(), Error> {
|
||||
match strict {
|
||||
// Strict mode is disabled
|
||||
false => Ok(()),
|
||||
// Strict mode is enabled
|
||||
true => {
|
||||
self.get_and_cache_ns(ns).await?;
|
||||
self.get_and_cache_db(ns, db).await?;
|
||||
self.get_and_cache_tb(ns, db, tb).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Writes the full database contents as binary SQL.
|
||||
pub async fn export(&mut self, ns: &str, db: &str, chn: Sender<Vec<u8>>) -> Result<(), Error> {
|
||||
// Output OPTIONS
|
||||
|
|
|
@ -13,11 +13,15 @@ async fn strict_mode_no_namespace() -> Result<(), Error> {
|
|||
DEFINE TABLE test;
|
||||
DEFINE FIELD extra ON test VALUE true;
|
||||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, true).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::NsNotFound)));
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::NsNotFound)));
|
||||
|
@ -42,11 +46,12 @@ async fn strict_mode_no_database() -> Result<(), Error> {
|
|||
DEFINE TABLE test;
|
||||
DEFINE FIELD extra ON test VALUE true;
|
||||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, true).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
|
@ -60,6 +65,9 @@ async fn strict_mode_no_database() -> Result<(), Error> {
|
|||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::DbNotFound)));
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::DbNotFound)));
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -71,11 +79,12 @@ async fn strict_mode_no_table() -> Result<(), Error> {
|
|||
-- DEFINE TABLE test;
|
||||
DEFINE FIELD extra ON test VALUE true;
|
||||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, true).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
assert_eq!(res.len(), 5);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
|
@ -89,6 +98,9 @@ async fn strict_mode_no_table() -> Result<(), Error> {
|
|||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::TbNotFound)));
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(matches!(tmp.err(), Some(Error::TbNotFound)));
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -100,11 +112,12 @@ async fn strict_mode_all_ok() -> Result<(), Error> {
|
|||
DEFINE TABLE test;
|
||||
DEFINE FIELD extra ON test VALUE true;
|
||||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, true).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
assert_eq!(res.len(), 6);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
|
@ -122,6 +135,10 @@ async fn strict_mode_all_ok() -> Result<(), Error> {
|
|||
let val = Value::parse("[{ id: test:tester, extra: true }]");
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse("[{ id: test:tester, extra: true }]");
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -130,6 +147,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
|||
let sql = "
|
||||
DEFINE FIELD extra ON test VALUE true;
|
||||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
INFO FOR KV;
|
||||
INFO FOR NS;
|
||||
INFO FOR DB;
|
||||
|
@ -138,7 +156,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
|||
let dbs = Datastore::new("memory").await?;
|
||||
let ses = Session::for_kv().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None, false).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
assert_eq!(res.len(), 7);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
|
@ -148,6 +166,10 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
|||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse("[{ id: test:tester, extra: true }]");
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"{
|
||||
ns: { test: 'DEFINE NAMESPACE test' },
|
||||
|
|
Loading…
Reference in a new issue