parent
2949ea7f4d
commit
7fabf54593
13 changed files with 353 additions and 33 deletions
|
@ -202,6 +202,10 @@ pub enum Error {
|
||||||
#[error("The scope token does not exist")]
|
#[error("The scope token does not exist")]
|
||||||
StNotFound,
|
StNotFound,
|
||||||
|
|
||||||
|
/// The requested param does not exist
|
||||||
|
#[error("The param does not exist")]
|
||||||
|
PaNotFound,
|
||||||
|
|
||||||
/// The requested table does not exist
|
/// The requested table does not exist
|
||||||
#[error("The table does not exist")]
|
#[error("The table does not exist")]
|
||||||
TbNotFound,
|
TbNotFound,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
/// DL /*{ns}*{db}!dl{us}
|
/// DL /*{ns}*{db}!dl{us}
|
||||||
/// DT /*{ns}*{db}!dt{tk}
|
/// DT /*{ns}*{db}!dt{tk}
|
||||||
/// SC /*{ns}*{db}!sc{sc}
|
/// SC /*{ns}*{db}!sc{sc}
|
||||||
|
/// PA /*{ns}*{db}!pa{pa}
|
||||||
/// TB /*{ns}*{db}!tb{tb}
|
/// TB /*{ns}*{db}!tb{tb}
|
||||||
/// LQ /*{ns}*{db}!lq{lq}
|
/// LQ /*{ns}*{db}!lq{lq}
|
||||||
///
|
///
|
||||||
|
@ -46,6 +47,7 @@ pub mod namespace;
|
||||||
pub mod nl;
|
pub mod nl;
|
||||||
pub mod ns;
|
pub mod ns;
|
||||||
pub mod nt;
|
pub mod nt;
|
||||||
|
pub mod pa;
|
||||||
pub mod sc;
|
pub mod sc;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
pub mod st;
|
pub mod st;
|
||||||
|
|
64
lib/src/key/pa.rs
Normal file
64
lib/src/key/pa.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use derive::Key;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)]
|
||||||
|
pub struct Pa {
|
||||||
|
__: u8,
|
||||||
|
_a: u8,
|
||||||
|
pub ns: String,
|
||||||
|
_b: u8,
|
||||||
|
pub db: String,
|
||||||
|
_c: u8,
|
||||||
|
_d: u8,
|
||||||
|
_e: u8,
|
||||||
|
pub pa: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(ns: &str, db: &str, pa: &str) -> Pa {
|
||||||
|
Pa::new(ns.to_string(), db.to_string(), pa.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prefix(ns: &str, db: &str) -> Vec<u8> {
|
||||||
|
let mut k = super::database::new(ns, db).encode().unwrap();
|
||||||
|
k.extend_from_slice(&[0x21, 0x70, 0x61, 0x00]);
|
||||||
|
k
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suffix(ns: &str, db: &str) -> Vec<u8> {
|
||||||
|
let mut k = super::database::new(ns, db).encode().unwrap();
|
||||||
|
k.extend_from_slice(&[0x21, 0x70, 0x61, 0xff]);
|
||||||
|
k
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pa {
|
||||||
|
pub fn new(ns: String, db: String, pa: String) -> Pa {
|
||||||
|
Pa {
|
||||||
|
__: 0x2f, // /
|
||||||
|
_a: 0x2a, // *
|
||||||
|
ns,
|
||||||
|
_b: 0x2a, // *
|
||||||
|
db,
|
||||||
|
_c: 0x21, // !
|
||||||
|
_d: 0x70, // p
|
||||||
|
_e: 0x61, // a
|
||||||
|
pa,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn key() {
|
||||||
|
use super::*;
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let val = Pa::new(
|
||||||
|
"test".to_string(),
|
||||||
|
"test".to_string(),
|
||||||
|
"test".to_string(),
|
||||||
|
);
|
||||||
|
let enc = Pa::encode(&val).unwrap();
|
||||||
|
let dec = Pa::decode(&enc).unwrap();
|
||||||
|
assert_eq!(val, dec);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ use crate::sql::statements::DefineFieldStatement;
|
||||||
use crate::sql::statements::DefineIndexStatement;
|
use crate::sql::statements::DefineIndexStatement;
|
||||||
use crate::sql::statements::DefineLoginStatement;
|
use crate::sql::statements::DefineLoginStatement;
|
||||||
use crate::sql::statements::DefineNamespaceStatement;
|
use crate::sql::statements::DefineNamespaceStatement;
|
||||||
|
use crate::sql::statements::DefineParamStatement;
|
||||||
use crate::sql::statements::DefineScopeStatement;
|
use crate::sql::statements::DefineScopeStatement;
|
||||||
use crate::sql::statements::DefineTableStatement;
|
use crate::sql::statements::DefineTableStatement;
|
||||||
use crate::sql::statements::DefineTokenStatement;
|
use crate::sql::statements::DefineTokenStatement;
|
||||||
|
@ -25,6 +26,7 @@ pub enum Entry {
|
||||||
Dts(Arc<[DefineTokenStatement]>),
|
Dts(Arc<[DefineTokenStatement]>),
|
||||||
Scs(Arc<[DefineScopeStatement]>),
|
Scs(Arc<[DefineScopeStatement]>),
|
||||||
Sts(Arc<[DefineTokenStatement]>),
|
Sts(Arc<[DefineTokenStatement]>),
|
||||||
|
Pas(Arc<[DefineParamStatement]>),
|
||||||
Tbs(Arc<[DefineTableStatement]>),
|
Tbs(Arc<[DefineTableStatement]>),
|
||||||
Evs(Arc<[DefineEventStatement]>),
|
Evs(Arc<[DefineEventStatement]>),
|
||||||
Fds(Arc<[DefineFieldStatement]>),
|
Fds(Arc<[DefineFieldStatement]>),
|
||||||
|
|
|
@ -16,6 +16,7 @@ use sql::statements::DefineFieldStatement;
|
||||||
use sql::statements::DefineIndexStatement;
|
use sql::statements::DefineIndexStatement;
|
||||||
use sql::statements::DefineLoginStatement;
|
use sql::statements::DefineLoginStatement;
|
||||||
use sql::statements::DefineNamespaceStatement;
|
use sql::statements::DefineNamespaceStatement;
|
||||||
|
use sql::statements::DefineParamStatement;
|
||||||
use sql::statements::DefineScopeStatement;
|
use sql::statements::DefineScopeStatement;
|
||||||
use sql::statements::DefineTableStatement;
|
use sql::statements::DefineTableStatement;
|
||||||
use sql::statements::DefineTokenStatement;
|
use sql::statements::DefineTokenStatement;
|
||||||
|
@ -812,6 +813,28 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Retrieve all scope definitions for a specific database.
|
||||||
|
pub async fn all_pa(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
) -> Result<Arc<[DefineParamStatement]>, Error> {
|
||||||
|
let key = crate::key::pa::prefix(ns, db);
|
||||||
|
match self.cache.exi(&key) {
|
||||||
|
true => match self.cache.get(&key) {
|
||||||
|
Some(Entry::Pas(v)) => Ok(v),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let beg = crate::key::pa::prefix(ns, db);
|
||||||
|
let end = crate::key::pa::suffix(ns, db);
|
||||||
|
let val = self.getr(beg..end, u32::MAX).await?;
|
||||||
|
let val = val.convert().into();
|
||||||
|
self.cache.set(key, Entry::Pas(Arc::clone(&val)));
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Retrieve all table definitions for a specific database.
|
/// Retrieve all table definitions for a specific database.
|
||||||
pub async fn all_tb(
|
pub async fn all_tb(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1018,6 +1041,17 @@ impl Transaction {
|
||||||
let val = self.get(key).await?.ok_or(Error::StNotFound)?;
|
let val = self.get(key).await?.ok_or(Error::StNotFound)?;
|
||||||
Ok(val.into())
|
Ok(val.into())
|
||||||
}
|
}
|
||||||
|
/// Retrieve a specific param definition.
|
||||||
|
pub async fn get_pa(
|
||||||
|
&mut self,
|
||||||
|
ns: &str,
|
||||||
|
db: &str,
|
||||||
|
pa: &str,
|
||||||
|
) -> Result<DefineParamStatement, Error> {
|
||||||
|
let key = crate::key::pa::new(ns, db, pa);
|
||||||
|
let val = self.get(key).await?.ok_or(Error::PaNotFound)?;
|
||||||
|
Ok(val.into())
|
||||||
|
}
|
||||||
/// Retrieve a specific table definition.
|
/// Retrieve a specific table definition.
|
||||||
pub async fn get_tb(
|
pub async fn get_tb(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1329,6 +1363,20 @@ impl Transaction {
|
||||||
chn.send(bytes!("")).await?;
|
chn.send(bytes!("")).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Output PARAMS
|
||||||
|
{
|
||||||
|
let pas = self.all_pa(ns, db).await?;
|
||||||
|
if !pas.is_empty() {
|
||||||
|
chn.send(bytes!("-- ------------------------------")).await?;
|
||||||
|
chn.send(bytes!("-- PARAMS")).await?;
|
||||||
|
chn.send(bytes!("-- ------------------------------")).await?;
|
||||||
|
chn.send(bytes!("")).await?;
|
||||||
|
for pa in pas.iter() {
|
||||||
|
chn.send(bytes!(format!("{};", pa))).await?;
|
||||||
|
}
|
||||||
|
chn.send(bytes!("")).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Output TABLES
|
// Output TABLES
|
||||||
{
|
{
|
||||||
let tbs = self.all_tb(ns, db).await?;
|
let tbs = self.all_tb(ns, db).await?;
|
||||||
|
|
|
@ -42,6 +42,7 @@ impl Param {
|
||||||
match self.first() {
|
match self.first() {
|
||||||
// The first part will be a field
|
// The first part will be a field
|
||||||
Some(Part::Field(v)) => match v.as_str() {
|
Some(Part::Field(v)) => match v.as_str() {
|
||||||
|
// This is a special param
|
||||||
"this" | "self" => match doc {
|
"this" | "self" => match doc {
|
||||||
// The base document exists
|
// The base document exists
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
|
@ -55,8 +56,9 @@ impl Param {
|
||||||
// The base document does not exist
|
// The base document does not exist
|
||||||
None => Ok(Value::None),
|
None => Ok(Value::None),
|
||||||
},
|
},
|
||||||
|
// This is a normal param
|
||||||
_ => match ctx.value(v) {
|
_ => match ctx.value(v) {
|
||||||
// The base variable exists
|
// The param has been set locally
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
// Get the path parts
|
// Get the path parts
|
||||||
let pth: &[Part] = self;
|
let pth: &[Part] = self;
|
||||||
|
@ -65,8 +67,22 @@ impl Param {
|
||||||
// Return the desired field
|
// Return the desired field
|
||||||
res.get(ctx, opt, txn, pth.next()).await
|
res.get(ctx, opt, txn, pth.next()).await
|
||||||
}
|
}
|
||||||
// The base variable does not exist
|
// The param has not been set locally
|
||||||
None => Ok(Value::None),
|
None => {
|
||||||
|
// Clone transaction
|
||||||
|
let run = txn.clone();
|
||||||
|
// Claim transaction
|
||||||
|
let mut run = run.lock().await;
|
||||||
|
// Get the param definition
|
||||||
|
let val = run.get_pa(opt.ns(), opt.db(), v).await;
|
||||||
|
// Check if the param has been set globally
|
||||||
|
match val {
|
||||||
|
// The param has been set globally
|
||||||
|
Ok(v) => Ok(v.value),
|
||||||
|
// The param has not been set globally
|
||||||
|
Err(_) => Ok(Value::None),
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -23,6 +23,7 @@ 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::character::complete::char;
|
||||||
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;
|
||||||
|
@ -40,6 +41,7 @@ pub enum DefineStatement {
|
||||||
Login(DefineLoginStatement),
|
Login(DefineLoginStatement),
|
||||||
Token(DefineTokenStatement),
|
Token(DefineTokenStatement),
|
||||||
Scope(DefineScopeStatement),
|
Scope(DefineScopeStatement),
|
||||||
|
Param(DefineParamStatement),
|
||||||
Table(DefineTableStatement),
|
Table(DefineTableStatement),
|
||||||
Event(DefineEventStatement),
|
Event(DefineEventStatement),
|
||||||
Field(DefineFieldStatement),
|
Field(DefineFieldStatement),
|
||||||
|
@ -60,6 +62,7 @@ impl DefineStatement {
|
||||||
Self::Login(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Login(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Token(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Token(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Scope(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Scope(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
Self::Param(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Table(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Table(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Event(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Event(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Field(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Field(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
@ -76,6 +79,7 @@ impl fmt::Display for DefineStatement {
|
||||||
Self::Login(v) => Display::fmt(v, f),
|
Self::Login(v) => Display::fmt(v, f),
|
||||||
Self::Token(v) => Display::fmt(v, f),
|
Self::Token(v) => Display::fmt(v, f),
|
||||||
Self::Scope(v) => Display::fmt(v, f),
|
Self::Scope(v) => Display::fmt(v, f),
|
||||||
|
Self::Param(v) => Display::fmt(v, f),
|
||||||
Self::Table(v) => Display::fmt(v, f),
|
Self::Table(v) => Display::fmt(v, f),
|
||||||
Self::Event(v) => Display::fmt(v, f),
|
Self::Event(v) => Display::fmt(v, f),
|
||||||
Self::Field(v) => Display::fmt(v, f),
|
Self::Field(v) => Display::fmt(v, f),
|
||||||
|
@ -91,6 +95,7 @@ pub fn define(i: &str) -> IResult<&str, DefineStatement> {
|
||||||
map(login, DefineStatement::Login),
|
map(login, DefineStatement::Login),
|
||||||
map(token, DefineStatement::Token),
|
map(token, DefineStatement::Token),
|
||||||
map(scope, DefineStatement::Scope),
|
map(scope, DefineStatement::Scope),
|
||||||
|
map(param, DefineStatement::Param),
|
||||||
map(table, DefineStatement::Table),
|
map(table, DefineStatement::Table),
|
||||||
map(event, DefineStatement::Event),
|
map(event, DefineStatement::Event),
|
||||||
map(field, DefineStatement::Field),
|
map(field, DefineStatement::Field),
|
||||||
|
@ -569,6 +574,68 @@ fn scope_signin(i: &str) -> IResult<&str, DefineScopeOption> {
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
||||||
|
pub struct DefineParamStatement {
|
||||||
|
pub name: Ident,
|
||||||
|
pub value: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefineParamStatement {
|
||||||
|
pub(crate) async fn compute(
|
||||||
|
&self,
|
||||||
|
_ctx: &Context<'_>,
|
||||||
|
opt: &Options,
|
||||||
|
txn: &Transaction,
|
||||||
|
_doc: Option<&Value>,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
// Selected DB?
|
||||||
|
opt.needs(Level::Db)?;
|
||||||
|
// Allowed to run?
|
||||||
|
opt.check(Level::Db)?;
|
||||||
|
// Clone transaction
|
||||||
|
let run = txn.clone();
|
||||||
|
// Claim transaction
|
||||||
|
let mut run = run.lock().await;
|
||||||
|
// Process the statement
|
||||||
|
let key = crate::key::pa::new(opt.ns(), opt.db(), &self.name);
|
||||||
|
run.add_ns(opt.ns(), opt.strict).await?;
|
||||||
|
run.add_db(opt.ns(), opt.db(), opt.strict).await?;
|
||||||
|
run.set(key, self).await?;
|
||||||
|
// Ok all good
|
||||||
|
Ok(Value::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DefineParamStatement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "DEFINE PARAM ${} VALUE {}", self.name, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param(i: &str) -> IResult<&str, DefineParamStatement> {
|
||||||
|
let (i, _) = tag_no_case("DEFINE")(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, _) = tag_no_case("PARAM")(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, _) = char('$')(i)?;
|
||||||
|
let (i, name) = ident(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, _) = tag_no_case("VALUE")(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, value) = value(i)?;
|
||||||
|
Ok((
|
||||||
|
i,
|
||||||
|
DefineParamStatement {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
||||||
pub struct DefineTableStatement {
|
pub struct DefineTableStatement {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
|
|
|
@ -70,18 +70,18 @@ impl InfoStatement {
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
}
|
}
|
||||||
res.insert("db".to_owned(), tmp.into());
|
res.insert("db".to_owned(), tmp.into());
|
||||||
// Process the tokens
|
|
||||||
let mut tmp = Object::default();
|
|
||||||
for v in run.all_nt(opt.ns()).await?.iter() {
|
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
|
||||||
}
|
|
||||||
res.insert("nt".to_owned(), tmp.into());
|
|
||||||
// Process the logins
|
// Process the logins
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_nl(opt.ns()).await?.iter() {
|
for v in run.all_nl(opt.ns()).await?.iter() {
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
}
|
}
|
||||||
res.insert("nl".to_owned(), tmp.into());
|
res.insert("nl".to_owned(), tmp.into());
|
||||||
|
// Process the tokens
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_nt(opt.ns()).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("nt".to_owned(), tmp.into());
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -96,30 +96,36 @@ impl InfoStatement {
|
||||||
let mut run = run.lock().await;
|
let mut run = run.lock().await;
|
||||||
// Create the result set
|
// Create the result set
|
||||||
let mut res = Object::default();
|
let mut res = Object::default();
|
||||||
// Process the tables
|
|
||||||
let mut tmp = Object::default();
|
|
||||||
for v in run.all_tb(opt.ns(), opt.db()).await?.iter() {
|
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
|
||||||
}
|
|
||||||
res.insert("tb".to_owned(), tmp.into());
|
|
||||||
// Process the scopes
|
|
||||||
let mut tmp = Object::default();
|
|
||||||
for v in run.all_sc(opt.ns(), opt.db()).await?.iter() {
|
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
|
||||||
}
|
|
||||||
res.insert("sc".to_owned(), tmp.into());
|
|
||||||
// Process the tokens
|
|
||||||
let mut tmp = Object::default();
|
|
||||||
for v in run.all_dt(opt.ns(), opt.db()).await?.iter() {
|
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
|
||||||
}
|
|
||||||
res.insert("dt".to_owned(), tmp.into());
|
|
||||||
// Process the logins
|
// Process the logins
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_dl(opt.ns(), opt.db()).await?.iter() {
|
for v in run.all_dl(opt.ns(), opt.db()).await?.iter() {
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
}
|
}
|
||||||
res.insert("dl".to_owned(), tmp.into());
|
res.insert("dl".to_owned(), tmp.into());
|
||||||
|
// Process the tokens
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_dt(opt.ns(), opt.db()).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("dt".to_owned(), tmp.into());
|
||||||
|
// Process the params
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_pa(opt.ns(), opt.db()).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("pa".to_owned(), tmp.into());
|
||||||
|
// Process the scopes
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_sc(opt.ns(), opt.db()).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("sc".to_owned(), tmp.into());
|
||||||
|
// Process the tables
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_tb(opt.ns(), opt.db()).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("tb".to_owned(), tmp.into());
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
@ -166,18 +172,18 @@ impl InfoStatement {
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
}
|
}
|
||||||
res.insert("fd".to_owned(), tmp.into());
|
res.insert("fd".to_owned(), tmp.into());
|
||||||
// Process the indexes
|
|
||||||
let mut tmp = Object::default();
|
|
||||||
for v in run.all_ix(opt.ns(), opt.db(), tb).await?.iter() {
|
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
|
||||||
}
|
|
||||||
res.insert("ix".to_owned(), tmp.into());
|
|
||||||
// Process the tables
|
// Process the tables
|
||||||
let mut tmp = Object::default();
|
let mut tmp = Object::default();
|
||||||
for v in run.all_ft(opt.ns(), opt.db(), tb).await?.iter() {
|
for v in run.all_ft(opt.ns(), opt.db(), tb).await?.iter() {
|
||||||
tmp.insert(v.name.to_string(), v.to_string().into());
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
}
|
}
|
||||||
res.insert("ft".to_owned(), tmp.into());
|
res.insert("ft".to_owned(), tmp.into());
|
||||||
|
// Process the indexes
|
||||||
|
let mut tmp = Object::default();
|
||||||
|
for v in run.all_ix(opt.ns(), opt.db(), tb).await?.iter() {
|
||||||
|
tmp.insert(v.name.to_string(), v.to_string().into());
|
||||||
|
}
|
||||||
|
res.insert("ix".to_owned(), tmp.into());
|
||||||
// Ok all good
|
// Ok all good
|
||||||
Value::from(res).ok()
|
Value::from(res).ok()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub use self::define::DefineIndexStatement;
|
||||||
pub use self::define::DefineLoginOption;
|
pub use self::define::DefineLoginOption;
|
||||||
pub use self::define::DefineLoginStatement;
|
pub use self::define::DefineLoginStatement;
|
||||||
pub use self::define::DefineNamespaceStatement;
|
pub use self::define::DefineNamespaceStatement;
|
||||||
|
pub use self::define::DefineParamStatement;
|
||||||
pub use self::define::DefineScopeOption;
|
pub use self::define::DefineScopeOption;
|
||||||
pub use self::define::DefineScopeStatement;
|
pub use self::define::DefineScopeStatement;
|
||||||
pub use self::define::DefineStatement;
|
pub use self::define::DefineStatement;
|
||||||
|
@ -57,6 +58,7 @@ pub use self::remove::RemoveFieldStatement;
|
||||||
pub use self::remove::RemoveIndexStatement;
|
pub use self::remove::RemoveIndexStatement;
|
||||||
pub use self::remove::RemoveLoginStatement;
|
pub use self::remove::RemoveLoginStatement;
|
||||||
pub use self::remove::RemoveNamespaceStatement;
|
pub use self::remove::RemoveNamespaceStatement;
|
||||||
|
pub use self::remove::RemoveParamStatement;
|
||||||
pub use self::remove::RemoveScopeStatement;
|
pub use self::remove::RemoveScopeStatement;
|
||||||
pub use self::remove::RemoveStatement;
|
pub use self::remove::RemoveStatement;
|
||||||
pub use self::remove::RemoveTableStatement;
|
pub use self::remove::RemoveTableStatement;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::sql::value::Value;
|
||||||
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::character::complete::char;
|
||||||
use nom::combinator::{map, opt};
|
use nom::combinator::{map, opt};
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -25,6 +26,7 @@ pub enum RemoveStatement {
|
||||||
Login(RemoveLoginStatement),
|
Login(RemoveLoginStatement),
|
||||||
Token(RemoveTokenStatement),
|
Token(RemoveTokenStatement),
|
||||||
Scope(RemoveScopeStatement),
|
Scope(RemoveScopeStatement),
|
||||||
|
Param(RemoveParamStatement),
|
||||||
Table(RemoveTableStatement),
|
Table(RemoveTableStatement),
|
||||||
Event(RemoveEventStatement),
|
Event(RemoveEventStatement),
|
||||||
Field(RemoveFieldStatement),
|
Field(RemoveFieldStatement),
|
||||||
|
@ -45,6 +47,7 @@ impl RemoveStatement {
|
||||||
Self::Login(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Login(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Token(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Token(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Scope(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Scope(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
Self::Param(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Table(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Table(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Event(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Event(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Self::Field(ref v) => v.compute(ctx, opt, txn, doc).await,
|
Self::Field(ref v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
@ -61,6 +64,7 @@ impl Display for RemoveStatement {
|
||||||
Self::Login(v) => Display::fmt(v, f),
|
Self::Login(v) => Display::fmt(v, f),
|
||||||
Self::Token(v) => Display::fmt(v, f),
|
Self::Token(v) => Display::fmt(v, f),
|
||||||
Self::Scope(v) => Display::fmt(v, f),
|
Self::Scope(v) => Display::fmt(v, f),
|
||||||
|
Self::Param(v) => Display::fmt(v, f),
|
||||||
Self::Table(v) => Display::fmt(v, f),
|
Self::Table(v) => Display::fmt(v, f),
|
||||||
Self::Event(v) => Display::fmt(v, f),
|
Self::Event(v) => Display::fmt(v, f),
|
||||||
Self::Field(v) => Display::fmt(v, f),
|
Self::Field(v) => Display::fmt(v, f),
|
||||||
|
@ -76,6 +80,7 @@ pub fn remove(i: &str) -> IResult<&str, RemoveStatement> {
|
||||||
map(login, RemoveStatement::Login),
|
map(login, RemoveStatement::Login),
|
||||||
map(token, RemoveStatement::Token),
|
map(token, RemoveStatement::Token),
|
||||||
map(scope, RemoveStatement::Scope),
|
map(scope, RemoveStatement::Scope),
|
||||||
|
map(param, RemoveStatement::Param),
|
||||||
map(table, RemoveStatement::Table),
|
map(table, RemoveStatement::Table),
|
||||||
map(event, RemoveStatement::Event),
|
map(event, RemoveStatement::Event),
|
||||||
map(field, RemoveStatement::Field),
|
map(field, RemoveStatement::Field),
|
||||||
|
@ -428,6 +433,60 @@ fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> {
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
||||||
|
pub struct RemoveParamStatement {
|
||||||
|
pub name: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemoveParamStatement {
|
||||||
|
pub(crate) async fn compute(
|
||||||
|
&self,
|
||||||
|
_ctx: &Context<'_>,
|
||||||
|
opt: &Options,
|
||||||
|
txn: &Transaction,
|
||||||
|
_doc: Option<&Value>,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
// Selected DB?
|
||||||
|
opt.needs(Level::Db)?;
|
||||||
|
// Allowed to run?
|
||||||
|
opt.check(Level::Db)?;
|
||||||
|
// Clone transaction
|
||||||
|
let run = txn.clone();
|
||||||
|
// Claim transaction
|
||||||
|
let mut run = run.lock().await;
|
||||||
|
// Delete the definition
|
||||||
|
let key = crate::key::pa::new(opt.ns(), opt.db(), &self.name);
|
||||||
|
run.del(key).await?;
|
||||||
|
// Ok all good
|
||||||
|
Ok(Value::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RemoveParamStatement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "REMOVE PARAM {}", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param(i: &str) -> IResult<&str, RemoveParamStatement> {
|
||||||
|
let (i, _) = tag_no_case("REMOVE")(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, _) = tag_no_case("PARAM")(i)?;
|
||||||
|
let (i, _) = shouldbespace(i)?;
|
||||||
|
let (i, _) = char('$')(i)?;
|
||||||
|
let (i, name) = ident(i)?;
|
||||||
|
Ok((
|
||||||
|
i,
|
||||||
|
RemoveParamStatement {
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store, Hash)]
|
||||||
pub struct RemoveTableStatement {
|
pub struct RemoveTableStatement {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
|
|
|
@ -76,6 +76,9 @@ async fn define_statement_table_drop() -> Result<(), Error> {
|
||||||
"{
|
"{
|
||||||
dl: {},
|
dl: {},
|
||||||
dt: {},
|
dt: {},
|
||||||
|
pa: {},
|
||||||
|
sc: {},
|
||||||
|
pa: {},
|
||||||
sc: {},
|
sc: {},
|
||||||
tb: { test: 'DEFINE TABLE test DROP SCHEMALESS' },
|
tb: { test: 'DEFINE TABLE test DROP SCHEMALESS' },
|
||||||
}",
|
}",
|
||||||
|
@ -104,6 +107,7 @@ async fn define_statement_table_schemaless() -> Result<(), Error> {
|
||||||
"{
|
"{
|
||||||
dl: {},
|
dl: {},
|
||||||
dt: {},
|
dt: {},
|
||||||
|
pa: {},
|
||||||
sc: {},
|
sc: {},
|
||||||
tb: { test: 'DEFINE TABLE test SCHEMALESS' },
|
tb: { test: 'DEFINE TABLE test SCHEMALESS' },
|
||||||
}",
|
}",
|
||||||
|
@ -136,6 +140,7 @@ async fn define_statement_table_schemafull() -> Result<(), Error> {
|
||||||
"{
|
"{
|
||||||
dl: {},
|
dl: {},
|
||||||
dt: {},
|
dt: {},
|
||||||
|
pa: {},
|
||||||
sc: {},
|
sc: {},
|
||||||
tb: { test: 'DEFINE TABLE test SCHEMAFULL' },
|
tb: { test: 'DEFINE TABLE test SCHEMAFULL' },
|
||||||
}",
|
}",
|
||||||
|
@ -164,6 +169,7 @@ async fn define_statement_table_schemaful() -> Result<(), Error> {
|
||||||
"{
|
"{
|
||||||
dl: {},
|
dl: {},
|
||||||
dt: {},
|
dt: {},
|
||||||
|
pa: {},
|
||||||
sc: {},
|
sc: {},
|
||||||
tb: { test: 'DEFINE TABLE test SCHEMAFULL' },
|
tb: { test: 'DEFINE TABLE test SCHEMAFULL' },
|
||||||
}",
|
}",
|
||||||
|
|
|
@ -5,6 +5,49 @@ use surrealdb::err::Error;
|
||||||
use surrealdb::kvs::Datastore;
|
use surrealdb::kvs::Datastore;
|
||||||
use surrealdb::sql::Value;
|
use surrealdb::sql::Value;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn define_global_param() -> Result<(), Error> {
|
||||||
|
let sql = "
|
||||||
|
DEFINE PARAM $test VALUE 12345;
|
||||||
|
INFO FOR DB;
|
||||||
|
SELECT * FROM $test;
|
||||||
|
LET $test = 56789;
|
||||||
|
SELECT * FROM $test;
|
||||||
|
";
|
||||||
|
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, false).await?;
|
||||||
|
assert_eq!(res.len(), 5);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result;
|
||||||
|
assert!(tmp.is_ok());
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result?;
|
||||||
|
let val = Value::parse(
|
||||||
|
"{
|
||||||
|
dl: {},
|
||||||
|
dt: {},
|
||||||
|
pa: { test: 'DEFINE PARAM $test VALUE 12345' },
|
||||||
|
sc: {},
|
||||||
|
tb: {},
|
||||||
|
}",
|
||||||
|
);
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result?;
|
||||||
|
let val = Value::parse("[12345]");
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result;
|
||||||
|
assert!(tmp.is_ok());
|
||||||
|
//
|
||||||
|
let tmp = res.remove(0).result?;
|
||||||
|
let val = Value::parse("[56789]");
|
||||||
|
assert_eq!(tmp, val);
|
||||||
|
//
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn define_protected_param() -> Result<(), Error> {
|
async fn define_protected_param() -> Result<(), Error> {
|
||||||
let sql = "
|
let sql = "
|
||||||
|
|
|
@ -192,6 +192,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
||||||
"{
|
"{
|
||||||
dl: {},
|
dl: {},
|
||||||
dt: {},
|
dt: {},
|
||||||
|
pa: {},
|
||||||
sc: {},
|
sc: {},
|
||||||
tb: { test: 'DEFINE TABLE test SCHEMALESS PERMISSIONS NONE' },
|
tb: { test: 'DEFINE TABLE test SCHEMALESS PERMISSIONS NONE' },
|
||||||
}",
|
}",
|
||||||
|
|
Loading…
Reference in a new issue