diff --git a/lib/src/kvs/ex.rs b/lib/src/kvs/ex.rs new file mode 100644 index 00000000..a593d15e --- /dev/null +++ b/lib/src/kvs/ex.rs @@ -0,0 +1,279 @@ +use super::Transaction; +use crate::err::Error; +use crate::kvs::Key; +use crate::kvs::Val; +use crate::sql; +use sql::statements::DefineDatabaseStatement; +use sql::statements::DefineEventStatement; +use sql::statements::DefineFieldStatement; +use sql::statements::DefineIndexStatement; +use sql::statements::DefineLoginStatement; +use sql::statements::DefineNamespaceStatement; +use sql::statements::DefineScopeStatement; +use sql::statements::DefineTableStatement; +use sql::statements::DefineTokenStatement; +use sql::statements::LiveStatement; + +pub trait Convert { + fn convert(self) -> T; +} + +impl Convert> for Vec<(Key, Val)> +where + T: From, +{ + fn convert(self) -> Vec { + self.into_iter().map(|(_, v)| v.into()).collect() + } +} + +impl Transaction { + // Get all namespaces + pub async fn all_ns(&mut self) -> Result, Error> { + let beg = crate::key::ns::new(crate::key::PREFIX); + let end = crate::key::ns::new(crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all namespace logins + pub async fn all_nl(&mut self, ns: &str) -> Result, Error> { + let beg = crate::key::nl::new(ns, crate::key::PREFIX); + let end = crate::key::nl::new(ns, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all namespace tokens + pub async fn all_nt(&mut self, ns: &str) -> Result, Error> { + let beg = crate::key::nt::new(ns, crate::key::PREFIX); + let end = crate::key::nt::new(ns, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all databases + pub async fn all_db(&mut self, ns: &str) -> Result, Error> { + let beg = crate::key::db::new(ns, crate::key::PREFIX); + let end = crate::key::db::new(ns, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all database logins + pub async fn all_dl(&mut self, ns: &str, db: &str) -> Result, Error> { + let beg = crate::key::dl::new(ns, db, crate::key::PREFIX); + let end = crate::key::dl::new(ns, db, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all database tokens + pub async fn all_dt(&mut self, ns: &str, db: &str) -> Result, Error> { + let beg = crate::key::dt::new(ns, db, crate::key::PREFIX); + let end = crate::key::dt::new(ns, db, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all scopes + pub async fn all_sc(&mut self, ns: &str, db: &str) -> Result, Error> { + let beg = crate::key::sc::new(ns, db, crate::key::PREFIX); + let end = crate::key::sc::new(ns, db, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all scope tokens + pub async fn all_st( + &mut self, + ns: &str, + db: &str, + sc: &str, + ) -> Result, Error> { + let beg = crate::key::st::new(ns, db, sc, crate::key::PREFIX); + let end = crate::key::st::new(ns, db, sc, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all tables + pub async fn all_tb(&mut self, ns: &str, db: &str) -> Result, Error> { + let beg = crate::key::tb::new(ns, db, crate::key::PREFIX); + let end = crate::key::tb::new(ns, db, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all events + pub async fn all_ev( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result, Error> { + let beg = crate::key::ev::new(ns, db, tb, crate::key::PREFIX); + let end = crate::key::ev::new(ns, db, tb, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all fields + pub async fn all_fd( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result, Error> { + let beg = crate::key::fd::new(ns, db, tb, crate::key::PREFIX); + let end = crate::key::fd::new(ns, db, tb, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all fields + pub async fn all_ix( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result, Error> { + let beg = crate::key::ix::new(ns, db, tb, crate::key::PREFIX); + let end = crate::key::ix::new(ns, db, tb, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all views + pub async fn all_ft( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result, Error> { + let beg = crate::key::ft::new(ns, db, tb, crate::key::PREFIX); + let end = crate::key::ft::new(ns, db, tb, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } + // Get all lives + pub async fn all_lv( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result, Error> { + let beg = crate::key::lv::new(ns, db, tb, crate::key::PREFIX); + let end = crate::key::lv::new(ns, db, tb, crate::key::SUFFIX); + let val = self.getr(beg..end, u32::MAX).await?; + Ok(val.convert()) + } +} + +impl Transaction { + // Get a namespace + pub async fn get_ns(&mut self, ns: &str) -> Result { + let key = crate::key::ns::new(ns); + let val = self.get(key).await?.ok_or(Error::NsNotFound)?; + Ok(val.into()) + } + // Get a namespace login + pub async fn get_nl(&mut self, ns: &str, nl: &str) -> Result { + let key = crate::key::nl::new(ns, nl); + let val = self.get(key).await?.ok_or(Error::NlNotFound)?; + Ok(val.into()) + } + // Get a namespace token + pub async fn get_nt(&mut self, ns: &str, nt: &str) -> Result { + let key = crate::key::nt::new(ns, nt); + let val = self.get(key).await?.ok_or(Error::NtNotFound)?; + Ok(val.into()) + } + // Get a database + pub async fn get_db(&mut self, ns: &str, db: &str) -> Result { + let key = crate::key::db::new(ns, db); + let val = self.get(key).await?.ok_or(Error::DbNotFound)?; + Ok(val.into()) + } + // Get a database login + pub async fn get_dl( + &mut self, + ns: &str, + db: &str, + dl: &str, + ) -> Result { + let key = crate::key::dl::new(ns, db, dl); + let val = self.get(key).await?.ok_or(Error::DlNotFound)?; + Ok(val.into()) + } + // Get a database token + pub async fn get_dt( + &mut self, + ns: &str, + db: &str, + dt: &str, + ) -> Result { + let key = crate::key::dt::new(ns, db, dt); + let val = self.get(key).await?.ok_or(Error::DtNotFound)?; + Ok(val.into()) + } + // Get a scope + pub async fn get_sc( + &mut self, + ns: &str, + db: &str, + sc: &str, + ) -> Result { + let key = crate::key::sc::new(ns, db, sc); + let val = self.get(key).await?.ok_or(Error::ScNotFound)?; + Ok(val.into()) + } + // Get a scope token + pub async fn get_st( + &mut self, + ns: &str, + db: &str, + sc: &str, + st: &str, + ) -> Result { + let key = crate::key::st::new(ns, db, sc, st); + let val = self.get(key).await?.ok_or(Error::StNotFound)?; + Ok(val.into()) + } + // Get a table + pub async fn get_tb( + &mut self, + ns: &str, + db: &str, + tb: &str, + ) -> Result { + let key = crate::key::tb::new(ns, db, tb); + let val = self.get(key).await?.ok_or(Error::TbNotFound)?; + Ok(val.into()) + } +} + +impl Transaction { + // Get all namespaces + pub async fn add_ns(&mut self, ns: &str) -> Result<(), Error> { + let key = crate::key::ns::new(ns); + self.put( + key, + DefineNamespaceStatement { + name: ns.to_owned(), + }, + ) + .await + } + // Get all namespace logins + pub async fn add_db(&mut self, ns: &str, db: &str) -> Result<(), Error> { + let key = crate::key::db::new(ns, db); + self.put( + key, + DefineDatabaseStatement { + name: db.to_owned(), + }, + ) + .await + } + // Get all namespace tokens + pub async fn add_tb(&mut self, ns: &str, db: &str, tb: &str) -> Result<(), Error> { + let key = crate::key::tb::new(ns, db, tb); + self.put( + key, + DefineTableStatement { + name: tb.to_owned(), + ..DefineTableStatement::default() + }, + ) + .await + } +} diff --git a/lib/src/kvs/mod.rs b/lib/src/kvs/mod.rs index c7ddeb78..9feed3e0 100644 --- a/lib/src/kvs/mod.rs +++ b/lib/src/kvs/mod.rs @@ -1,3 +1,4 @@ +mod ex; mod file; mod ixdb; mod kv; diff --git a/lib/src/kvs/tx.rs b/lib/src/kvs/tx.rs index 1a2cb0be..99bfdb33 100644 --- a/lib/src/kvs/tx.rs +++ b/lib/src/kvs/tx.rs @@ -4,6 +4,17 @@ use crate::kvs::Key; use crate::kvs::Val; use std::ops::Range; +trait Add { + fn add(self, v: T) -> Self; +} + +impl Add for Vec { + fn add(mut self, v: u8) -> Self { + self.push(v); + self + } +} + impl Transaction { // Check if closed pub async fn closed(&self) -> bool { @@ -151,4 +162,178 @@ impl Transaction { Transaction::TiKV(v) => v.scan(rng, limit).await, } } + // Retrieve a range of keys from the databases + pub async fn getr(&mut self, rng: Range, limit: u32) -> Result, Error> + where + K: Into, + { + let beg: Key = rng.start.into(); + let end: Key = rng.end.into(); + let mut nxt: Option = None; + let mut num = limit; + let mut out: Vec<(Key, Val)> = vec![]; + // Start processing + while num > 0 { + // Get records batch + let res = match nxt { + None => { + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + Some(ref mut beg) => { + beg.push(0); + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + }; + // Get total results + let n = res.len() - 1; + // Loop over results + for (i, (k, v)) in res.into_iter().enumerate() { + // Ready the next + if i == n { + nxt = Some(k.clone()); + } + // Delete + out.push((k, v)); + // Count + num -= 1; + } + } + Ok(out) + } + // Delete a range of keys from the databases + pub async fn delr(&mut self, rng: Range, limit: u32) -> Result<(), Error> + where + K: Into, + { + let beg: Key = rng.start.into(); + let end: Key = rng.end.into(); + let mut nxt: Option = None; + let mut num = limit; + // Start processing + while num > 0 { + // Get records batch + let res = match nxt { + None => { + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + Some(ref mut beg) => { + beg.push(0); + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + }; + // Get total results + let n = res.len() - 1; + // Loop over results + for (i, (k, _)) in res.into_iter().enumerate() { + // Ready the next + if i == n { + nxt = Some(k.clone()); + } + // Delete + self.del(k).await?; + // Count + num -= 1; + } + } + Ok(()) + } + // Retrieve a prefix of keys from the databases + pub async fn getp(&mut self, key: K, limit: u32) -> Result, Error> + where + K: Into, + { + let beg: Key = key.into(); + let end: Key = beg.clone().add(255); + let mut nxt: Option = None; + let mut num = limit; + let mut out: Vec<(Key, Val)> = vec![]; + // Start processing + while num > 0 { + // Get records batch + let res = match nxt { + None => { + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + Some(ref mut beg) => { + beg.push(0); + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + }; + // Get total results + let n = res.len() - 1; + // Loop over results + for (i, (k, v)) in res.into_iter().enumerate() { + // Ready the next + if i == n { + nxt = Some(k.clone()); + } + // Delete + out.push((k, v)); + // Count + num -= 1; + } + } + Ok(out) + } + // Delete a prefix of keys from the databases + pub async fn delp(&mut self, key: K, limit: u32) -> Result<(), Error> + where + K: Into, + { + let beg: Key = key.into(); + let end: Key = beg.clone().add(255); + let mut nxt: Option = None; + let mut num = limit; + // Start processing + while num > 0 { + // Get records batch + let res = match nxt { + None => { + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + Some(ref mut beg) => { + beg.push(0); + let min = beg.clone(); + let max = end.clone(); + let num = std::cmp::min(1000, num); + self.scan(min..max, num).await? + } + }; + // Get total results + let n = res.len() - 1; + // Loop over results + for (i, (k, _)) in res.into_iter().enumerate() { + // Ready the next + if i == n { + nxt = Some(k.clone()); + } + // Delete + self.del(k).await?; + // Count + num -= 1; + } + } + Ok(()) + } } diff --git a/lib/src/sql/statements/define.rs b/lib/src/sql/statements/define.rs index fade3ab7..02084b83 100644 --- a/lib/src/sql/statements/define.rs +++ b/lib/src/sql/statements/define.rs @@ -14,17 +14,24 @@ use crate::sql::idiom; use crate::sql::idiom::{Idiom, Idioms}; use crate::sql::kind::{kind, Kind}; use crate::sql::permission::{permissions, Permissions}; +use crate::sql::statements::UpdateStatement; use crate::sql::strand::strand_raw; use crate::sql::value::{value, values, Value, Values}; use crate::sql::view::{view, View}; +use argon2::password_hash::{PasswordHasher, SaltString}; +use argon2::Argon2; use derive::Store; use nom::branch::alt; use nom::bytes::complete::tag_no_case; use nom::combinator::{map, opt}; use nom::multi::many0; use nom::sequence::tuple; +use rand::distributions::Alphanumeric; +use rand::rngs::OsRng; +use rand::Rng; use serde::{Deserialize, Serialize}; use std::fmt; +use std::sync::Arc; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Store)] pub enum DefineStatement { @@ -105,13 +112,16 @@ impl DefineNamespaceStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Kv)?; - // Continue - todo!() + // Process the statement + let key = crate::key::ns::new(&self.name); + txn.clone().lock().await.set(key, self).await?; + // Ok all good + Ok(Value::None) } } @@ -149,13 +159,20 @@ impl DefineDatabaseStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Ns)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::db::new(opt.ns(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) } } @@ -187,8 +204,8 @@ fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> { pub struct DefineLoginStatement { pub name: String, pub base: Base, - pub pass: Option, - pub hash: Option, + pub hash: String, + pub code: String, } impl DefineLoginStatement { @@ -196,30 +213,45 @@ impl DefineLoginStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { - // Allowed to run? match self.base { - Base::Ns => opt.check(Level::Kv)?, - Base::Db => opt.check(Level::Ns)?, + Base::Ns => { + // Allowed to run? + opt.check(Level::Kv)?; + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::nl::new(opt.ns(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) + } + Base::Db => { + // Allowed to run? + opt.check(Level::Ns)?; + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::dl::new(opt.ns(), opt.db(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) + } _ => unreachable!(), } - // Continue - todo!() } } impl fmt::Display for DefineLoginStatement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "DEFINE LOGIN {} ON {}", self.name, self.base)?; - if let Some(ref v) = self.pass { - write!(f, " PASSWORD {}", v)? - } - if let Some(ref v) = self.hash { - write!(f, " PASSHASH {}", v)? - } - Ok(()) + write!(f, "DEFINE LOGIN {} ON {} PASSHASH {}", self.name, self.base, self.hash) } } @@ -239,13 +271,17 @@ fn login(i: &str) -> IResult<&str, DefineLoginStatement> { DefineLoginStatement { name, base, - pass: match opts { - DefineLoginOption::Password(ref v) => Some(v.to_owned()), - _ => None, - }, + code: rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(128) + .map(char::from) + .collect::(), hash: match opts { - DefineLoginOption::Passhash(ref v) => Some(v.to_owned()), - _ => None, + DefineLoginOption::Passhash(v) => v, + DefineLoginOption::Password(v) => Argon2::default() + .hash_password(v.as_ref(), SaltString::generate(&mut OsRng).as_ref()) + .unwrap() + .to_string(), }, }, )) @@ -294,17 +330,39 @@ impl DefineTokenStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { - // Allowed to run? match self.base { - Base::Ns => opt.check(Level::Kv)?, - Base::Db => opt.check(Level::Ns)?, + Base::Ns => { + // Allowed to run? + opt.check(Level::Kv)?; + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::nt::new(opt.ns(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) + } + Base::Db => { + // Allowed to run? + opt.check(Level::Ns)?; + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::dt::new(opt.ns(), opt.db(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) + } _ => unreachable!(), } - // Continue - todo!() } } @@ -354,6 +412,7 @@ fn token(i: &str) -> IResult<&str, DefineTokenStatement> { #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] pub struct DefineScopeStatement { pub name: String, + pub code: String, pub session: Option, pub signup: Option, pub signin: Option, @@ -365,13 +424,21 @@ impl DefineScopeStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Db)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::sc::new(opt.ns(), opt.db(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) } } @@ -405,6 +472,11 @@ fn scope(i: &str) -> IResult<&str, DefineScopeStatement> { i, DefineScopeStatement { name, + code: rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(128) + .map(char::from) + .collect::(), session: opts.iter().find_map(|x| match x { DefineScopeOption::Session(ref v) => Some(v.to_owned()), _ => None, @@ -485,15 +557,41 @@ pub struct DefineTableStatement { impl DefineTableStatement { pub async fn compute( &self, - _ctx: &Runtime, + ctx: &Runtime, opt: &Options, - _txn: &Transaction, - _doc: Option<&Value>, + txn: &Transaction, + doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Db)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::tb::new(opt.ns(), opt.db(), &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.set(key, self).await?; + // Check if table is a view + if let Some(view) = &self.view { + // Remove the table data + let key = crate::key::table::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::ft::new(opt.ns(), opt.db(), &v.name, &self.name); + run.set(key, self).await?; + // Process the view data + let stm = UpdateStatement { + what: Values(vec![Value::Table(v.clone())]), + ..UpdateStatement::default() + }; + Arc::new(stm).compute(ctx, opt, txn, doc).await?; + } + } + // Ok all good + Ok(Value::None) } } @@ -618,13 +716,22 @@ impl DefineEventStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Db)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::ev::new(opt.ns(), opt.db(), &self.what, &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.add_tb(opt.ns(), opt.db(), &self.what).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) } } @@ -688,13 +795,22 @@ impl DefineFieldStatement { &self, _ctx: &Runtime, opt: &Options, - _txn: &Transaction, + txn: &Transaction, _doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Db)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::fd::new(opt.ns(), opt.db(), &self.what, &self.name.to_string()); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.add_tb(opt.ns(), opt.db(), &self.what).await?; + run.set(key, self).await?; + // Ok all good + Ok(Value::None) } } @@ -825,15 +941,33 @@ pub struct DefineIndexStatement { impl DefineIndexStatement { pub async fn compute( &self, - _ctx: &Runtime, + ctx: &Runtime, opt: &Options, - _txn: &Transaction, - _doc: Option<&Value>, + txn: &Transaction, + doc: Option<&Value>, ) -> Result { // Allowed to run? opt.check(Level::Db)?; - // Continue - todo!() + // Clone transaction + let run = txn.clone(); + // Process the statement + let key = crate::key::ix::new(opt.ns(), opt.db(), &self.what, &self.name); + let mut run = run.lock().await; + run.add_ns(opt.ns()).await?; + run.add_db(opt.ns(), opt.db()).await?; + run.add_tb(opt.ns(), opt.db(), &self.what).await?; + run.set(key, self).await?; + // Remove the index data + let key = crate::key::index::new(opt.ns(), opt.db(), &self.what, &self.name, Value::None); + run.delp(key, u32::MAX).await?; + // Update the index data + let stm = UpdateStatement { + what: Values(vec![Value::Table(self.what.clone().into())]), + ..UpdateStatement::default() + }; + Arc::new(stm).compute(ctx, opt, txn, doc).await?; + // Ok all good + Ok(Value::None) } } diff --git a/lib/src/sql/table.rs b/lib/src/sql/table.rs index 6ac9d706..94facd1b 100644 --- a/lib/src/sql/table.rs +++ b/lib/src/sql/table.rs @@ -27,6 +27,14 @@ pub struct Table { pub name: String, } +impl From for Table { + fn from(v: String) -> Self { + Table { + name: v, + } + } +} + impl fmt::Display for Table { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", escape(&self.name, &val_char, "`"))