Implement initial logic for DEFINE statements
This commit is contained in:
parent
2a0d46a2b6
commit
0f6d700f6b
5 changed files with 660 additions and 53 deletions
279
lib/src/kvs/ex.rs
Normal file
279
lib/src/kvs/ex.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod ex;
|
||||||
mod file;
|
mod file;
|
||||||
mod ixdb;
|
mod ixdb;
|
||||||
mod kv;
|
mod kv;
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, "`"))
|
||||||
|
|
Loading…
Reference in a new issue