From d9ae887d50712c81510332694c1c90320d75b342 Mon Sep 17 00:00:00 2001 From: Gerard Guillemas Martos Date: Tue, 11 Jun 2024 11:34:21 +0200 Subject: [PATCH] Resolve panics when a NS or a DB are not configured (#4157) Co-authored-by: Emmanuel Keller --- core/src/dbs/options.rs | 32 +++---- core/src/dbs/processor.rs | 44 +++++----- core/src/doc/allow.rs | 2 +- core/src/doc/changefeeds.rs | 6 +- core/src/doc/compute.rs | 2 +- core/src/doc/document.rs | 18 ++-- core/src/doc/edges.rs | 8 +- core/src/doc/field.rs | 2 +- core/src/doc/index.rs | 38 ++++---- core/src/doc/lives.rs | 2 +- core/src/doc/pluck.rs | 2 +- core/src/doc/process.rs | 2 +- core/src/doc/purge.rs | 10 +-- core/src/doc/store.rs | 2 +- core/src/fnc/search.rs | 2 +- core/src/idx/ft/mod.rs | 2 +- core/src/idx/mod.rs | 11 ++- core/src/idx/planner/executor.rs | 48 +++++------ core/src/idx/planner/iterators.rs | 32 +++---- core/src/idx/planner/tree.rs | 4 +- core/src/idx/trees/store/mod.rs | 49 +++++++---- core/src/sql/function.rs | 6 +- core/src/sql/model.rs | 8 +- core/src/sql/param.rs | 6 +- core/src/sql/statements/analyze.rs | 4 +- core/src/sql/statements/define/access.rs | 14 +-- core/src/sql/statements/define/analyzer.rs | 8 +- core/src/sql/statements/define/database.rs | 6 +- core/src/sql/statements/define/event.rs | 12 +-- core/src/sql/statements/define/field.rs | 24 +++--- core/src/sql/statements/define/function.rs | 8 +- core/src/sql/statements/define/index.rs | 20 ++--- core/src/sql/statements/define/model.rs | 8 +- core/src/sql/statements/define/param.rs | 8 +- core/src/sql/statements/define/table.rs | 22 ++--- core/src/sql/statements/define/user.rs | 20 ++--- core/src/sql/statements/info.rs | 73 ++++++++-------- core/src/sql/statements/kill.rs | 12 +-- core/src/sql/statements/live.rs | 8 +- core/src/sql/statements/rebuild.rs | 7 +- core/src/sql/statements/remove/access.rs | 8 +- core/src/sql/statements/remove/analyzer.rs | 4 +- core/src/sql/statements/remove/database.rs | 8 +- core/src/sql/statements/remove/event.rs | 6 +- core/src/sql/statements/remove/field.rs | 6 +- core/src/sql/statements/remove/function.rs | 4 +- core/src/sql/statements/remove/index.rs | 10 ++- core/src/sql/statements/remove/model.rs | 3 +- core/src/sql/statements/remove/namespace.rs | 3 +- core/src/sql/statements/remove/param.rs | 4 +- core/src/sql/statements/remove/table.rs | 12 +-- core/src/sql/statements/remove/user.rs | 8 +- core/src/sql/statements/show.rs | 4 +- lib/tests/remove.rs | 96 +++++++++++++++++++++ 54 files changed, 442 insertions(+), 326 deletions(-) diff --git a/core/src/dbs/options.rs b/core/src/dbs/options.rs index be579b9caaa..26960933609 100644 --- a/core/src/dbs/options.rs +++ b/core/src/dbs/options.rs @@ -339,13 +339,13 @@ impl Options { } /// Get currently selected NS - pub fn ns(&self) -> &str { - self.ns.as_ref().map(AsRef::as_ref).unwrap() + pub fn ns(&self) -> Result<&str, Error> { + self.ns.as_ref().map(AsRef::as_ref).ok_or(Error::NsEmpty) } /// Get currently selected DB - pub fn db(&self) -> &str { - self.db.as_ref().map(AsRef::as_ref).unwrap() + pub fn db(&self) -> Result<&str, Error> { + self.db.as_ref().map(AsRef::as_ref).ok_or(Error::DbEmpty) } /// Check whether this request supports realtime queries @@ -379,14 +379,8 @@ impl Options { // Validate the target resource and base let res = match base { Base::Root => res.on_root(), - Base::Ns => { - self.valid_for_ns()?; - res.on_ns(self.ns()) - } - Base::Db => { - self.valid_for_db()?; - res.on_db(self.ns(), self.db()) - } + Base::Ns => res.on_ns(self.ns()?), + Base::Db => res.on_db(self.ns()?, self.db()?), // TODO(gguillemas): This variant is kept in 2.0.0 for backward compatibility. Drop in 3.0.0. Base::Sc(_) => { // We should not get here, the scope base is only used in parsing for backward compatibility. @@ -406,15 +400,15 @@ impl Options { /// /// TODO: This method is called a lot during data operations, so we decided to bypass the system's authorization mechanism. /// This is a temporary solution, until we optimize the new authorization system. - pub fn check_perms(&self, action: Action) -> bool { + pub fn check_perms(&self, action: Action) -> Result { // If permissions are disabled, don't check permissions if !self.perms { - return false; + return Ok(false); } // If auth is disabled and actor is anonymous, don't check permissions if !self.auth_enabled && self.auth.is_anon() { - return false; + return Ok(false); } // Is the actor allowed to view? @@ -424,10 +418,10 @@ impl Options { let can_edit = [Role::Editor, Role::Owner].iter().any(|r| self.auth.has_role(r)); // Is the target database in the actor's level? let db_in_actor_level = self.auth.is_root() - || self.auth.is_ns() && self.auth.level().ns().unwrap() == self.ns() + || self.auth.is_ns() && self.auth.level().ns().unwrap() == self.ns()? || self.auth.is_db() - && self.auth.level().ns().unwrap() == self.ns() - && self.auth.level().db().unwrap() == self.db(); + && self.auth.level().ns().unwrap() == self.ns()? + && self.auth.level().db().unwrap() == self.db()?; // Is the actor allowed to do the action on the selected database? let is_allowed = match action { @@ -442,7 +436,7 @@ impl Options { }; // Check permissions if the author is not already allowed to do the action - !is_allowed + Ok(!is_allowed) } } diff --git a/core/src/dbs/processor.rs b/core/src/dbs/processor.rs index 8dd4ec03fc1..c1eb6c09ea6 100644 --- a/core/src/dbs/processor.rs +++ b/core/src/dbs/processor.rs @@ -187,9 +187,9 @@ impl<'a> Processor<'a> { v: Thing, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?; + ctx.tx_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 key = thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id); let val = ctx.tx_lock().await.get(key).await?; // Parse the data from the store let val = Operable::Value(match val { @@ -216,7 +216,7 @@ impl<'a> Processor<'a> { v: Thing, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?; + ctx.tx_lock().await.check_ns_db_tb(opt.ns()?, opt.db()?, &v.tb, opt.strict).await?; // Process the document record let pro = Processed { rid: Some(v), @@ -238,9 +238,9 @@ impl<'a> Processor<'a> { o: Value, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?; + ctx.tx_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 key = thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id); let val = ctx.tx_lock().await.get(key).await?; // Parse the data from the store let x = match val { @@ -273,9 +273,9 @@ impl<'a> Processor<'a> { o: Option, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?; + ctx.tx_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 key = thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id); let val = ctx.tx_lock().await.get(key).await?; // Parse the data from the store let x = match val { @@ -304,10 +304,10 @@ impl<'a> Processor<'a> { v: &Table, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), v, opt.strict).await?; + ctx.tx_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); + let beg = thing::prefix(opt.ns()?, opt.db()?, v); + let end = thing::suffix(opt.ns()?, opt.db()?, v); // Loop until no more keys let mut next_page = Some(ScanPage::from(beg..end)); while let Some(page) = next_page { @@ -358,23 +358,23 @@ impl<'a> Processor<'a> { v: Range, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?; + ctx.tx_lock().await.check_ns_db_tb(opt.ns()?, opt.db()?, &v.tb, opt.strict).await?; // Prepare the range start key let beg = match &v.beg { - Bound::Unbounded => thing::prefix(opt.ns(), opt.db(), &v.tb), - Bound::Included(id) => thing::new(opt.ns(), opt.db(), &v.tb, id).encode().unwrap(), + Bound::Unbounded => thing::prefix(opt.ns()?, opt.db()?, &v.tb), + Bound::Included(id) => thing::new(opt.ns()?, opt.db()?, &v.tb, id).encode().unwrap(), Bound::Excluded(id) => { - let mut key = thing::new(opt.ns(), opt.db(), &v.tb, id).encode().unwrap(); + let mut key = thing::new(opt.ns()?, opt.db()?, &v.tb, id).encode().unwrap(); key.push(0x00); key } }; // Prepare the range end key let end = match &v.end { - Bound::Unbounded => thing::suffix(opt.ns(), opt.db(), &v.tb), - Bound::Excluded(id) => thing::new(opt.ns(), opt.db(), &v.tb, id).encode().unwrap(), + Bound::Unbounded => thing::suffix(opt.ns()?, opt.db()?, &v.tb), + Bound::Excluded(id) => thing::new(opt.ns()?, opt.db()?, &v.tb, id).encode().unwrap(), Bound::Included(id) => { - let mut key = thing::new(opt.ns(), opt.db(), &v.tb, id).encode().unwrap(); + let mut key = thing::new(opt.ns()?, opt.db()?, &v.tb, id).encode().unwrap(); key.push(0x00); key } @@ -429,8 +429,8 @@ impl<'a> Processor<'a> { e: Edges, ) -> Result<(), Error> { // Pull out options - let ns = opt.ns(); - let db = opt.db(); + let ns = opt.ns()?; + let db = opt.db()?; let tb = &e.from.tb; let id = &e.from.id; // Fetch start and end key pairs @@ -522,7 +522,7 @@ impl<'a> Processor<'a> { // Parse the data from the store let gra: graph::Graph = graph::Graph::decode(&k)?; // Fetch the data from the store - let key = thing::new(opt.ns(), opt.db(), gra.ft, &gra.fk); + let key = thing::new(opt.ns()?, opt.db()?, gra.ft, &gra.fk); let val = ctx.tx_lock().await.get(key).await?; let rid = Thing::from((gra.ft, gra.fk)); // Parse the data from the store @@ -555,7 +555,7 @@ impl<'a> Processor<'a> { irf: IteratorRef, ) -> Result<(), Error> { // Check that the table exists - ctx.tx_lock().await.check_ns_db_tb(opt.ns(), opt.db(), &table.0, opt.strict).await?; + ctx.tx_lock().await.check_ns_db_tb(opt.ns()?, opt.db()?, &table.0, opt.strict).await?; if let Some(exe) = ctx.get_query_executor() { if let Some(mut iterator) = exe.new_iterator(opt, irf).await? { // Get the first batch @@ -623,7 +623,7 @@ impl Iterable { thg: &Thing, ) -> Result { // Fetch the data from the store - let key = thing::new(opt.ns(), opt.db(), &thg.tb, &thg.id); + let key = thing::new(opt.ns()?, opt.db()?, &thg.tb, &thg.id); // Fetch and parse the data from the store let val = tx.get(key).await?.map(Value::from).unwrap_or(Value::None); // Return the result diff --git a/core/src/doc/allow.rs b/core/src/doc/allow.rs index 21831601607..e3190527338 100644 --- a/core/src/doc/allow.rs +++ b/core/src/doc/allow.rs @@ -17,7 +17,7 @@ impl<'a> Document<'a> { // Check if this record exists if self.id.is_some() { // Should we run permissions checks? - if opt.check_perms(stm.into()) { + if opt.check_perms(stm.into())? { // Get the table let tb = self.tb(ctx, opt).await?; // Get the permission clause diff --git a/core/src/doc/changefeeds.rs b/core/src/doc/changefeeds.rs index 24b2c03583d..9440066911f 100644 --- a/core/src/doc/changefeeds.rs +++ b/core/src/doc/changefeeds.rs @@ -20,7 +20,7 @@ impl<'a> Document<'a> { // Claim transaction let mut run = ctx.tx_lock().await; // Get the database and the table for the record - let db = run.add_and_cache_db(opt.ns(), opt.db(), opt.strict).await?; + let db = run.add_and_cache_db(opt.ns()?, opt.db()?, opt.strict).await?; // Check if changefeeds are enabled if let Some(cf) = db.as_ref().changefeed.as_ref().or(tb.as_ref().changefeed.as_ref()) { // Get the arguments @@ -28,8 +28,8 @@ impl<'a> Document<'a> { let id = self.id.as_ref().unwrap(); // Create the changefeed entry run.record_change( - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, tb, id, self.initial.doc.clone(), diff --git a/core/src/doc/compute.rs b/core/src/doc/compute.rs index 0201158115f..53dec4aff7d 100644 --- a/core/src/doc/compute.rs +++ b/core/src/doc/compute.rs @@ -50,7 +50,7 @@ impl<'a> Document<'a> { // we load the new record, and reprocess Err(Error::RetryWithId(v)) => { // Fetch the data from the store - let key = crate::key::thing::new(opt.ns(), opt.db(), &v.tb, &v.id); + let key = crate::key::thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id); let val = ctx.tx_lock().await.get(key).await?; // Parse the data from the store let val = match val { diff --git a/core/src/doc/document.rs b/core/src/doc/document.rs index 9377210d042..46c496e888d 100644 --- a/core/src/doc/document.rs +++ b/core/src/doc/document.rs @@ -152,7 +152,7 @@ impl<'a> Document<'a> { // Get the record id let rid = self.id.as_ref().unwrap(); // Get the table definition - let tb = run.get_and_cache_tb(opt.ns(), opt.db(), &rid.tb).await; + let tb = run.get_and_cache_tb(opt.ns()?, opt.db()?, &rid.tb).await; // Return the table or attempt to define it match tb { // The table doesn't exist @@ -162,9 +162,9 @@ impl<'a> Document<'a> { // Allowed to run? opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?; // We can create the table automatically - run.add_and_cache_ns(opt.ns(), opt.strict).await?; - run.add_and_cache_db(opt.ns(), opt.db(), opt.strict).await?; - run.add_and_cache_tb(opt.ns(), opt.db(), &rid.tb, opt.strict).await + run.add_and_cache_ns(opt.ns()?, opt.strict).await?; + run.add_and_cache_db(opt.ns()?, opt.db()?, opt.strict).await?; + run.add_and_cache_tb(opt.ns()?, opt.db()?, &rid.tb, opt.strict).await } // There was an error Err(err) => Err(err), @@ -181,7 +181,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the table definitions - ctx.tx_lock().await.all_tb_views(opt.ns(), opt.db(), &id.tb).await + ctx.tx_lock().await.all_tb_views(opt.ns()?, opt.db()?, &id.tb).await } /// Get the events for this document pub async fn ev( @@ -192,7 +192,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the event definitions - ctx.tx_lock().await.all_tb_events(opt.ns(), opt.db(), &id.tb).await + ctx.tx_lock().await.all_tb_events(opt.ns()?, opt.db()?, &id.tb).await } /// Get the fields for this document pub async fn fd( @@ -203,7 +203,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the field definitions - ctx.tx_lock().await.all_tb_fields(opt.ns(), opt.db(), &id.tb).await + ctx.tx_lock().await.all_tb_fields(opt.ns()?, opt.db()?, &id.tb).await } /// Get the indexes for this document pub async fn ix( @@ -214,7 +214,7 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the index definitions - ctx.tx_lock().await.all_tb_indexes(opt.ns(), opt.db(), &id.tb).await + ctx.tx_lock().await.all_tb_indexes(opt.ns()?, opt.db()?, &id.tb).await } // Get the lives for this document pub async fn lv( @@ -225,6 +225,6 @@ impl<'a> Document<'a> { // Get the record id let id = self.id.as_ref().unwrap(); // Get the table definition - ctx.tx_lock().await.all_tb_lives(opt.ns(), opt.db(), &id.tb).await + ctx.tx_lock().await.all_tb_lives(opt.ns()?, opt.db()?, &id.tb).await } } diff --git a/core/src/doc/edges.rs b/core/src/doc/edges.rs index 9551c4243e5..48ce9b2acbd 100644 --- a/core/src/doc/edges.rs +++ b/core/src/doc/edges.rs @@ -30,16 +30,16 @@ impl<'a> Document<'a> { // Get temporary edge references let (ref o, ref i) = (Dir::Out, Dir::In); // Store the left pointer edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, o, rid); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &l.tb, &l.id, o, rid); run.set(key, vec![]).await?; // Store the left inner edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, i, l); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id, i, l); run.set(key, vec![]).await?; // Store the right inner edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, o, r); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id, o, r); run.set(key, vec![]).await?; // Store the right pointer edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, i, rid); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &r.tb, &r.id, i, rid); run.set(key, vec![]).await?; // Store the edges on the record self.current.doc.to_mut().put(&*EDGE, Value::Bool(true)); diff --git a/core/src/doc/field.rs b/core/src/doc/field.rs index 17e8287bc80..5c005a0acd3 100644 --- a/core/src/doc/field.rs +++ b/core/src/doc/field.rs @@ -127,7 +127,7 @@ impl<'a> Document<'a> { } } // Check for a PERMISSIONS clause - if opt.check_perms(Action::Edit) { + if opt.check_perms(Action::Edit)? { // Get the permission clause let perms = if self.is_new() { &fd.permissions.create diff --git a/core/src/doc/index.rs b/core/src/doc/index.rs index bd93bc45503..8724fc95062 100644 --- a/core/src/doc/index.rs +++ b/core/src/doc/index.rs @@ -257,26 +257,26 @@ impl<'a> IndexOperation<'a> { } } - fn get_unique_index_key(&self, v: &'a Array) -> key::index::Index { - crate::key::index::Index::new( - self.opt.ns(), - self.opt.db(), + fn get_unique_index_key(&self, v: &'a Array) -> Result { + Ok(crate::key::index::Index::new( + self.opt.ns()?, + self.opt.db()?, &self.ix.what, &self.ix.name, v, None, - ) + )) } - fn get_non_unique_index_key(&self, v: &'a Array) -> key::index::Index { - crate::key::index::Index::new( - self.opt.ns(), - self.opt.db(), + fn get_non_unique_index_key(&self, v: &'a Array) -> Result { + Ok(crate::key::index::Index::new( + self.opt.ns()?, + self.opt.db()?, &self.ix.what, &self.ix.name, v, Some(&self.rid.id), - ) + )) } async fn index_unique(&mut self, ctx: &Context<'_>) -> Result<(), Error> { @@ -285,7 +285,7 @@ impl<'a> IndexOperation<'a> { if let Some(o) = self.o.take() { let i = Indexable::new(o, self.ix); for o in i { - let key = self.get_unique_index_key(&o); + let key = self.get_unique_index_key(&o)?; match run.delc(key, Some(self.rid)).await { Err(Error::TxConditionNotMet) => Ok(()), Err(e) => Err(e), @@ -298,9 +298,9 @@ impl<'a> IndexOperation<'a> { let i = Indexable::new(n, self.ix); for n in i { if !n.is_all_none_or_null() { - let key = self.get_unique_index_key(&n); + let key = self.get_unique_index_key(&n)?; if run.putc(key, self.rid, None).await.is_err() { - let key = self.get_unique_index_key(&n); + let key = self.get_unique_index_key(&n)?; let val = run.get(key).await?.unwrap(); let rid: Thing = val.into(); return self.err_index_exists(rid, n); @@ -317,7 +317,7 @@ impl<'a> IndexOperation<'a> { if let Some(o) = self.o.take() { let i = Indexable::new(o, self.ix); for o in i { - let key = self.get_non_unique_index_key(&o); + let key = self.get_non_unique_index_key(&o)?; match run.delc(key, Some(self.rid)).await { Err(Error::TxConditionNotMet) => Ok(()), Err(e) => Err(e), @@ -329,9 +329,9 @@ impl<'a> IndexOperation<'a> { if let Some(n) = self.n.take() { let i = Indexable::new(n, self.ix); for n in i { - let key = self.get_non_unique_index_key(&n); + let key = self.get_non_unique_index_key(&n)?; if run.putc(key, self.rid, None).await.is_err() { - let key = self.get_non_unique_index_key(&n); + let key = self.get_non_unique_index_key(&n)?; let val = run.get(key).await?.unwrap(); let rid: Thing = val.into(); return self.err_index_exists(rid, n); @@ -358,7 +358,7 @@ impl<'a> IndexOperation<'a> { ctx: &Context<'_>, p: &SearchParams, ) -> Result<(), Error> { - let ikb = IndexKeyBase::new(self.opt, self.ix); + let ikb = IndexKeyBase::new(self.opt.ns()?, self.opt.db()?, self.ix)?; let mut ft = FtIndex::new(ctx, self.opt, &p.az, ikb, p, TransactionType::Write).await?; @@ -377,7 +377,7 @@ impl<'a> IndexOperation<'a> { p: &MTreeParams, ) -> Result<(), Error> { let mut tx = ctx.tx_lock().await; - let ikb = IndexKeyBase::new(self.opt, self.ix); + let ikb = IndexKeyBase::new(self.opt.ns()?, self.opt.db()?, self.ix)?; let mut mt = MTreeIndex::new(ctx.get_index_stores(), &mut tx, ikb, p, TransactionType::Write) .await?; @@ -393,7 +393,7 @@ impl<'a> IndexOperation<'a> { } async fn index_hnsw(&mut self, ctx: &Context<'_>, p: &HnswParams) -> Result<(), Error> { - let hnsw = ctx.get_index_stores().get_index_hnsw(self.opt, self.ix, p).await; + let hnsw = ctx.get_index_stores().get_index_hnsw(self.opt, self.ix, p).await?; let mut hnsw = hnsw.write().await; // Delete the old index data if let Some(o) = self.o.take() { diff --git a/core/src/doc/lives.rs b/core/src/doc/lives.rs index 16f9a2b75c6..c8b5ac7f630 100644 --- a/core/src/doc/lives.rs +++ b/core/src/doc/lives.rs @@ -79,7 +79,7 @@ impl<'a> Document<'a> { doc: &CursorDoc<'_>, ) -> Result<(), Error> { // Should we run permissions checks? - if opt.check_perms(stm.into()) { + if opt.check_perms(stm.into())? { // Get the table let tb = self.tb(ctx, opt).await?; // Process the table permissions diff --git a/core/src/doc/pluck.rs b/core/src/doc/pluck.rs index f113b5b5dd0..9ec088dca68 100644 --- a/core/src/doc/pluck.rs +++ b/core/src/doc/pluck.rs @@ -76,7 +76,7 @@ impl<'a> Document<'a> { // Check if this record exists if self.id.is_some() { // Should we run permissions checks? - if opt.check_perms(Action::View) { + if opt.check_perms(Action::View)? { // Loop through all field statements for fd in self.fd(ctx, opt).await?.iter() { // Loop over each field in document diff --git a/core/src/doc/process.rs b/core/src/doc/process.rs index 5ccf8738c9a..82c4d08232e 100644 --- a/core/src/doc/process.rs +++ b/core/src/doc/process.rs @@ -44,7 +44,7 @@ impl<'a> Document<'a> { // we load the new record, and reprocess Err(Error::RetryWithId(v)) => { // Fetch the data from the store - let key = crate::key::thing::new(opt.ns(), opt.db(), &v.tb, &v.id); + let key = crate::key::thing::new(opt.ns()?, opt.db()?, &v.tb, &v.id); let val = ctx.tx_lock().await.get(key).await?; // Parse the data from the store let val = match val { diff --git a/core/src/doc/purge.rs b/core/src/doc/purge.rs index 0fb667d744a..bce570506ab 100644 --- a/core/src/doc/purge.rs +++ b/core/src/doc/purge.rs @@ -30,7 +30,7 @@ impl<'a> Document<'a> { // Get the record id if let Some(rid) = self.id { // Purge the record data - let key = crate::key::thing::new(opt.ns(), opt.db(), &rid.tb, &rid.id); + let key = crate::key::thing::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id); run.del(key).await?; // Purge the record edges match ( @@ -42,16 +42,16 @@ impl<'a> Document<'a> { // Get temporary edge references let (ref o, ref i) = (Dir::Out, Dir::In); // Purge the left pointer edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, o, rid); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &l.tb, &l.id, o, rid); run.del(key).await?; // Purge the left inner edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, i, l); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id, i, l); run.del(key).await?; // Purge the right inner edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, o, r); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id, o, r); run.del(key).await?; // Purge the right pointer edge - let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, i, rid); + let key = crate::key::graph::new(opt.ns()?, opt.db()?, &r.tb, &r.id, i, rid); run.del(key).await?; } _ => { diff --git a/core/src/doc/store.rs b/core/src/doc/store.rs index 40d11c14cdf..49a5645f6db 100644 --- a/core/src/doc/store.rs +++ b/core/src/doc/store.rs @@ -25,7 +25,7 @@ impl<'a> Document<'a> { // Get the record id let rid = self.id.as_ref().unwrap(); // Store the record data - let key = crate::key::thing::new(opt.ns(), opt.db(), &rid.tb, &rid.id); + let key = crate::key::thing::new(opt.ns()?, opt.db()?, &rid.tb, &rid.id); // match stm { // This is a CREATE statement so try to insert the key diff --git a/core/src/fnc/search.rs b/core/src/fnc/search.rs index 391fb75753f..2bf7905d7a2 100644 --- a/core/src/fnc/search.rs +++ b/core/src/fnc/search.rs @@ -14,7 +14,7 @@ pub async fn analyze( ) -> Result { if let (Some(opt), Value::Strand(az), Value::Strand(val)) = (opt, az, val) { let az: Analyzer = - ctx.tx_lock().await.get_db_analyzer(opt.ns(), opt.db(), az.as_str()).await?.into(); + ctx.tx_lock().await.get_db_analyzer(opt.ns()?, opt.db()?, az.as_str()).await?.into(); az.analyze(stk, ctx, opt, val.0).await } else { Ok(Value::None) diff --git a/core/src/idx/ft/mod.rs b/core/src/idx/ft/mod.rs index e4aa80c7c1e..aee2cb3f6ce 100644 --- a/core/src/idx/ft/mod.rs +++ b/core/src/idx/ft/mod.rs @@ -106,7 +106,7 @@ impl FtIndex { tt: TransactionType, ) -> Result { let mut tx = ctx.tx_lock().await; - let az = tx.get_db_analyzer(opt.ns(), opt.db(), az).await?; + let az = tx.get_db_analyzer(opt.ns()?, opt.db()?, az).await?; let res = Self::with_analyzer(ctx.get_index_stores(), &mut tx, az, index_key_base, p, tt).await; drop(tx); diff --git a/core/src/idx/mod.rs b/core/src/idx/mod.rs index 764a48d5774..87d2f710a56 100644 --- a/core/src/idx/mod.rs +++ b/core/src/idx/mod.rs @@ -3,7 +3,6 @@ pub(crate) mod ft; pub mod planner; pub mod trees; -use crate::dbs::Options; use crate::err::Error; use crate::idx::docids::DocId; use crate::idx::ft::terms::TermId; @@ -42,15 +41,15 @@ struct Inner { } impl IndexKeyBase { - pub(crate) fn new(opt: &Options, ix: &DefineIndexStatement) -> Self { - Self { + pub(crate) fn new(ns: &str, db: &str, ix: &DefineIndexStatement) -> Result { + Ok(Self { inner: Arc::new(Inner { - ns: opt.ns().to_string(), - db: opt.db().to_string(), + ns: ns.to_string(), + db: db.to_string(), tb: ix.what.to_string(), ix: ix.name.to_string(), }), - } + }) } fn new_bc_key(&self, term_id: TermId) -> Key { diff --git a/core/src/idx/planner/executor.rs b/core/src/idx/planner/executor.rs index 34137b03401..24e576cee6d 100644 --- a/core/src/idx/planner/executor.rs +++ b/core/src/idx/planner/executor.rs @@ -132,7 +132,7 @@ impl InnerQueryExecutor { let ft_entry = match ft_map.entry(ix_ref) { Entry::Occupied(e) => FtEntry::new(stk, ctx, opt, e.get(), io).await?, Entry::Vacant(e) => { - let ikb = IndexKeyBase::new(opt, idx_def); + let ikb = IndexKeyBase::new(opt.ns()?, opt.db()?, idx_def)?; let ft = FtIndex::new( ctx, opt, @@ -174,7 +174,7 @@ impl InnerQueryExecutor { .await? } Entry::Vacant(e) => { - let ikb = IndexKeyBase::new(opt, idx_def); + let ikb = IndexKeyBase::new(opt.ns()?, opt.db()?, idx_def)?; let mut tx = ctx.tx_lock().await; let mt = MTreeIndex::new( ctx.get_index_stores(), @@ -222,7 +222,7 @@ impl InnerQueryExecutor { let hnsw = ctx .get_index_stores() .get_index_hnsw(opt, idx_def, p) - .await; + .await?; let entry = HnswEntry::new( stk, ctx, @@ -346,7 +346,7 @@ impl QueryExecutor { match it_entry { IteratorEntry::Single(_, io) => self.new_single_iterator(opt, irf, io).await, IteratorEntry::Range(_, ixr, from, to) => { - Ok(self.new_range_iterator(opt, *ixr, from, to)) + Ok(self.new_range_iterator(opt, *ixr, from, to)?) } } } else { @@ -386,19 +386,19 @@ impl QueryExecutor { IndexOperator::Equality(value) | IndexOperator::Exactness(value) => { Some(ThingIterator::IndexEqual(IndexEqualThingIterator::new( irf, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, &ix.what, &ix.name, value, ))) } IndexOperator::Union(value) => Some(ThingIterator::IndexUnion( - IndexUnionThingIterator::new(irf, opt.ns(), opt.db(), &ix.what, &ix.name, value), + IndexUnionThingIterator::new(irf, opt.ns()?, opt.db()?, &ix.what, &ix.name, value), )), IndexOperator::Join(ios) => { let iterators = self.build_iterators(opt, irf, ios).await?; - let index_join = Box::new(IndexJoinThingIterator::new(irf, opt, ix, iterators)); + let index_join = Box::new(IndexJoinThingIterator::new(irf, opt, ix, iterators)?); Some(ThingIterator::IndexJoin(index_join)) } _ => None, @@ -411,35 +411,35 @@ impl QueryExecutor { ir: IndexRef, from: &RangeValue, to: &RangeValue, - ) -> Option { + ) -> Result, Error> { if let Some(ix) = self.get_index_def(ir) { match ix.index { Index::Idx => { - return Some(ThingIterator::IndexRange(IndexRangeThingIterator::new( + return Ok(Some(ThingIterator::IndexRange(IndexRangeThingIterator::new( ir, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, &ix.what, &ix.name, from, to, - ))) + )))) } Index::Uniq => { - return Some(ThingIterator::UniqueRange(UniqueRangeThingIterator::new( + return Ok(Some(ThingIterator::UniqueRange(UniqueRangeThingIterator::new( ir, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, &ix.what, &ix.name, from, to, - ))) + )))) } _ => {} } } - None + Ok(None) } async fn new_unique_index_iterator( @@ -453,19 +453,19 @@ impl QueryExecutor { IndexOperator::Equality(value) | IndexOperator::Exactness(value) => { Some(ThingIterator::UniqueEqual(UniqueEqualThingIterator::new( irf, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, &ix.what, &ix.name, value, ))) } - IndexOperator::Union(value) => { - Some(ThingIterator::UniqueUnion(UniqueUnionThingIterator::new(irf, opt, ix, value))) - } + IndexOperator::Union(value) => Some(ThingIterator::UniqueUnion( + UniqueUnionThingIterator::new(irf, opt, ix, value)?, + )), IndexOperator::Join(ios) => { let iterators = self.build_iterators(opt, irf, ios).await?; - let unique_join = Box::new(UniqueJoinThingIterator::new(irf, opt, ix, iterators)); + let unique_join = Box::new(UniqueJoinThingIterator::new(irf, opt, ix, iterators)?); Some(ThingIterator::UniqueJoin(unique_join)) } _ => None, diff --git a/core/src/idx/planner/iterators.rs b/core/src/idx/planner/iterators.rs index bb42228ea4f..8a5a34edba2 100644 --- a/core/src/idx/planner/iterators.rs +++ b/core/src/idx/planner/iterators.rs @@ -404,10 +404,10 @@ impl JoinThingIterator { opt: &Options, ix: &DefineIndexStatement, remote_iterators: VecDeque, - ) -> Self { - Self { - ns: opt.ns().to_string(), - db: opt.db().to_string(), + ) -> Result { + Ok(Self { + ns: opt.ns()?.to_string(), + db: opt.db()?.to_string(), ix_what: ix.what.clone(), ix_name: ix.name.clone(), current_remote: None, @@ -415,7 +415,7 @@ impl JoinThingIterator { remote_iterators, current_local: None, distinct: Default::default(), - } + }) } } @@ -501,8 +501,8 @@ impl IndexJoinThingIterator { opt: &Options, ix: &DefineIndexStatement, remote_iterators: VecDeque, - ) -> Self { - Self(irf, JoinThingIterator::new(opt, ix, remote_iterators)) + ) -> Result { + Ok(Self(irf, JoinThingIterator::new(opt, ix, remote_iterators)?)) } async fn next_batch( @@ -663,20 +663,20 @@ impl UniqueUnionThingIterator { opt: &Options, ix: &DefineIndexStatement, a: &Array, - ) -> Self { + ) -> Result { // We create a VecDeque to hold the key for each value in the array. let keys: VecDeque = a.0.iter() - .map(|v| { + .map(|v| -> Result { let a = Array::from(v.clone()); - let key = Index::new(opt.ns(), opt.db(), &ix.what, &ix.name, &a, None).into(); - key + let key = Index::new(opt.ns()?, opt.db()?, &ix.what, &ix.name, &a, None).into(); + Ok(key) }) - .collect(); - Self { + .collect::, Error>>()?; + Ok(Self { irf, keys, - } + }) } async fn next_batch( @@ -710,8 +710,8 @@ impl UniqueJoinThingIterator { opt: &Options, ix: &DefineIndexStatement, remote_iterators: VecDeque, - ) -> Self { - Self(irf, JoinThingIterator::new(opt, ix, remote_iterators)) + ) -> Result { + Ok(Self(irf, JoinThingIterator::new(opt, ix, remote_iterators)?)) } async fn next_batch( diff --git a/core/src/idx/planner/tree.rs b/core/src/idx/planner/tree.rs index c5a09c5f3ce..3b1b278c762 100644 --- a/core/src/idx/planner/tree.rs +++ b/core/src/idx/planner/tree.rs @@ -545,8 +545,8 @@ struct SchemaCache { impl SchemaCache { async fn new(opt: &Options, table: &Table, tx: &mut kvs::Transaction) -> Result { - let indexes = tx.all_tb_indexes(opt.ns(), opt.db(), table).await?; - let fields = tx.all_tb_fields(opt.ns(), opt.db(), table).await?; + let indexes = tx.all_tb_indexes(opt.ns()?, opt.db()?, table).await?; + let fields = tx.all_tb_fields(opt.ns()?, opt.db()?, table).await?; Ok(Self { indexes, fields, diff --git a/core/src/idx/trees/store/mod.rs b/core/src/idx/trees/store/mod.rs index a81f529532b..f35805450e8 100644 --- a/core/src/idx/trees/store/mod.rs +++ b/core/src/idx/trees/store/mod.rs @@ -283,50 +283,65 @@ impl IndexStores { opt: &Options, ix: &DefineIndexStatement, p: &HnswParams, - ) -> SharedHnswIndex { - let ikb = IndexKeyBase::new(opt, ix); - self.0.hnsw_indexes.get(&ikb, p).await + ) -> Result { + let ikb = IndexKeyBase::new(opt.ns()?, opt.db()?, ix)?; + Ok(self.0.hnsw_indexes.get(&ikb, p).await) } pub(crate) async fn index_removed( &self, - opt: &Options, tx: &mut Transaction, + ns: &str, + db: &str, tb: &str, ix: &str, ) -> Result<(), Error> { - self.remove_index( - opt, - tx.get_and_cache_tb_index(opt.ns(), opt.db(), tb, ix).await?.as_ref(), - ) - .await + self.remove_index(ns, db, tx.get_and_cache_tb_index(ns, db, tb, ix).await?.as_ref()).await } pub(crate) async fn namespace_removed( &self, - opt: &Options, tx: &mut Transaction, + ns: &str, ) -> Result<(), Error> { - for tb in tx.all_tb(opt.ns(), opt.db()).await?.iter() { - self.table_removed(opt, tx, &tb.name).await?; + for db in tx.all_db(ns).await?.iter() { + self.database_removed(tx, ns, &db.name).await?; + } + Ok(()) + } + + pub(crate) async fn database_removed( + &self, + tx: &mut Transaction, + ns: &str, + db: &str, + ) -> Result<(), Error> { + for tb in tx.all_tb(ns, db).await?.iter() { + self.table_removed(tx, ns, db, &tb.name).await?; } Ok(()) } pub(crate) async fn table_removed( &self, - opt: &Options, tx: &mut Transaction, + ns: &str, + db: &str, tb: &str, ) -> Result<(), Error> { - for ix in tx.all_tb_indexes(opt.ns(), opt.db(), tb).await?.iter() { - self.remove_index(opt, ix).await?; + for ix in tx.all_tb_indexes(ns, db, tb).await?.iter() { + self.remove_index(ns, db, ix).await?; } Ok(()) } - async fn remove_index(&self, opt: &Options, ix: &DefineIndexStatement) -> Result<(), Error> { - let ikb = IndexKeyBase::new(opt, ix); + async fn remove_index( + &self, + ns: &str, + db: &str, + ix: &DefineIndexStatement, + ) -> Result<(), Error> { + let ikb = IndexKeyBase::new(ns, db, ix)?; match ix.index { Index::Search(_) => { self.remove_search_caches(ikb); diff --git a/core/src/sql/function.rs b/core/src/sql/function.rs index 0ac83e8a7b3..50ffa2b2e88 100644 --- a/core/src/sql/function.rs +++ b/core/src/sql/function.rs @@ -205,8 +205,6 @@ impl Function { fnc::run(stk, ctx, opt, doc, s, a).await } Self::Custom(s, x) => { - // Check that a database is set to prevent a panic - opt.valid_for_db()?; // Get the full name of this function let name = format!("fn::{s}"); // Check this function is allowed @@ -216,12 +214,12 @@ impl Function { // Claim transaction let mut run = ctx.tx_lock().await; // Get the function definition - let val = run.get_and_cache_db_function(opt.ns(), opt.db(), s).await?; + let val = run.get_and_cache_db_function(opt.ns()?, opt.db()?, s).await?; drop(run); val }; // Check permissions - if opt.check_perms(Action::View) { + if opt.check_perms(Action::View)? { match &val.permissions { Permission::Full => (), Permission::None => { diff --git a/core/src/sql/model.rs b/core/src/sql/model.rs index 3fd86354262..d9d3b92ccff 100644 --- a/core/src/sql/model.rs +++ b/core/src/sql/model.rs @@ -71,21 +71,21 @@ impl Model { let mut run = ctx.tx_lock().await; // Get the function definition let val = - run.get_and_cache_db_model(opt.ns(), opt.db(), &self.name, &self.version).await?; + run.get_and_cache_db_model(opt.ns()?, opt.db()?, &self.name, &self.version).await?; drop(run); val }; // Calculate the model path let path = format!( "ml/{}/{}/{}-{}-{}.surml", - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, self.name, self.version, val.hash ); // Check permissions - if opt.check_perms(Action::View) { + if opt.check_perms(Action::View)? { match &val.permissions { Permission::Full => (), Permission::None => { diff --git a/core/src/sql/param.rs b/core/src/sql/param.rs index 7e5d3210c3d..a3a869959bf 100644 --- a/core/src/sql/param.rs +++ b/core/src/sql/param.rs @@ -69,20 +69,18 @@ impl Param { Some(v) => v.compute(stk, ctx, opt, doc).await, // The param has not been set locally None => { - // Check that a database is set to prevent a panic - opt.valid_for_db()?; let val = { // Claim transaction let mut run = ctx.tx_lock().await; // Get the param definition - run.get_and_cache_db_param(opt.ns(), opt.db(), v).await + run.get_and_cache_db_param(opt.ns()?, opt.db()?, v).await }; // Check if the param has been set globally match val { // The param has been set globally Ok(val) => { // Check permissions - if opt.check_perms(Action::View) { + if opt.check_perms(Action::View)? { match &val.permissions { Permission::Full => (), Permission::None => { diff --git a/core/src/sql/statements/analyze.rs b/core/src/sql/statements/analyze.rs index b6b0a40e2f0..07bacd1c5e0 100644 --- a/core/src/sql/statements/analyze.rs +++ b/core/src/sql/statements/analyze.rs @@ -41,9 +41,9 @@ impl AnalyzeStatement { let ix = ctx .tx_lock() .await - .get_and_cache_tb_index(opt.ns(), opt.db(), tb.as_str(), idx.as_str()) + .get_and_cache_tb_index(opt.ns()?, opt.db()?, tb, idx) .await?; - let ikb = IndexKeyBase::new(opt, &ix); + let ikb = IndexKeyBase::new(opt.ns()?, opt.db()?, &ix)?; // Index operation dispatching let value: Value = match &ix.index { diff --git a/core/src/sql/statements/define/access.rs b/core/src/sql/statements/define/access.rs index 25f4796c9ca..ba1ee45d49a 100644 --- a/core/src/sql/statements/define/access.rs +++ b/core/src/sql/statements/define/access.rs @@ -66,7 +66,7 @@ impl DefineAccessStatement { // Clear the cache run.clear_cache(); // Check if access method already exists - if run.get_ns_access(opt.ns(), &self.name).await.is_ok() { + if run.get_ns_access(opt.ns()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -76,8 +76,8 @@ impl DefineAccessStatement { } } // Process the statement - let key = crate::key::namespace::ac::new(opt.ns(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; + let key = crate::key::namespace::ac::new(opt.ns()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; run.set( key, DefineAccessStatement { @@ -95,7 +95,7 @@ impl DefineAccessStatement { // Clear the cache run.clear_cache(); // Check if access method already exists - if run.get_db_access(opt.ns(), opt.db(), &self.name).await.is_ok() { + if run.get_db_access(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -105,9 +105,9 @@ impl DefineAccessStatement { } } // Process the statement - let key = crate::key::database::ac::new(opt.ns(), opt.db(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::ac::new(opt.ns()?, opt.db()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; run.set( key, DefineAccessStatement { diff --git a/core/src/sql/statements/define/analyzer.rs b/core/src/sql/statements/define/analyzer.rs index 865eea6c716..51ff7f35649 100644 --- a/core/src/sql/statements/define/analyzer.rs +++ b/core/src/sql/statements/define/analyzer.rs @@ -39,7 +39,7 @@ impl DefineAnalyzerStatement { // Clear the cache run.clear_cache(); // Check if analyzer already exists - if run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await.is_ok() { + if run.get_db_analyzer(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -49,9 +49,9 @@ impl DefineAnalyzerStatement { } } // Process the statement - let key = crate::key::database::az::new(opt.ns(), opt.db(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::az::new(opt.ns()?, opt.db()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; // Persist the definition run.set( key, diff --git a/core/src/sql/statements/define/database.rs b/core/src/sql/statements/define/database.rs index 2a19a3944a3..eedf9b2eea6 100644 --- a/core/src/sql/statements/define/database.rs +++ b/core/src/sql/statements/define/database.rs @@ -38,7 +38,7 @@ impl DefineDatabaseStatement { // Clear the cache run.clear_cache(); // Check if database already exists - if run.get_db(opt.ns(), &self.name).await.is_ok() { + if run.get_db(opt.ns()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -48,8 +48,8 @@ impl DefineDatabaseStatement { } } // Process the statement - let key = crate::key::namespace::db::new(opt.ns(), &self.name); - let ns = run.add_ns(opt.ns(), opt.strict).await?; + let key = crate::key::namespace::db::new(opt.ns()?, &self.name); + let ns = run.add_ns(opt.ns()?, opt.strict).await?; // Set the id if self.id.is_none() && ns.id.is_some() { // Set the id diff --git a/core/src/sql/statements/define/event.rs b/core/src/sql/statements/define/event.rs index f7b0460067f..99fd2ab7ec6 100644 --- a/core/src/sql/statements/define/event.rs +++ b/core/src/sql/statements/define/event.rs @@ -39,7 +39,7 @@ impl DefineEventStatement { // Clear the cache run.clear_cache(); // Check if event already exists - if run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok() { + 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 { @@ -49,10 +49,10 @@ impl DefineEventStatement { } } // Process the statement - let key = crate::key::table::ev::new(opt.ns(), opt.db(), &self.what, &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; - run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?; + let key = crate::key::table::ev::new(opt.ns()?, opt.db()?, &self.what, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; + run.add_tb(opt.ns()?, opt.db()?, &self.what, opt.strict).await?; run.set( key, DefineEventStatement { @@ -62,7 +62,7 @@ impl DefineEventStatement { ) .await?; // Clear the cache - let key = crate::key::table::ev::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::ev::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/define/field.rs b/core/src/sql/statements/define/field.rs index f0090081cee..1d620aabf8c 100644 --- a/core/src/sql/statements/define/field.rs +++ b/core/src/sql/statements/define/field.rs @@ -51,7 +51,7 @@ impl DefineFieldStatement { run.clear_cache(); // Check if field already exists let fd = self.name.to_string(); - if run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd).await.is_ok() { + 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 { @@ -61,11 +61,11 @@ impl DefineFieldStatement { } } // Process the statement - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; - let tb = run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?; - let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd); + let tb = run.add_tb(opt.ns()?, opt.db()?, &self.what, opt.strict).await?; + let key = crate::key::table::fd::new(opt.ns()?, opt.db()?, &self.what, &fd); run.set( key, DefineFieldStatement { @@ -76,7 +76,7 @@ impl DefineFieldStatement { .await?; // find existing field definitions. - let fields = run.all_tb_fields(opt.ns(), opt.db(), &self.what).await.ok(); + let fields = run.all_tb_fields(opt.ns()?, opt.db()?, &self.what).await.ok(); // Process possible recursive_definitions. if let Some(mut cur_kind) = self.kind.as_ref().and_then(|x| x.inner_kind()) { @@ -86,9 +86,9 @@ impl DefineFieldStatement { name.0.push(Part::All); let fd = name.to_string(); - let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::table::fd::new(opt.ns()?, opt.db()?, &self.what, &fd); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; // merge the new definition with possible existing definitions. let statement = if let Some(existing) = @@ -155,14 +155,14 @@ impl DefineFieldStatement { _ => None, }; if let Some(tb) = new_tb { - let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.what); + let key = crate::key::database::tb::new(opt.ns()?, opt.db()?, &self.what); run.set(key, &tb).await?; - let key = crate::key::table::ft::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::ft::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; } // Clear the cache - let key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::fd::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/define/function.rs b/core/src/sql/statements/define/function.rs index 39c604ca172..234ba3e8102 100644 --- a/core/src/sql/statements/define/function.rs +++ b/core/src/sql/statements/define/function.rs @@ -42,7 +42,7 @@ impl DefineFunctionStatement { // Clear the cache run.clear_cache(); // Check if function already exists - if run.get_db_function(opt.ns(), opt.db(), &self.name).await.is_ok() { + if run.get_db_function(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -52,9 +52,9 @@ impl DefineFunctionStatement { } } // Process the statement - let key = crate::key::database::fc::new(opt.ns(), opt.db(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::fc::new(opt.ns()?, opt.db()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; run.set( key, DefineFunctionStatement { diff --git a/core/src/sql/statements/define/index.rs b/core/src/sql/statements/define/index.rs index fa204afb3e8..a59700f5057 100644 --- a/core/src/sql/statements/define/index.rs +++ b/core/src/sql/statements/define/index.rs @@ -44,7 +44,7 @@ impl DefineIndexStatement { // Clear the cache run.clear_cache(); // Check if index already exists - if run.get_tb_index(opt.ns(), opt.db(), &self.what, &self.name).await.is_ok() { + 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 { @@ -54,16 +54,16 @@ impl DefineIndexStatement { } } // If we are strict, check that the table exists - run.check_ns_db_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?; + run.check_ns_db_tb(opt.ns()?, opt.db()?, &self.what, opt.strict).await?; // Does the table exists? - match run.get_and_cache_tb(opt.ns(), opt.db(), &self.what).await { + match run.get_and_cache_tb(opt.ns()?, opt.db()?, &self.what).await { Ok(db) => { // Are we SchemaFull? if db.full { // Check that the fields exists for idiom in self.cols.iter() { if let Some(Part::Field(id)) = idiom.first() { - run.get_tb_field(opt.ns(), opt.db(), &self.what, id).await?; + run.get_tb_field(opt.ns()?, opt.db()?, &self.what, id).await?; } } } @@ -77,10 +77,10 @@ impl DefineIndexStatement { } // 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?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; - run.add_tb(opt.ns(), opt.db(), &self.what, opt.strict).await?; + let key = crate::key::table::ix::new(opt.ns()?, opt.db()?, &self.what, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; + run.add_tb(opt.ns()?, opt.db()?, &self.what, opt.strict).await?; run.set( key, DefineIndexStatement { @@ -91,10 +91,10 @@ impl DefineIndexStatement { ) .await?; // Remove the index data - let key = crate::key::index::all::new(opt.ns(), opt.db(), &self.what, &self.name); + let key = crate::key::index::all::new(opt.ns()?, opt.db()?, &self.what, &self.name); run.delp(key, u32::MAX).await?; // Clear the cache - let key = crate::key::table::ix::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::ix::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; // Release the transaction drop(run); diff --git a/core/src/sql/statements/define/model.rs b/core/src/sql/statements/define/model.rs index a110cb2e88a..82181f25c87 100644 --- a/core/src/sql/statements/define/model.rs +++ b/core/src/sql/statements/define/model.rs @@ -63,7 +63,7 @@ impl DefineModelStatement { // Clear the cache run.clear_cache(); // Check if model already exists - if run.get_db_model(opt.ns(), opt.db(), &self.name, &self.version).await.is_ok() { + 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 { @@ -73,9 +73,9 @@ impl DefineModelStatement { } } // Process the statement - let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::ml::new(opt.ns()?, opt.db()?, &self.name, &self.version); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; run.set( key, DefineModelStatement { diff --git a/core/src/sql/statements/define/param.rs b/core/src/sql/statements/define/param.rs index 3c1cb27af2e..129ea7b9681 100644 --- a/core/src/sql/statements/define/param.rs +++ b/core/src/sql/statements/define/param.rs @@ -41,7 +41,7 @@ impl DefineParamStatement { // Clear the cache run.clear_cache(); // Check if param already exists - if run.get_db_param(opt.ns(), opt.db(), &self.name).await.is_ok() { + if run.get_db_param(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -51,9 +51,9 @@ impl DefineParamStatement { } } // Process the statement - let key = crate::key::database::pa::new(opt.ns(), opt.db(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::pa::new(opt.ns()?, opt.db()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; run.set( key, DefineParamStatement { diff --git a/core/src/sql/statements/define/table.rs b/core/src/sql/statements/define/table.rs index f8980761e92..07d917932c9 100644 --- a/core/src/sql/statements/define/table.rs +++ b/core/src/sql/statements/define/table.rs @@ -55,7 +55,7 @@ impl DefineTableStatement { // Clear the cache run.clear_cache(); // Check if table already exists - if run.get_tb(opt.ns(), opt.db(), &self.name).await.is_ok() { + if run.get_tb(opt.ns()?, opt.db()?, &self.name).await.is_ok() { if self.if_not_exists { return Ok(Value::None); } else { @@ -65,9 +65,9 @@ impl DefineTableStatement { } } // Process the statement - let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name); - let ns = run.add_ns(opt.ns(), opt.strict).await?; - let db = run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::tb::new(opt.ns()?, opt.db()?, &self.name); + let ns = run.add_ns(opt.ns()?, opt.strict).await?; + let db = run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; let dt = if self.id.is_none() && ns.id.is_some() && db.id.is_some() { DefineTableStatement { id: Some(run.get_next_tb_id(ns.id.unwrap(), db.id.unwrap()).await?), @@ -84,8 +84,8 @@ impl DefineTableStatement { let tb: &str = &self.name; let in_kind = rel.from.clone().unwrap_or(Kind::Record(vec![])); let out_kind = rel.to.clone().unwrap_or(Kind::Record(vec![])); - let in_key = crate::key::table::fd::new(opt.ns(), opt.db(), tb, "in"); - let out_key = crate::key::table::fd::new(opt.ns(), opt.db(), tb, "out"); + let in_key = crate::key::table::fd::new(opt.ns()?, opt.db()?, tb, "in"); + let out_key = crate::key::table::fd::new(opt.ns()?, opt.db()?, tb, "out"); run.set( in_key, DefineFieldStatement { @@ -108,21 +108,21 @@ impl DefineTableStatement { .await?; } - let tb_key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.name); + let tb_key = crate::key::table::fd::prefix(opt.ns()?, opt.db()?, &self.name); run.clr(tb_key).await?; run.set(key, &dt).await?; // Check if table is a view if let Some(view) = &self.view { // Remove the table data - let key = crate::key::table::all::new(opt.ns(), opt.db(), &self.name); + let key = crate::key::table::all::new(opt.ns()?, opt.db()?, &self.name); run.delp(key, u32::MAX).await?; // Process each foreign table for v in view.what.0.iter() { // Save the view config - let key = crate::key::table::ft::new(opt.ns(), opt.db(), v, &self.name); + let key = crate::key::table::ft::new(opt.ns()?, opt.db()?, v, &self.name); run.set(key, self).await?; // Clear the cache - let key = crate::key::table::ft::prefix(opt.ns(), opt.db(), v); + let key = crate::key::table::ft::prefix(opt.ns()?, opt.db()?, v); run.clr(key).await?; } // Release the transaction @@ -139,7 +139,7 @@ impl DefineTableStatement { stm.compute(stk, ctx, opt, doc).await?; } } else if dt.changefeed.is_some() { - run.record_table_change(opt.ns(), opt.db(), self.name.0.as_str(), &dt); + run.record_table_change(opt.ns()?, opt.db()?, self.name.0.as_str(), &dt); } // Ok all good diff --git a/core/src/sql/statements/define/user.rs b/core/src/sql/statements/define/user.rs index e690faac6c7..4fddc5f18f4 100644 --- a/core/src/sql/statements/define/user.rs +++ b/core/src/sql/statements/define/user.rs @@ -142,19 +142,19 @@ impl DefineUserStatement { // Clear the cache run.clear_cache(); // Check if user already exists - if run.get_ns_user(opt.ns(), &self.name).await.is_ok() { + 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(), + ns: opt.ns()?.into(), }); } } // Process the statement - let key = crate::key::namespace::us::new(opt.ns(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; + let key = crate::key::namespace::us::new(opt.ns()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; run.set( key, DefineUserStatement { @@ -173,21 +173,21 @@ impl DefineUserStatement { // Clear the cache run.clear_cache(); // Check if user already exists - if run.get_db_user(opt.ns(), opt.db(), &self.name).await.is_ok() { + 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(), + ns: opt.ns()?.into(), + db: opt.db()?.into(), }); } } // Process the statement - let key = crate::key::database::us::new(opt.ns(), opt.db(), &self.name); - run.add_ns(opt.ns(), opt.strict).await?; - run.add_db(opt.ns(), opt.db(), opt.strict).await?; + let key = crate::key::database::us::new(opt.ns()?, opt.db()?, &self.name); + run.add_ns(opt.ns()?, opt.strict).await?; + run.add_db(opt.ns()?, opt.db()?, opt.strict).await?; run.set( key, DefineUserStatement { diff --git a/core/src/sql/statements/info.rs b/core/src/sql/statements/info.rs index 1e5ddc8ec3c..591c6581fda 100644 --- a/core/src/sql/statements/info.rs +++ b/core/src/sql/statements/info.rs @@ -103,19 +103,19 @@ impl InfoStatement { let mut res = Object::default(); // Process the databases let mut tmp = Object::default(); - for v in run.all_db(opt.ns()).await?.iter() { + for v in run.all_db(opt.ns()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("databases".to_owned(), tmp.into()); // Process the users let mut tmp = Object::default(); - for v in run.all_ns_users(opt.ns()).await?.iter() { + for v in run.all_ns_users(opt.ns()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("users".to_owned(), tmp.into()); // Process the accesses let mut tmp = Object::default(); - for v in run.all_ns_accesses_redacted(opt.ns()).await?.iter() { + for v in run.all_ns_accesses_redacted(opt.ns()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("accesses".to_owned(), tmp.into()); @@ -131,43 +131,43 @@ impl InfoStatement { let mut res = Object::default(); // Process the users let mut tmp = Object::default(); - for v in run.all_db_users(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_users(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("users".to_owned(), tmp.into()); // Process the functions let mut tmp = Object::default(); - for v in run.all_db_functions(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_functions(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("functions".to_owned(), tmp.into()); // Process the models let mut tmp = Object::default(); - for v in run.all_db_models(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_models(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(format!("{}<{}>", v.name, v.version), v.to_string().into()); } res.insert("models".to_owned(), tmp.into()); // Process the params let mut tmp = Object::default(); - for v in run.all_db_params(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_params(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("params".to_owned(), tmp.into()); // Process the accesses let mut tmp = Object::default(); - for v in run.all_db_accesses_redacted(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_accesses_redacted(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("accesses".to_owned(), tmp.into()); // Process the tables let mut tmp = Object::default(); - for v in run.all_tb(opt.ns(), opt.db()).await?.iter() { + for v in run.all_tb(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tables".to_owned(), tmp.into()); // Process the analyzers let mut tmp = Object::default(); - for v in run.all_db_analyzers(opt.ns(), opt.db()).await?.iter() { + for v in run.all_db_analyzers(opt.ns()?, opt.db()?).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("analyzers".to_owned(), tmp.into()); @@ -183,31 +183,31 @@ impl InfoStatement { let mut res = Object::default(); // Process the events let mut tmp = Object::default(); - for v in run.all_tb_events(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_events(opt.ns()?, opt.db()?, tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("events".to_owned(), tmp.into()); // Process the fields let mut tmp = Object::default(); - for v in run.all_tb_fields(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_fields(opt.ns()?, opt.db()?, tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("fields".to_owned(), tmp.into()); // Process the tables let mut tmp = Object::default(); - for v in run.all_tb_views(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_views(opt.ns()?, opt.db()?, tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("tables".to_owned(), tmp.into()); // Process the indexes let mut tmp = Object::default(); - for v in run.all_tb_indexes(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_indexes(opt.ns()?, opt.db()?, tb).await?.iter() { tmp.insert(v.name.to_string(), v.to_string().into()); } res.insert("indexes".to_owned(), tmp.into()); // Process the live queries let mut tmp = Object::default(); - for v in run.all_tb_lives(opt.ns(), opt.db(), tb).await?.iter() { + for v in run.all_tb_lives(opt.ns()?, opt.db()?, tb).await?.iter() { tmp.insert(v.id.to_raw(), v.to_string().into()); } res.insert("lives".to_owned(), tmp.into()); @@ -224,8 +224,8 @@ impl InfoStatement { // Process the user let res = match base { Base::Root => run.get_root_user(user).await?, - Base::Ns => run.get_ns_user(opt.ns(), user).await?, - Base::Db => run.get_db_user(opt.ns(), opt.db(), user).await?, + Base::Ns => run.get_ns_user(opt.ns()?, user).await?, + Base::Db => run.get_db_user(opt.ns()?, opt.db()?, user).await?, _ => return Err(Error::InvalidLevel(base.to_string())), }; // Ok all good @@ -253,13 +253,13 @@ impl InfoStatement { // Create the result set let mut res = Object::default(); // Process the databases - res.insert("databases".to_owned(), process_arr(run.all_db(opt.ns()).await?)); + res.insert("databases".to_owned(), process_arr(run.all_db(opt.ns()?).await?)); // Process the users - res.insert("users".to_owned(), process_arr(run.all_ns_users(opt.ns()).await?)); + res.insert("users".to_owned(), process_arr(run.all_ns_users(opt.ns()?).await?)); // Process the accesses res.insert( "accesses".to_owned(), - process_arr(run.all_ns_accesses_redacted(opt.ns()).await?), + process_arr(run.all_ns_accesses_redacted(opt.ns()?).await?), ); // Ok all good Value::from(res).ok() @@ -274,39 +274,42 @@ impl InfoStatement { // Process the users res.insert( "users".to_owned(), - process_arr(run.all_db_users(opt.ns(), opt.db()).await?), + process_arr(run.all_db_users(opt.ns()?, opt.db()?).await?), ); // Process the accesses res.insert( "accesses".to_owned(), - process_arr(run.all_db_accesses(opt.ns(), opt.db()).await?), + process_arr(run.all_db_accesses(opt.ns()?, opt.db()?).await?), ); // Process the functions res.insert( "functions".to_owned(), - process_arr(run.all_db_functions(opt.ns(), opt.db()).await?), + process_arr(run.all_db_functions(opt.ns()?, opt.db()?).await?), ); // Process the models res.insert( "models".to_owned(), - process_arr(run.all_db_models(opt.ns(), opt.db()).await?), + process_arr(run.all_db_models(opt.ns()?, opt.db()?).await?), ); // Process the params res.insert( "params".to_owned(), - process_arr(run.all_db_params(opt.ns(), opt.db()).await?), + process_arr(run.all_db_params(opt.ns()?, opt.db()?).await?), ); // Process the accesses res.insert( "accesses".to_owned(), - process_arr(run.all_db_accesses_redacted(opt.ns(), opt.db()).await?), + process_arr(run.all_db_accesses_redacted(opt.ns()?, opt.db()?).await?), ); // Process the tables - res.insert("tables".to_owned(), process_arr(run.all_tb(opt.ns(), opt.db()).await?)); + res.insert( + "tables".to_owned(), + process_arr(run.all_tb(opt.ns()?, opt.db()?).await?), + ); // Process the analyzers res.insert( "analyzers".to_owned(), - process_arr(run.all_db_analyzers(opt.ns(), opt.db()).await?), + process_arr(run.all_db_analyzers(opt.ns()?, opt.db()?).await?), ); // Ok all good Value::from(res).ok() @@ -321,27 +324,27 @@ impl InfoStatement { // Process the events res.insert( "events".to_owned(), - process_arr(run.all_tb_events(opt.ns(), opt.db(), tb).await?), + process_arr(run.all_tb_events(opt.ns()?, opt.db()?, tb).await?), ); // Process the fields res.insert( "fields".to_owned(), - process_arr(run.all_tb_fields(opt.ns(), opt.db(), tb).await?), + process_arr(run.all_tb_fields(opt.ns()?, opt.db()?, tb).await?), ); // Process the tables res.insert( "tables".to_owned(), - process_arr(run.all_tb_views(opt.ns(), opt.db(), tb).await?), + process_arr(run.all_tb_views(opt.ns()?, opt.db()?, tb).await?), ); // Process the indexes res.insert( "indexes".to_owned(), - process_arr(run.all_tb_indexes(opt.ns(), opt.db(), tb).await?), + process_arr(run.all_tb_indexes(opt.ns()?, opt.db()?, tb).await?), ); // Process the live queries res.insert( "lives".to_owned(), - process_arr(run.all_tb_lives(opt.ns(), opt.db(), tb).await?), + process_arr(run.all_tb_lives(opt.ns()?, opt.db()?, tb).await?), ); // Ok all good Value::from(res).ok() @@ -356,8 +359,8 @@ impl InfoStatement { // Process the user let res = match base { Base::Root => run.get_root_user(user).await?, - Base::Ns => run.get_ns_user(opt.ns(), user).await?, - Base::Db => run.get_db_user(opt.ns(), opt.db(), user).await?, + Base::Ns => run.get_ns_user(opt.ns()?, user).await?, + Base::Db => run.get_db_user(opt.ns()?, opt.db()?, user).await?, _ => return Err(Error::InvalidLevel(base.to_string())), }; // Ok all good diff --git a/core/src/sql/statements/kill.rs b/core/src/sql/statements/kill.rs index 89ac63ea49a..d0972d0b5c6 100644 --- a/core/src/sql/statements/kill.rs +++ b/core/src/sql/statements/kill.rs @@ -78,12 +78,12 @@ impl KillStatement { if FFLAGS.change_feed_live_queries.enabled() { run.pre_commit_register_async_event(TrackedResult::KillQuery(KillEntry { live_id: live_query_id, - ns: opt.ns().to_string(), - db: opt.db().to_string(), + ns: opt.ns()?.to_string(), + db: opt.db()?.to_string(), }))?; } else { // Fetch the live query key - let key = crate::key::node::lq::new(opt.id()?, live_query_id.0, opt.ns(), opt.db()); + let key = crate::key::node::lq::new(opt.id()?, live_query_id.0, opt.ns()?, opt.db()?); // Fetch the live query key if it exists match run.get(key).await? { Some(val) => match std::str::from_utf8(&val) { @@ -92,13 +92,13 @@ impl KillStatement { let key = crate::key::node::lq::new( opt.id()?, live_query_id.0, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, ); run.del(key).await?; // Delete the table live query let key = - crate::key::table::lq::new(opt.ns(), opt.db(), tb, live_query_id.0); + crate::key::table::lq::new(opt.ns()?, opt.db()?, tb, live_query_id.0); run.del(key).await?; } _ => { diff --git a/core/src/sql/statements/live.rs b/core/src/sql/statements/live.rs index 02e90625b21..cf9a1666e6b 100644 --- a/core/src/sql/statements/live.rs +++ b/core/src/sql/statements/live.rs @@ -112,8 +112,8 @@ impl LiveStatement { let mut stm = stm; stm.what = Value::Table(tb.clone()); - let ns = opt.ns().to_string(); - let db = opt.db().to_string(); + let ns = opt.ns()?.to_string(); + let db = opt.db()?.to_string(); self.validate_change_feed_valid(&mut run, &ns, &db, &tb).await?; // Send the live query registration hook to the transaction pre-commit channel run.pre_commit_register_async_event(TrackedResult::LiveQuery(LqEntry { @@ -140,9 +140,9 @@ impl LiveStatement { // Store the current Node ID stm.node = nid.into(); // Insert the node live query - run.putc_ndlq(nid, id, opt.ns(), opt.db(), tb.as_str(), None).await?; + run.putc_ndlq(nid, id, opt.ns()?, opt.db()?, tb.as_str(), None).await?; // Insert the table live query - run.putc_tblq(opt.ns(), opt.db(), &tb, stm, None).await?; + run.putc_tblq(opt.ns()?, opt.db()?, &tb, stm, None).await?; } v => { return Err(Error::LiveStatement { diff --git a/core/src/sql/statements/rebuild.rs b/core/src/sql/statements/rebuild.rs index 4a36d4407e7..146c56f8aae 100644 --- a/core/src/sql/statements/rebuild.rs +++ b/core/src/sql/statements/rebuild.rs @@ -76,7 +76,12 @@ impl RebuildIndexStatement { let ix = ctx .tx_lock() .await - .get_and_cache_tb_index(opt.ns(), opt.db(), self.what.as_str(), self.name.as_str()) + .get_and_cache_tb_index( + opt.ns()?, + opt.db()?, + self.what.as_str(), + self.name.as_str(), + ) .await?; // Remove the index diff --git a/core/src/sql/statements/remove/access.rs b/core/src/sql/statements/remove/access.rs index 6eb04149c92..318f9cdc171 100644 --- a/core/src/sql/statements/remove/access.rs +++ b/core/src/sql/statements/remove/access.rs @@ -33,9 +33,9 @@ impl RemoveAccessStatement { // Clear the cache run.clear_cache(); // Get the definition - let ac = run.get_ns_access(opt.ns(), &self.name).await?; + let ac = run.get_ns_access(opt.ns()?, &self.name).await?; // Delete the definition - let key = crate::key::namespace::ac::new(opt.ns(), &ac.name); + let key = crate::key::namespace::ac::new(opt.ns()?, &ac.name); run.del(key).await?; // Ok all good Ok(Value::None) @@ -46,9 +46,9 @@ impl RemoveAccessStatement { // Clear the cache run.clear_cache(); // Get the definition - let ac = run.get_db_access(opt.ns(), opt.db(), &self.name).await?; + let ac = run.get_db_access(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::ac::new(opt.ns(), opt.db(), &ac.name); + let key = crate::key::database::ac::new(opt.ns()?, opt.db()?, &ac.name); run.del(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/analyzer.rs b/core/src/sql/statements/remove/analyzer.rs index d0339132396..02540386d91 100644 --- a/core/src/sql/statements/remove/analyzer.rs +++ b/core/src/sql/statements/remove/analyzer.rs @@ -28,9 +28,9 @@ impl RemoveAnalyzerStatement { // Clear the cache run.clear_cache(); // Get the definition - let az = run.get_db_analyzer(opt.ns(), opt.db(), &self.name).await?; + let az = run.get_db_analyzer(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::az::new(opt.ns(), opt.db(), &az.name); + let key = crate::key::database::az::new(opt.ns()?, opt.db()?, &az.name); run.del(key).await?; // TODO Check that the analyzer is not used in any schema // Ok all good diff --git a/core/src/sql/statements/remove/database.rs b/core/src/sql/statements/remove/database.rs index 9b6d36d16e3..ee76f5ff323 100644 --- a/core/src/sql/statements/remove/database.rs +++ b/core/src/sql/statements/remove/database.rs @@ -26,15 +26,17 @@ impl RemoveDatabaseStatement { opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?; // Claim transaction let mut run = ctx.tx_lock().await; + // Remove index store + ctx.get_index_stores().database_removed(&mut run, opt.ns()?, &self.name).await?; // Clear the cache run.clear_cache(); // Get the definition - let db = run.get_db(opt.ns(), &self.name).await?; + let db = run.get_db(opt.ns()?, &self.name).await?; // Delete the definition - let key = crate::key::namespace::db::new(opt.ns(), &db.name); + let key = crate::key::namespace::db::new(opt.ns()?, &db.name); run.del(key).await?; // Delete the resource data - let key = crate::key::database::all::new(opt.ns(), &db.name); + let key = crate::key::database::all::new(opt.ns()?, &db.name); run.delp(key, u32::MAX).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/event.rs b/core/src/sql/statements/remove/event.rs index bacb60a6ef5..9fe1258b252 100644 --- a/core/src/sql/statements/remove/event.rs +++ b/core/src/sql/statements/remove/event.rs @@ -30,12 +30,12 @@ impl RemoveEventStatement { // Clear the cache run.clear_cache(); // Get the definition - let ev = run.get_tb_event(opt.ns(), opt.db(), &self.what, &self.name).await?; + let ev = run.get_tb_event(opt.ns()?, opt.db()?, &self.what, &self.name).await?; // Delete the definition - let key = crate::key::table::ev::new(opt.ns(), opt.db(), &ev.what, &ev.name); + let key = crate::key::table::ev::new(opt.ns()?, opt.db()?, &ev.what, &ev.name); run.del(key).await?; // Clear the cache - let key = crate::key::table::ev::prefix(opt.ns(), opt.db(), &ev.what); + let key = crate::key::table::ev::prefix(opt.ns()?, opt.db()?, &ev.what); run.clr(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/field.rs b/core/src/sql/statements/remove/field.rs index 2536b36a62f..476f3c8e1e4 100644 --- a/core/src/sql/statements/remove/field.rs +++ b/core/src/sql/statements/remove/field.rs @@ -31,13 +31,13 @@ impl RemoveFieldStatement { run.clear_cache(); // Get the definition let fd_name = self.name.to_string(); - let fd = run.get_tb_field(opt.ns(), opt.db(), &self.what, &fd_name).await?; + let fd = run.get_tb_field(opt.ns()?, opt.db()?, &self.what, &fd_name).await?; // Delete the definition let fd_name = fd.name.to_string(); - let key = crate::key::table::fd::new(opt.ns(), opt.db(), &self.what, &fd_name); + let key = crate::key::table::fd::new(opt.ns()?, opt.db()?, &self.what, &fd_name); run.del(key).await?; // Clear the cache - let key = crate::key::table::fd::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::fd::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/function.rs b/core/src/sql/statements/remove/function.rs index 404c1fc6189..57b3e383983 100644 --- a/core/src/sql/statements/remove/function.rs +++ b/core/src/sql/statements/remove/function.rs @@ -29,9 +29,9 @@ impl RemoveFunctionStatement { // Clear the cache run.clear_cache(); // Get the definition - let fc = run.get_db_function(opt.ns(), opt.db(), &self.name).await?; + let fc = run.get_db_function(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::fc::new(opt.ns(), opt.db(), &fc.name); + let key = crate::key::database::fc::new(opt.ns()?, opt.db()?, &fc.name); run.del(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/index.rs b/core/src/sql/statements/remove/index.rs index cd36bbeb44f..56e9731d785 100644 --- a/core/src/sql/statements/remove/index.rs +++ b/core/src/sql/statements/remove/index.rs @@ -28,17 +28,19 @@ impl RemoveIndexStatement { // Claim transaction let mut run = ctx.tx_lock().await; // Clear the index store cache - ctx.get_index_stores().index_removed(opt, &mut run, &self.what, &self.name).await?; + ctx.get_index_stores() + .index_removed(&mut run, opt.ns()?, opt.db()?, &self.what, &self.name) + .await?; // Clear the cache run.clear_cache(); // Delete the definition - let key = crate::key::table::ix::new(opt.ns(), opt.db(), &self.what, &self.name); + let key = crate::key::table::ix::new(opt.ns()?, opt.db()?, &self.what, &self.name); run.del(key).await?; // Remove the index data - let key = crate::key::index::all::new(opt.ns(), opt.db(), &self.what, &self.name); + let key = crate::key::index::all::new(opt.ns()?, opt.db()?, &self.what, &self.name); run.delp(key, u32::MAX).await?; // Clear the cache - let key = crate::key::table::ix::prefix(opt.ns(), opt.db(), &self.what); + let key = crate::key::table::ix::prefix(opt.ns()?, opt.db()?, &self.what); run.clr(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/model.rs b/core/src/sql/statements/remove/model.rs index c3f98874921..3e54389d6d8 100644 --- a/core/src/sql/statements/remove/model.rs +++ b/core/src/sql/statements/remove/model.rs @@ -30,7 +30,8 @@ impl RemoveModelStatement { // Clear the cache run.clear_cache(); // Delete the definition - let key = crate::key::database::ml::new(opt.ns(), opt.db(), &self.name, &self.version); + let key = + crate::key::database::ml::new(opt.ns()?, opt.db()?, &self.name, &self.version); run.del(key).await?; // Remove the model file // TODO diff --git a/core/src/sql/statements/remove/namespace.rs b/core/src/sql/statements/remove/namespace.rs index 759a4bac3c3..8450ba043f9 100644 --- a/core/src/sql/statements/remove/namespace.rs +++ b/core/src/sql/statements/remove/namespace.rs @@ -26,7 +26,8 @@ impl RemoveNamespaceStatement { opt.is_allowed(Action::Edit, ResourceKind::Namespace, &Base::Root)?; // Claim transaction let mut run = ctx.tx_lock().await; - ctx.get_index_stores().namespace_removed(opt, &mut run).await?; + // Delete index stores instance + ctx.get_index_stores().namespace_removed(&mut run, &self.name).await?; // Clear the cache run.clear_cache(); // Get the definition diff --git a/core/src/sql/statements/remove/param.rs b/core/src/sql/statements/remove/param.rs index fef8d0d09ca..98228a05f0d 100644 --- a/core/src/sql/statements/remove/param.rs +++ b/core/src/sql/statements/remove/param.rs @@ -29,9 +29,9 @@ impl RemoveParamStatement { // Clear the cache run.clear_cache(); // Get the definition - let pa = run.get_db_param(opt.ns(), opt.db(), &self.name).await?; + let pa = run.get_db_param(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::pa::new(opt.ns(), opt.db(), &pa.name); + let key = crate::key::database::pa::new(opt.ns()?, opt.db()?, &pa.name); run.del(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/remove/table.rs b/core/src/sql/statements/remove/table.rs index 1620aee368f..3e85050c232 100644 --- a/core/src/sql/statements/remove/table.rs +++ b/core/src/sql/statements/remove/table.rs @@ -27,23 +27,25 @@ impl RemoveTableStatement { // Claim transaction let mut run = ctx.tx_lock().await; // Remove the index stores - ctx.get_index_stores().table_removed(opt, &mut run, &self.name).await?; + ctx.get_index_stores() + .table_removed(&mut run, opt.ns()?, opt.db()?, &self.name) + .await?; // Clear the cache run.clear_cache(); // Get the defined table - let tb = run.get_tb(opt.ns(), opt.db(), &self.name).await?; + let tb = run.get_tb(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name); + let key = crate::key::database::tb::new(opt.ns()?, opt.db()?, &self.name); run.del(key).await?; // Remove the resource data - let key = crate::key::table::all::new(opt.ns(), opt.db(), &self.name); + let key = crate::key::table::all::new(opt.ns()?, opt.db()?, &self.name); run.delp(key, u32::MAX).await?; // Check if this is a foreign table if let Some(view) = &tb.view { // Process each foreign table for v in view.what.0.iter() { // Save the view config - let key = crate::key::table::ft::new(opt.ns(), opt.db(), v, &self.name); + let key = crate::key::table::ft::new(opt.ns()?, opt.db()?, v, &self.name); run.del(key).await?; } } diff --git a/core/src/sql/statements/remove/user.rs b/core/src/sql/statements/remove/user.rs index 75d2504246b..4d4d995fb5a 100644 --- a/core/src/sql/statements/remove/user.rs +++ b/core/src/sql/statements/remove/user.rs @@ -46,9 +46,9 @@ impl RemoveUserStatement { // Clear the cache run.clear_cache(); // Get the definition - let us = run.get_ns_user(opt.ns(), &self.name).await?; + let us = run.get_ns_user(opt.ns()?, &self.name).await?; // Delete the definition - let key = crate::key::namespace::us::new(opt.ns(), &us.name); + let key = crate::key::namespace::us::new(opt.ns()?, &us.name); run.del(key).await?; // Ok all good Ok(Value::None) @@ -59,9 +59,9 @@ impl RemoveUserStatement { // Clear the cache run.clear_cache(); // Get the definition - let us = run.get_db_user(opt.ns(), opt.db(), &self.name).await?; + let us = run.get_db_user(opt.ns()?, opt.db()?, &self.name).await?; // Delete the definition - let key = crate::key::database::us::new(opt.ns(), opt.db(), &us.name); + let key = crate::key::database::us::new(opt.ns()?, opt.db()?, &us.name); run.del(key).await?; // Ok all good Ok(Value::None) diff --git a/core/src/sql/statements/show.rs b/core/src/sql/statements/show.rs index b430576fef9..bb46b0c8c84 100644 --- a/core/src/sql/statements/show.rs +++ b/core/src/sql/statements/show.rs @@ -60,8 +60,8 @@ impl ShowStatement { let tb = self.table.as_deref(); let r = crate::cf::read( &mut run, - opt.ns(), - opt.db(), + opt.ns()?, + opt.db()?, tb.map(|x| x.as_str()), self.since.clone(), self.limit, diff --git a/lib/tests/remove.rs b/lib/tests/remove.rs index c588814a7e9..9b525e0af8e 100644 --- a/lib/tests/remove.rs +++ b/lib/tests/remove.rs @@ -49,6 +49,102 @@ async fn remove_statement_table() -> Result<(), Error> { Ok(()) } +#[tokio::test] +async fn remove_statement_namespace() -> Result<(), Error> { + // Namespace not selected + { + let sql = " + REMOVE NAMESPACE test; + DEFINE NAMESPACE test; + REMOVE NAMESPACE test; + "; + let dbs = new_ds().await?; + let ses = Session::owner(); + let res = &mut dbs.execute(sql, &ses, None).await?; + assert_eq!(res.len(), 3); + // + let tmp = res.remove(0).result; + assert!(tmp.is_err()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + } + // Namespace selected + { + let sql = " + REMOVE NAMESPACE test; + DEFINE NAMESPACE test; + REMOVE NAMESPACE test; + "; + let dbs = new_ds().await?; + // No namespace is selected + let ses = Session::owner().with_ns("test"); + let res = &mut dbs.execute(sql, &ses, None).await?; + assert_eq!(res.len(), 3); + // + let tmp = res.remove(0).result; + assert!(tmp.is_err()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + } + Ok(()) +} + +#[tokio::test] +async fn remove_statement_database() -> Result<(), Error> { + // Database not selected + { + let sql = " + REMOVE DATABASE test; + DEFINE DATABASE test; + REMOVE DATABASE test; + "; + let dbs = new_ds().await?; + let ses = Session::owner().with_ns("test"); + let res = &mut dbs.execute(sql, &ses, None).await?; + assert_eq!(res.len(), 3); + // + let tmp = res.remove(0).result; + assert!(tmp.is_err()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + } + // Database selected + { + let sql = " + REMOVE DATABASE test; + DEFINE DATABASE test; + REMOVE DATABASE test; + "; + let dbs = new_ds().await?; + // No database is selected + 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_err()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + } + Ok(()) +} + #[tokio::test] async fn remove_statement_analyzer() -> Result<(), Error> { let sql = "