Implement initial logic for DEFINE statements

This commit is contained in:
Tobie Morgan Hitchcock 2022-03-07 18:15:57 +00:00
parent 2a0d46a2b6
commit 0f6d700f6b
5 changed files with 660 additions and 53 deletions

279
lib/src/kvs/ex.rs Normal file
View file

@ -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<T> {
fn convert(self) -> T;
}
impl<T> Convert<Vec<T>> for Vec<(Key, Val)>
where
T: From<Val>,
{
fn convert(self) -> Vec<T> {
self.into_iter().map(|(_, v)| v.into()).collect()
}
}
impl Transaction {
// Get all namespaces
pub async fn all_ns(&mut self) -> Result<Vec<DefineNamespaceStatement>, 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<Vec<DefineLoginStatement>, 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<Vec<DefineTokenStatement>, 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<Vec<DefineDatabaseStatement>, 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<Vec<DefineLoginStatement>, 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<Vec<DefineTokenStatement>, 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<Vec<DefineScopeStatement>, 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<Vec<DefineTokenStatement>, 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<Vec<DefineTableStatement>, 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<Vec<DefineEventStatement>, 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<Vec<DefineFieldStatement>, 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<Vec<DefineIndexStatement>, 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<Vec<DefineTableStatement>, 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<Vec<LiveStatement>, 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<DefineNamespaceStatement, Error> {
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<DefineLoginStatement, Error> {
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<DefineTokenStatement, Error> {
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<DefineDatabaseStatement, Error> {
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<DefineLoginStatement, Error> {
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<DefineTokenStatement, Error> {
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<DefineScopeStatement, Error> {
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<DefineTokenStatement, Error> {
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<DefineTableStatement, Error> {
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
}
}

View file

@ -1,3 +1,4 @@
mod ex;
mod file; mod file;
mod ixdb; mod ixdb;
mod kv; mod kv;

View file

@ -4,6 +4,17 @@ use crate::kvs::Key;
use crate::kvs::Val; use crate::kvs::Val;
use std::ops::Range; use std::ops::Range;
trait Add<T> {
fn add(self, v: T) -> Self;
}
impl Add<u8> for Vec<u8> {
fn add(mut self, v: u8) -> Self {
self.push(v);
self
}
}
impl Transaction { impl Transaction {
// Check if closed // Check if closed
pub async fn closed(&self) -> bool { pub async fn closed(&self) -> bool {
@ -151,4 +162,178 @@ impl Transaction {
Transaction::TiKV(v) => v.scan(rng, limit).await, Transaction::TiKV(v) => v.scan(rng, limit).await,
} }
} }
// Retrieve a range of keys from the databases
pub async fn getr<K>(&mut self, rng: Range<K>, limit: u32) -> Result<Vec<(Key, Val)>, Error>
where
K: Into<Key>,
{
let beg: Key = rng.start.into();
let end: Key = rng.end.into();
let mut nxt: Option<Key> = 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<K>(&mut self, rng: Range<K>, limit: u32) -> Result<(), Error>
where
K: Into<Key>,
{
let beg: Key = rng.start.into();
let end: Key = rng.end.into();
let mut nxt: Option<Key> = 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<K>(&mut self, key: K, limit: u32) -> Result<Vec<(Key, Val)>, Error>
where
K: Into<Key>,
{
let beg: Key = key.into();
let end: Key = beg.clone().add(255);
let mut nxt: Option<Key> = 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<K>(&mut self, key: K, limit: u32) -> Result<(), Error>
where
K: Into<Key>,
{
let beg: Key = key.into();
let end: Key = beg.clone().add(255);
let mut nxt: Option<Key> = 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(())
}
} }

View file

@ -14,17 +14,24 @@ use crate::sql::idiom;
use crate::sql::idiom::{Idiom, Idioms}; use crate::sql::idiom::{Idiom, Idioms};
use crate::sql::kind::{kind, Kind}; use crate::sql::kind::{kind, Kind};
use crate::sql::permission::{permissions, Permissions}; use crate::sql::permission::{permissions, Permissions};
use crate::sql::statements::UpdateStatement;
use crate::sql::strand::strand_raw; use crate::sql::strand::strand_raw;
use crate::sql::value::{value, values, Value, Values}; use crate::sql::value::{value, values, Value, Values};
use crate::sql::view::{view, View}; use crate::sql::view::{view, View};
use argon2::password_hash::{PasswordHasher, SaltString};
use argon2::Argon2;
use derive::Store; use derive::Store;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::combinator::{map, opt}; use nom::combinator::{map, opt};
use nom::multi::many0; use nom::multi::many0;
use nom::sequence::tuple; use nom::sequence::tuple;
use rand::distributions::Alphanumeric;
use rand::rngs::OsRng;
use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::sync::Arc;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Store)]
pub enum DefineStatement { pub enum DefineStatement {
@ -105,13 +112,16 @@ impl DefineNamespaceStatement {
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Kv)?; opt.check(Level::Kv)?;
// Continue // Process the statement
todo!() 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, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Ns)?; opt.check(Level::Ns)?;
// Continue // Clone transaction
todo!() 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 struct DefineLoginStatement {
pub name: String, pub name: String,
pub base: Base, pub base: Base,
pub pass: Option<String>, pub hash: String,
pub hash: Option<String>, pub code: String,
} }
impl DefineLoginStatement { impl DefineLoginStatement {
@ -196,30 +213,45 @@ impl DefineLoginStatement {
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run?
match self.base { match self.base {
Base::Ns => opt.check(Level::Kv)?, Base::Ns => {
Base::Db => opt.check(Level::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!(), _ => unreachable!(),
} }
// Continue
todo!()
} }
} }
impl fmt::Display for DefineLoginStatement { impl fmt::Display for DefineLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE LOGIN {} ON {}", self.name, self.base)?; write!(f, "DEFINE LOGIN {} ON {} PASSHASH {}", self.name, self.base, self.hash)
if let Some(ref v) = self.pass {
write!(f, " PASSWORD {}", v)?
}
if let Some(ref v) = self.hash {
write!(f, " PASSHASH {}", v)?
}
Ok(())
} }
} }
@ -239,13 +271,17 @@ fn login(i: &str) -> IResult<&str, DefineLoginStatement> {
DefineLoginStatement { DefineLoginStatement {
name, name,
base, base,
pass: match opts { code: rand::thread_rng()
DefineLoginOption::Password(ref v) => Some(v.to_owned()), .sample_iter(&Alphanumeric)
_ => None, .take(128)
}, .map(char::from)
.collect::<String>(),
hash: match opts { hash: match opts {
DefineLoginOption::Passhash(ref v) => Some(v.to_owned()), DefineLoginOption::Passhash(v) => v,
_ => None, 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, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run?
match self.base { match self.base {
Base::Ns => opt.check(Level::Kv)?, Base::Ns => {
Base::Db => opt.check(Level::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!(), _ => unreachable!(),
} }
// Continue
todo!()
} }
} }
@ -354,6 +412,7 @@ fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineScopeStatement { pub struct DefineScopeStatement {
pub name: String, pub name: String,
pub code: String,
pub session: Option<Duration>, pub session: Option<Duration>,
pub signup: Option<Value>, pub signup: Option<Value>,
pub signin: Option<Value>, pub signin: Option<Value>,
@ -365,13 +424,21 @@ impl DefineScopeStatement {
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Db)?; opt.check(Level::Db)?;
// Continue // Clone transaction
todo!() 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, i,
DefineScopeStatement { DefineScopeStatement {
name, name,
code: rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(128)
.map(char::from)
.collect::<String>(),
session: opts.iter().find_map(|x| match x { session: opts.iter().find_map(|x| match x {
DefineScopeOption::Session(ref v) => Some(v.to_owned()), DefineScopeOption::Session(ref v) => Some(v.to_owned()),
_ => None, _ => None,
@ -485,15 +557,41 @@ pub struct DefineTableStatement {
impl DefineTableStatement { impl DefineTableStatement {
pub async fn compute( pub async fn compute(
&self, &self,
_ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Db)?; opt.check(Level::Db)?;
// Continue // Clone transaction
todo!() 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, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Db)?; opt.check(Level::Db)?;
// Continue // Clone transaction
todo!() 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, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Db)?; opt.check(Level::Db)?;
// Continue // Clone transaction
todo!() 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 { impl DefineIndexStatement {
pub async fn compute( pub async fn compute(
&self, &self,
_ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options,
_txn: &Transaction, txn: &Transaction,
_doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Allowed to run? // Allowed to run?
opt.check(Level::Db)?; opt.check(Level::Db)?;
// Continue // Clone transaction
todo!() 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)
} }
} }

View file

@ -27,6 +27,14 @@ pub struct Table {
pub name: String, pub name: String,
} }
impl From<String> for Table {
fn from(v: String) -> Self {
Table {
name: v,
}
}
}
impl fmt::Display for Table { impl fmt::Display for Table {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", escape(&self.name, &val_char, "`")) write!(f, "{}", escape(&self.name, &val_char, "`"))