From 75fc006c21e6375d6bcdabec4da32f2630374774 Mon Sep 17 00:00:00 2001 From: Emmanuel Keller Date: Mon, 10 Jul 2023 09:24:47 +0100 Subject: [PATCH] Ensure index resources are properly deleted on index deletion (#2234) --- lib/src/doc/index.rs | 15 +++++-- lib/src/idx/planner/plan.rs | 6 +-- lib/src/key/bc.rs | 44 ++++++++++++++++++ lib/src/key/bd.rs | 44 ++++++++++++++++++ lib/src/key/bf.rs | 44 ++++++++++++++++++ lib/src/key/bi.rs | 44 ++++++++++++++++++ lib/src/key/bk.rs | 44 ++++++++++++++++++ lib/src/key/bl.rs | 44 ++++++++++++++++++ lib/src/key/bo.rs | 44 ++++++++++++++++++ lib/src/key/bp.rs | 44 ++++++++++++++++++ lib/src/key/bt.rs | 44 ++++++++++++++++++ lib/src/key/bu.rs | 44 ++++++++++++++++++ lib/src/key/index.rs | 52 +++++++-------------- lib/src/lib.rs | 3 +- lib/src/sql/statements/define.rs | 6 +-- lib/src/sql/statements/remove.rs | 43 +++++++++++++++--- lib/tests/remove.rs | 77 ++++++++++++++++++++++++++++++++ 17 files changed, 590 insertions(+), 52 deletions(-) diff --git a/lib/src/doc/index.rs b/lib/src/doc/index.rs index e4a72154..c2c5c579 100644 --- a/lib/src/doc/index.rs +++ b/lib/src/doc/index.rs @@ -118,13 +118,13 @@ impl<'a> IndexOperation<'a> { } fn get_non_unique_index_key(&self, v: &Array) -> key::index::Index { - key::index::new( + key::index::Index::new( self.opt.ns(), self.opt.db(), &self.ix.what, &self.ix.name, - v, - Some(&self.rid.id), + v.to_owned(), + Some(self.rid.id.to_owned()), ) } @@ -145,7 +145,14 @@ impl<'a> IndexOperation<'a> { } fn get_unique_index_key(&self, v: &Array) -> key::index::Index { - key::index::new(self.opt.ns(), self.opt.db(), &self.ix.what, &self.ix.name, v, None) + key::index::Index::new( + self.opt.ns(), + self.opt.db(), + &self.ix.what, + &self.ix.name, + v.to_owned(), + None, + ) } async fn index_unique(&self, run: &mut kvs::Transaction) -> Result<(), Error> { diff --git a/lib/src/idx/planner/plan.rs b/lib/src/idx/planner/plan.rs index f2f3cc96..e43d5607 100644 --- a/lib/src/idx/planner/plan.rs +++ b/lib/src/idx/planner/plan.rs @@ -198,8 +198,8 @@ impl NonUniqueEqualThingIterator { v: &Value, ) -> Result { let v = Array::from(v.clone()); - let beg = key::index::prefix_all_ids(opt.ns(), opt.db(), &ix.what, &ix.name, &v); - let end = key::index::suffix_all_ids(opt.ns(), opt.db(), &ix.what, &ix.name, &v); + let (beg, end) = + key::index::Index::range_all_ids(opt.ns(), opt.db(), &ix.what, &ix.name, &v); Ok(Self { beg, end, @@ -230,7 +230,7 @@ pub(crate) struct UniqueEqualThingIterator { impl UniqueEqualThingIterator { fn new(opt: &Options, ix: &DefineIndexStatement, v: &Value) -> Result { let v = Array::from(v.clone()); - let key = key::index::new(opt.ns(), opt.db(), &ix.what, &ix.name, &v, None).into(); + let key = key::index::Index::new(opt.ns(), opt.db(), &ix.what, &ix.name, v, None).into(); Ok(Self { key: Some(key), }) diff --git a/lib/src/key/bc.rs b/lib/src/key/bc.rs index 327515c7..82e4291a 100644 --- a/lib/src/key/bc.rs +++ b/lib/src/key/bc.rs @@ -1,6 +1,7 @@ use crate::idx::ft::terms::TermId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bc<'a> { @@ -37,6 +38,49 @@ impl<'a> Bc<'a> { term_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'c', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bd.rs b/lib/src/key/bd.rs index 3a83304d..3e7e68a9 100644 --- a/lib/src/key/bd.rs +++ b/lib/src/key/bd.rs @@ -1,6 +1,7 @@ use crate::idx::btree::NodeId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bd<'a> { @@ -43,6 +44,49 @@ impl<'a> Bd<'a> { node_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'd', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bf.rs b/lib/src/key/bf.rs index 833310b5..865caeec 100644 --- a/lib/src/key/bf.rs +++ b/lib/src/key/bf.rs @@ -2,6 +2,7 @@ use crate::idx::ft::docids::DocId; use crate::idx::ft::terms::TermId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bf<'a> { @@ -47,6 +48,49 @@ impl<'a> Bf<'a> { doc_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'f', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bi.rs b/lib/src/key/bi.rs index 944e8ce9..26a602a5 100644 --- a/lib/src/key/bi.rs +++ b/lib/src/key/bi.rs @@ -1,6 +1,7 @@ use crate::idx::btree::NodeId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bi<'a> { @@ -37,6 +38,49 @@ impl<'a> Bi<'a> { node_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +pub struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'i', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bk.rs b/lib/src/key/bk.rs index d33fb7da..42e7e97f 100644 --- a/lib/src/key/bk.rs +++ b/lib/src/key/bk.rs @@ -1,6 +1,7 @@ use crate::idx::ft::docids::DocId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bk<'a> { @@ -37,6 +38,49 @@ impl<'a> Bk<'a> { doc_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'k', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bl.rs b/lib/src/key/bl.rs index 9babeffd..10740f27 100644 --- a/lib/src/key/bl.rs +++ b/lib/src/key/bl.rs @@ -1,6 +1,7 @@ use crate::idx::btree::NodeId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bl<'a> { @@ -43,6 +44,49 @@ impl<'a> Bl<'a> { node_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +pub struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'l', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bo.rs b/lib/src/key/bo.rs index eb63d897..51865826 100644 --- a/lib/src/key/bo.rs +++ b/lib/src/key/bo.rs @@ -2,6 +2,7 @@ use crate::idx::ft::docids::DocId; use crate::idx::ft::terms::TermId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bo<'a> { @@ -47,6 +48,49 @@ impl<'a> Bo<'a> { term_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +pub struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'o', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bp.rs b/lib/src/key/bp.rs index 6bb95bd2..03d94d1e 100644 --- a/lib/src/key/bp.rs +++ b/lib/src/key/bp.rs @@ -1,6 +1,7 @@ use crate::idx::btree::NodeId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bp<'a> { @@ -43,6 +44,49 @@ impl<'a> Bp<'a> { node_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +pub struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + pub fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'p', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bt.rs b/lib/src/key/bt.rs index eee3a61b..e7d5d437 100644 --- a/lib/src/key/bt.rs +++ b/lib/src/key/bt.rs @@ -1,6 +1,7 @@ use crate::idx::btree::NodeId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bt<'a> { @@ -43,6 +44,49 @@ impl<'a> Bt<'a> { node_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b't', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/bu.rs b/lib/src/key/bu.rs index 7e9f51dc..f7d9813a 100644 --- a/lib/src/key/bu.rs +++ b/lib/src/key/bu.rs @@ -1,6 +1,7 @@ use crate::idx::ft::terms::TermId; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] pub struct Bu<'a> { @@ -37,6 +38,49 @@ impl<'a> Bu<'a> { term_id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] +struct Prefix<'a> { + __: u8, + _a: u8, + pub ns: &'a str, + _b: u8, + pub db: &'a str, + _c: u8, + pub tb: &'a str, + _d: u8, + _e: u8, + _f: u8, + pub ix: &'a str, + _g: u8, +} + +impl<'a> Prefix<'a> { + fn new(ns: &'a str, db: &'a str, tb: &'a str, ix: &'a str) -> Self { + Self { + __: b'/', + _a: b'*', + ns, + _b: b'*', + db, + _c: b'*', + tb, + _d: b'!', + _e: b'b', + _f: b'u', + ix, + _g: b'*', + } + } } #[cfg(test)] diff --git a/lib/src/key/index.rs b/lib/src/key/index.rs index 64b9a3b5..5a048d60 100644 --- a/lib/src/key/index.rs +++ b/lib/src/key/index.rs @@ -3,6 +3,7 @@ use crate::sql::array::Array; use crate::sql::id::Id; use derive::Key; use serde::{Deserialize, Serialize}; +use std::ops::Range; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)] struct Prefix<'a> { @@ -79,41 +80,6 @@ pub struct Index<'a> { pub id: Option, } -pub fn new<'a>( - ns: &'a str, - db: &'a str, - tb: &'a str, - ix: &'a str, - fd: &Array, - id: Option<&Id>, -) -> Index<'a> { - Index::new(ns, db, tb, ix, fd.to_owned(), id.cloned()) -} - -pub fn prefix(ns: &str, db: &str, tb: &str, ix: &str) -> Vec { - let mut k = Prefix::new(ns, db, tb, ix).encode().unwrap(); - k.extend_from_slice(&[0x00]); - k -} - -pub fn suffix(ns: &str, db: &str, tb: &str, ix: &str) -> Vec { - let mut k = Prefix::new(ns, db, tb, ix).encode().unwrap(); - k.extend_from_slice(&[0xff]); - k -} - -pub fn prefix_all_ids(ns: &str, db: &str, tb: &str, ix: &str, fd: &Array) -> Vec { - let mut k = PrefixIds::new(ns, db, tb, ix, fd).encode().unwrap(); - k.extend_from_slice(&[0x00]); - k -} - -pub fn suffix_all_ids(ns: &str, db: &str, tb: &str, ix: &str, fd: &Array) -> Vec { - let mut k = PrefixIds::new(ns, db, tb, ix, fd).encode().unwrap(); - k.extend_from_slice(&[0xff]); - k -} - impl<'a> Index<'a> { pub fn new( ns: &'a str, @@ -137,6 +103,22 @@ impl<'a> Index<'a> { id, } } + + pub fn range(ns: &str, db: &str, tb: &str, ix: &str) -> Range> { + let mut beg = Prefix::new(ns, db, tb, ix).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = Prefix::new(ns, db, tb, ix).encode().unwrap(); + end.extend_from_slice(&[0xff]); + beg..end + } + + pub fn range_all_ids(ns: &str, db: &str, tb: &str, ix: &str, fd: &Array) -> (Vec, Vec) { + let mut beg = PrefixIds::new(ns, db, tb, ix, fd).encode().unwrap(); + beg.extend_from_slice(&[0x00]); + let mut end = PrefixIds::new(ns, db, tb, ix, fd).encode().unwrap(); + end.extend_from_slice(&[0xff]); + (beg, end) + } } #[cfg(test)] diff --git a/lib/src/lib.rs b/lib/src/lib.rs index bfcb37a5..e1a98964 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -111,7 +111,6 @@ mod ctx; mod doc; mod exe; mod fnc; -mod key; mod vs; pub mod sql; @@ -137,6 +136,8 @@ pub mod iam; #[doc(hidden)] pub mod idx; #[doc(hidden)] +pub mod key; +#[doc(hidden)] pub mod kvs; #[doc(inline)] diff --git a/lib/src/sql/statements/define.rs b/lib/src/sql/statements/define.rs index 29a7f087..c0ad0eb7 100644 --- a/lib/src/sql/statements/define.rs +++ b/lib/src/sql/statements/define.rs @@ -21,7 +21,7 @@ use crate::sql::idiom::{Idiom, Idioms}; use crate::sql::index::Index; use crate::sql::kind::{kind, Kind}; use crate::sql::permission::{permissions, Permissions}; -use crate::sql::statements::UpdateStatement; +use crate::sql::statements::{RemoveIndexStatement, UpdateStatement}; use crate::sql::strand::strand_raw; use crate::sql::tokenizer::{tokenizers, Tokenizer}; use crate::sql::value::{value, values, Value, Values}; @@ -1310,9 +1310,7 @@ impl DefineIndexStatement { let key = crate::key::ix::prefix(opt.ns(), opt.db(), &self.what); run.clr(key).await?; // Remove the index data - let beg = crate::key::index::prefix(opt.ns(), opt.db(), &self.what, &self.name); - let end = crate::key::index::suffix(opt.ns(), opt.db(), &self.what, &self.name); - run.delr(beg..end, u32::MAX).await?; + RemoveIndexStatement::delete_resources(&mut run, opt, &self.what, &self.name).await?; // Release the transaction drop(run); // Force queries to run diff --git a/lib/src/sql/statements/remove.rs b/lib/src/sql/statements/remove.rs index e386243b..04eeed97 100644 --- a/lib/src/sql/statements/remove.rs +++ b/lib/src/sql/statements/remove.rs @@ -3,6 +3,7 @@ use crate::dbs::Options; use crate::dbs::{Level, Transaction}; use crate::doc::CursorDoc; use crate::err::Error; +use crate::kvs; use crate::sql::base::{base, base_or_scope, Base}; use crate::sql::comment::{mightbespace, shouldbespace}; use crate::sql::error::IResult; @@ -238,7 +239,7 @@ impl RemoveFunctionStatement { } } -impl fmt::Display for RemoveFunctionStatement { +impl Display for RemoveFunctionStatement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "REMOVE FUNCTION fn::{}", self.name) } @@ -793,13 +794,45 @@ impl RemoveIndexStatement { // Clear the cache let key = crate::key::ix::prefix(opt.ns(), opt.db(), &self.what); run.clr(key).await?; - // Remove the resource data - let beg = crate::key::index::prefix(opt.ns(), opt.db(), &self.what, &self.name); - let end = crate::key::index::suffix(opt.ns(), opt.db(), &self.what, &self.name); - run.delr(beg..end, u32::MAX).await?; + // Delete resource + Self::delete_resources(&mut run, opt, &self.what, &self.name).await?; // Ok all good Ok(Value::None) } + + // Remove the resource data (whatever the type of the index) + pub(crate) async fn delete_resources( + run: &mut kvs::Transaction, + opt: &Options, + tb: &str, + ix: &str, + ) -> Result<(), Error> { + let rng = crate::key::index::Index::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bc::Bc::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bd::Bd::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bf::Bf::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bi::Bi::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bk::Bk::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bl::Bl::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bo::Bo::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bp::Bp::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let key = crate::key::bs::Bs::new(opt.ns(), opt.db(), tb, ix); + run.del(key).await?; + let rng = crate::key::bt::Bt::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + let rng = crate::key::bu::Bu::range(opt.ns(), opt.db(), tb, ix); + run.delr(rng, u32::MAX).await?; + Ok(()) + } } impl Display for RemoveIndexStatement { diff --git a/lib/tests/remove.rs b/lib/tests/remove.rs index 01b917b7..382056eb 100644 --- a/lib/tests/remove.rs +++ b/lib/tests/remove.rs @@ -3,6 +3,18 @@ mod parse; use parse::Parse; use surrealdb::dbs::Session; use surrealdb::err::Error; +use surrealdb::key::bc::Bc; +use surrealdb::key::bd::Bd; +use surrealdb::key::bf::Bf; +use surrealdb::key::bi::Bi; +use surrealdb::key::bk::Bk; +use surrealdb::key::bl::Bl; +use surrealdb::key::bo::Bo; +use surrealdb::key::bp::Bp; +use surrealdb::key::bs::Bs; +use surrealdb::key::bt::Bt; +use surrealdb::key::bu::Bu; +use surrealdb::key::index::Index; use surrealdb::kvs::Datastore; use surrealdb::sql::Value; @@ -73,3 +85,68 @@ async fn remove_statement_analyzer() -> Result<(), Error> { assert_eq!(tmp, val); Ok(()) } + +macro_rules! check_empty_range { + ($tx:expr, $rng:expr) => {{ + let r = $tx.getr($rng, 1).await?; + assert!(r.is_empty()); + }}; +} + +macro_rules! check_none_val { + ($tx:expr, $key:expr) => {{ + let r = $tx.get($key).await?; + assert!(r.is_none()); + }}; +} + +#[tokio::test] +async fn remove_statement_index() -> Result<(), Error> { + let sql = " + DEFINE INDEX uniq_isbn ON book FIELDS isbn UNIQUE; + DEFINE INDEX idx_author ON book FIELDS author; + DEFINE ANALYZER simple TOKENIZERS blank,class FILTERS lowercase; + DEFINE INDEX ft_title ON book FIELDS title SEARCH ANALYZER simple BM25 HIGHLIGHTS; + CREATE book:1 SET title = 'Rust Web Programming', isbn = '978-1803234694', author = 'Maxwell Flitton'; + REMOVE INDEX uniq_isbn ON book; + REMOVE INDEX idx_author ON book; + REMOVE INDEX ft_title ON book; + INFO FOR TABLE book; + "; + 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).await?; + assert_eq!(res.len(), 9); + for _ in 0..8 { + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + } + // Check infos output + let tmp = res.remove(0).result?; + let val = Value::parse( + "{ + events: {}, + fields: {}, + indexes: {}, + tables: {}, + }", + ); + assert_eq!(tmp, val); + + let mut tx = dbs.transaction(false, false).await?; + for ix in ["uniq_isbn", "idx_author", "ft_title"] { + check_empty_range!(&mut tx, Bc::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bd::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bf::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bi::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bk::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bl::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bo::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bp::range("test", "test", "book", ix)); + check_none_val!(&mut tx, Bs::new("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bt::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Bu::range("test", "test", "book", ix)); + check_empty_range!(&mut tx, Index::range("test", "test", "book", ix)); + } + Ok(()) +}