Convert all processing code to async

This commit is contained in:
Tobie Morgan Hitchcock 2022-01-14 08:12:56 +00:00
parent db9960fcbe
commit 3126251a65
41 changed files with 1092 additions and 963 deletions

View file

@ -19,7 +19,7 @@ pub async fn execute(txt: &str, session: Session, vars: Variables) -> Result<Res
// Process all statements // Process all statements
exe.ns = session.ns; exe.ns = session.ns;
exe.db = session.db; exe.db = session.db;
exe.execute(ctx, ast) exe.execute(ctx, ast).await
} }
pub async fn process(ast: Query, session: Session, vars: Variables) -> Result<Responses, Error> { pub async fn process(ast: Query, session: Session, vars: Variables) -> Result<Responses, Error> {
@ -30,7 +30,7 @@ pub async fn process(ast: Query, session: Session, vars: Variables) -> Result<Re
// Process all statements // Process all statements
exe.ns = session.ns; exe.ns = session.ns;
exe.db = session.db; exe.db = session.db;
exe.execute(ctx, ast) exe.execute(ctx, ast).await
} }
pub fn export(session: Session) -> Result<String, Error> { pub fn export(session: Session) -> Result<String, Error> {

View file

@ -3,7 +3,6 @@ use crate::dbs::response::{Response, Responses};
use crate::dbs::Auth; use crate::dbs::Auth;
use crate::dbs::Level; use crate::dbs::Level;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error; use crate::err::Error;
use crate::sql::query::Query; use crate::sql::query::Query;
@ -47,7 +46,7 @@ impl Executor {
todo!() todo!()
} }
pub fn execute(&mut self, mut ctx: Runtime, qry: Query) -> Result<Responses, Error> { pub async fn execute(&mut self, mut ctx: Runtime, qry: Query) -> Result<Responses, Error> {
// Initialise array of responses // Initialise array of responses
let mut out: Vec<Response> = vec![]; let mut out: Vec<Response> = vec![];
// Create a new options // Create a new options
@ -75,25 +74,25 @@ impl Executor {
} }
// Begin a new transaction // Begin a new transaction
Statement::Begin(stm) => { Statement::Begin(stm) => {
let res = stm.process(&ctx, &opt, self, None); let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err(); self.err = res.err();
continue; continue;
} }
// Cancel a running transaction // Cancel a running transaction
Statement::Cancel(stm) => { Statement::Cancel(stm) => {
let res = stm.process(&ctx, &opt, self, None); let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err(); self.err = res.err();
continue; continue;
} }
// Commit a running transaction // Commit a running transaction
Statement::Commit(stm) => { Statement::Commit(stm) => {
let res = stm.process(&ctx, &opt, self, None); let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err(); self.err = res.err();
continue; continue;
} }
// Process param definition statements // Process param definition statements
Statement::Set(stm) => { Statement::Set(stm) => {
match stm.process(&ctx, &opt, self, None) { match stm.compute(&ctx, &opt, self, None).await {
Ok(val) => { Ok(val) => {
let mut new = Context::new(&ctx); let mut new = Context::new(&ctx);
let key = stm.name.to_owned(); let key = stm.name.to_owned();
@ -115,7 +114,7 @@ impl Executor {
ctx = new.freeze(); ctx = new.freeze();
} }
// Process statement // Process statement
let res = stm.process(&ctx, &opt, self, None); let res = stm.compute(&ctx, &opt, self, None).await;
// Catch statement timeout // Catch statement timeout
if let Some(timeout) = stm.timeout() { if let Some(timeout) = stm.timeout() {
if ctx.is_timedout() { if ctx.is_timedout() {

View file

@ -3,7 +3,6 @@ mod dbs;
mod executor; mod executor;
mod iterator; mod iterator;
mod options; mod options;
mod process;
mod response; mod response;
mod runtime; mod runtime;
mod session; mod session;
@ -13,7 +12,6 @@ pub use self::dbs::*;
pub use self::executor::*; pub use self::executor::*;
pub use self::iterator::*; pub use self::iterator::*;
pub use self::options::*; pub use self::options::*;
pub use self::process::*;
pub use self::response::*; pub use self::response::*;
pub use self::runtime::*; pub use self::runtime::*;
pub use self::session::*; pub use self::session::*;

View file

@ -1,15 +0,0 @@
use crate::dbs::executor::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::value::Value;
pub trait Process {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error>;
}

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -92,6 +91,27 @@ impl Array {
} }
} }
impl Array {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
let mut x = Vec::new();
for v in &self.value {
match v.compute(ctx, opt, exe, doc).await {
Ok(v) => x.push(v),
Err(e) => return Err(e),
};
}
Ok(Value::Array(Array {
value: x,
}))
}
}
impl fmt::Display for Array { impl fmt::Display for Array {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
@ -102,29 +122,6 @@ impl fmt::Display for Array {
} }
} }
impl dbs::Process for Array {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
self.value
.iter()
.map(|v| match v.process(ctx, opt, exe, doc) {
Ok(v) => Ok(v),
Err(e) => Err(e),
})
.collect::<Result<Vec<_>, _>>()
.map(|v| {
Value::Array(Array {
value: v,
})
})
}
}
impl Serialize for Array { impl Serialize for Array {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@ -190,6 +187,38 @@ impl ops::Sub for Array {
// ------------------------------ // ------------------------------
pub trait Abolish<T> {
fn abolish<F>(&mut self, f: F)
where
F: FnMut(usize) -> bool;
}
impl<T> Abolish<T> for Vec<T> {
fn abolish<F>(&mut self, mut f: F)
where
F: FnMut(usize) -> bool,
{
let len = self.len();
let mut del = 0;
{
let v = &mut **self;
for i in 0..len {
if f(i) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
}
}
// ------------------------------
pub trait Uniq<T> { pub trait Uniq<T> {
fn uniq(self) -> Vec<T>; fn uniq(self) -> Vec<T>;
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -28,21 +27,15 @@ impl Default for Expression {
} }
} }
impl fmt::Display for Expression { impl Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "{} {} {}", self.l, self.o, self.r)
}
}
impl dbs::Process for Expression {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
let l = self.l.process(ctx, opt, exe, doc)?; let l = self.l.compute(ctx, opt, exe, doc).await?;
match self.o { match self.o {
Operator::Or => match l.is_truthy() { Operator::Or => match l.is_truthy() {
true => return Ok(l), // No need to continue true => return Ok(l), // No need to continue
@ -54,7 +47,7 @@ impl dbs::Process for Expression {
}, },
_ => {} // Continue _ => {} // Continue
} }
let r = self.r.process(ctx, opt, exe, doc)?; let r = self.r.compute(ctx, opt, exe, doc).await?;
match self.o { match self.o {
Operator::Or => fnc::operate::or(l, r), Operator::Or => fnc::operate::or(l, r),
Operator::And => fnc::operate::and(l, r), Operator::And => fnc::operate::and(l, r),
@ -91,6 +84,12 @@ impl dbs::Process for Expression {
} }
} }
impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {} {}", self.l, self.o, self.r)
}
}
pub fn expression(i: &str) -> IResult<&str, Expression> { pub fn expression(i: &str) -> IResult<&str, Expression> {
let (i, l) = single(i)?; let (i, l) = single(i)?;
let (i, o) = operator(i)?; let (i, o) = operator(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -31,6 +30,42 @@ impl PartialOrd for Function {
} }
} }
impl Function {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
Function::Future(ref e) => match opt.futures {
true => {
let a = e.compute(ctx, opt, exe, doc).await?;
fnc::future::run(ctx, a)
}
false => Ok(self.to_owned().into()),
},
Function::Script(ref s) => {
let a = s.to_owned();
fnc::script::run(ctx, a)
}
Function::Cast(ref s, ref e) => {
let a = e.compute(ctx, opt, exe, doc).await?;
fnc::cast::run(ctx, s, a)
}
Function::Normal(ref s, ref e) => {
let mut a: Vec<Value> = vec![];
for v in e {
let v = v.compute(ctx, opt, exe, doc).await?;
a.push(v);
}
fnc::run(ctx, s, a)
}
}
}
}
impl fmt::Display for Function { impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -47,42 +82,6 @@ impl fmt::Display for Function {
} }
} }
impl dbs::Process for Function {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
Function::Future(ref e) => match opt.futures {
true => {
let a = e.process(ctx, opt, exe, doc)?;
fnc::future::run(ctx, a)
}
false => Ok(self.to_owned().into()),
},
Function::Script(ref s) => {
let a = s.to_owned();
fnc::script::run(ctx, a)
}
Function::Cast(ref s, ref e) => {
let a = e.process(ctx, opt, exe, doc)?;
fnc::cast::run(ctx, s, a)
}
Function::Normal(ref s, ref e) => {
let mut a: Vec<Value> = vec![];
for v in e {
let v = v.process(ctx, opt, exe, doc)?;
a.push(v);
}
fnc::run(ctx, s, a)
}
}
}
}
pub fn function(i: &str) -> IResult<&str, Function> { pub fn function(i: &str) -> IResult<&str, Function> {
alt((casts, langs, future, normal))(i) alt((casts, langs, future, normal))(i)
} }
@ -397,7 +396,7 @@ mod tests {
let res = function(sql); let res = function(sql);
assert!(res.is_ok()); assert!(res.is_ok());
let out = res.unwrap().1; let out = res.unwrap().1;
assert_eq!("<int>1.2345", format!("{}", out)); assert_eq!("<int> 1.2345", format!("{}", out));
assert_eq!(out, Function::Cast(String::from("int"), 1.2345.into())); assert_eq!(out, Function::Cast(String::from("int"), 1.2345.into()));
} }
@ -407,7 +406,7 @@ mod tests {
let res = function(sql); let res = function(sql);
assert!(res.is_ok()); assert!(res.is_ok());
let out = res.unwrap().1; let out = res.unwrap().1;
assert_eq!("<string>1.2345", format!("{}", out)); assert_eq!("<string> 1.2345", format!("{}", out));
assert_eq!(out, Function::Cast(String::from("string"), 1.2345.into())); assert_eq!(out, Function::Cast(String::from("string"), 1.2345.into()));
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -50,6 +49,23 @@ impl Idiom {
} }
} }
impl Idiom {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match doc {
// There is a current document
Some(v) => v.get(ctx, opt, exe, self).await.ok(),
// There isn't any document
None => Ok(Value::None),
}
}
}
impl fmt::Display for Idiom { impl fmt::Display for Idiom {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
@ -68,23 +84,6 @@ impl fmt::Display for Idiom {
} }
} }
impl dbs::Process for Idiom {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match doc {
// There is a current document
Some(v) => v.get(ctx, opt, exe, self).ok(),
// There isn't any document
None => Ok(Value::None),
}
}
}
// Used in a DEFINE FIELD and DEFINE INDEX clause // Used in a DEFINE FIELD and DEFINE INDEX clause
pub fn local(i: &str) -> IResult<&str, Idiom> { pub fn local(i: &str) -> IResult<&str, Idiom> {
let (i, p) = first(i)?; let (i, p) = first(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -53,6 +52,27 @@ impl Object {
} }
} }
impl Object {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
let mut x = BTreeMap::new();
for (k, v) in &self.value {
match v.compute(ctx, opt, exe, doc).await {
Ok(v) => x.insert(k.clone(), v),
Err(e) => return Err(e),
};
}
Ok(Value::Object(Object {
value: x,
}))
}
}
impl fmt::Display for Object { impl fmt::Display for Object {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
@ -67,29 +87,6 @@ impl fmt::Display for Object {
} }
} }
impl dbs::Process for Object {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
self.value
.iter()
.map(|(k, v)| match v.process(ctx, opt, exe, doc) {
Ok(v) => Ok((k.clone(), v)),
Err(e) => Err(e),
})
.collect::<Result<BTreeMap<_, _>, _>>()
.map(|v| {
Value::Object(Object {
value: v,
})
})
}
}
impl Serialize for Object { impl Serialize for Object {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -26,17 +25,11 @@ impl From<Idiom> for Param {
} }
} }
impl fmt::Display for Param { impl Param {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "${}", &self.name)
}
}
impl dbs::Process for Param {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -47,9 +40,9 @@ impl dbs::Process for Param {
// The base variable exists // The base variable exists
Some(v) => { Some(v) => {
// Process the paramater value // Process the paramater value
let res = v.process(ctx, opt, exe, doc)?; let res = v.compute(ctx, opt, exe, doc).await?;
// Return the desired field // Return the desired field
res.get(ctx, opt, exe, &self.name.next()).ok() res.get(ctx, opt, exe, &self.name.next()).await.ok()
} }
// The base variable does not exist // The base variable does not exist
None => Ok(Value::None), None => Ok(Value::None),
@ -59,6 +52,12 @@ impl dbs::Process for Param {
} }
} }
impl fmt::Display for Param {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "${}", &self.name)
}
}
pub fn param(i: &str) -> IResult<&str, Param> { pub fn param(i: &str) -> IResult<&str, Param> {
let (i, _) = tag("$")(i)?; let (i, _) = tag("$")(i)?;
let (i, v) = idiom::param(i)?; let (i, v) = idiom::param(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -111,6 +110,38 @@ impl Statement {
} }
} }
impl Statement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match *self {
Statement::Use(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Set(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Info(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Live(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Kill(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Begin(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Cancel(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Commit(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Output(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Ifelse(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Select(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Create(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Update(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Relate(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Delete(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Insert(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Define(ref v) => v.compute(ctx, opt, exe, doc).await,
Statement::Remove(ref v) => v.compute(ctx, opt, exe, doc).await,
_ => unreachable!(),
}
}
}
impl fmt::Display for Statement { impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -137,38 +168,6 @@ impl fmt::Display for Statement {
} }
} }
impl dbs::Process for Statement {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match *self {
Statement::Use(ref v) => v.process(ctx, opt, exe, doc),
Statement::Set(ref v) => v.process(ctx, opt, exe, doc),
Statement::Info(ref v) => v.process(ctx, opt, exe, doc),
Statement::Live(ref v) => v.process(ctx, opt, exe, doc),
Statement::Kill(ref v) => v.process(ctx, opt, exe, doc),
Statement::Begin(ref v) => v.process(ctx, opt, exe, doc),
Statement::Cancel(ref v) => v.process(ctx, opt, exe, doc),
Statement::Commit(ref v) => v.process(ctx, opt, exe, doc),
Statement::Output(ref v) => v.process(ctx, opt, exe, doc),
Statement::Ifelse(ref v) => v.process(ctx, opt, exe, doc),
Statement::Select(ref v) => v.process(ctx, opt, exe, doc),
Statement::Create(ref v) => v.process(ctx, opt, exe, doc),
Statement::Update(ref v) => v.process(ctx, opt, exe, doc),
Statement::Relate(ref v) => v.process(ctx, opt, exe, doc),
Statement::Delete(ref v) => v.process(ctx, opt, exe, doc),
Statement::Insert(ref v) => v.process(ctx, opt, exe, doc),
Statement::Define(ref v) => v.process(ctx, opt, exe, doc),
Statement::Remove(ref v) => v.process(ctx, opt, exe, doc),
_ => unreachable!(),
}
}
}
pub fn statement(i: &str) -> IResult<&str, Statement> { pub fn statement(i: &str) -> IResult<&str, Statement> {
delimited( delimited(
mightbespace, mightbespace,

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -16,17 +15,11 @@ use std::fmt;
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct BeginStatement; pub struct BeginStatement;
impl fmt::Display for BeginStatement { impl BeginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "BEGIN TRANSACTION")
}
}
impl dbs::Process for BeginStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
_opt: &Options, _opt: &Options<'_>,
_exe: &mut Executor, _exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -34,6 +27,12 @@ impl dbs::Process for BeginStatement {
} }
} }
impl fmt::Display for BeginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "BEGIN TRANSACTION")
}
}
pub fn begin(i: &str) -> IResult<&str, BeginStatement> { pub fn begin(i: &str) -> IResult<&str, BeginStatement> {
alt((begin_query, begin_basic))(i) alt((begin_query, begin_basic))(i)
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -16,17 +15,11 @@ use std::fmt;
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct CancelStatement; pub struct CancelStatement;
impl fmt::Display for CancelStatement { impl CancelStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "CANCEL TRANSACTION")
}
}
impl dbs::Process for CancelStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
_opt: &Options, _opt: &Options<'_>,
_exe: &mut Executor, _exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -34,6 +27,12 @@ impl dbs::Process for CancelStatement {
} }
} }
impl fmt::Display for CancelStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CANCEL TRANSACTION")
}
}
pub fn cancel(i: &str) -> IResult<&str, CancelStatement> { pub fn cancel(i: &str) -> IResult<&str, CancelStatement> {
alt((cancel_query, cancel_basic))(i) alt((cancel_query, cancel_basic))(i)
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -16,17 +15,11 @@ use std::fmt;
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct CommitStatement; pub struct CommitStatement;
impl fmt::Display for CommitStatement { impl CommitStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "COMMIT TRANSACTION")
}
}
impl dbs::Process for CommitStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
_opt: &Options, _opt: &Options<'_>,
_exe: &mut Executor, _exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -34,6 +27,12 @@ impl dbs::Process for CommitStatement {
} }
} }
impl fmt::Display for CommitStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "COMMIT TRANSACTION")
}
}
pub fn commit(i: &str) -> IResult<&str, CommitStatement> { pub fn commit(i: &str) -> IResult<&str, CommitStatement> {
alt((commit_query, commit_basic))(i) alt((commit_query, commit_basic))(i)
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -28,27 +27,11 @@ pub struct CreateStatement {
pub timeout: Option<Timeout>, pub timeout: Option<Timeout>,
} }
impl fmt::Display for CreateStatement { impl CreateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "CREATE {}", self.what)?;
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
impl dbs::Process for CreateStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -62,7 +45,7 @@ impl dbs::Process for CreateStatement {
let opt = &opt.futures(false); let opt = &opt.futures(false);
// Loop over the create targets // Loop over the create targets
for w in self.what.0.iter() { for w in self.what.0.iter() {
match w.process(ctx, opt, exe, doc)? { match w.compute(ctx, opt, exe, doc).await? {
Value::Table(v) => { Value::Table(v) => {
i.process_table(ctx, exe, v); i.process_table(ctx, exe, v);
} }
@ -90,6 +73,22 @@ impl dbs::Process for CreateStatement {
} }
} }
impl fmt::Display for CreateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CREATE {}", self.what)?;
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
pub fn create(i: &str) -> IResult<&str, CreateStatement> { pub fn create(i: &str) -> IResult<&str, CreateStatement> {
let (i, _) = tag_no_case("CREATE")(i)?; let (i, _) = tag_no_case("CREATE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Level; use crate::dbs::Level;
use crate::dbs::Options; use crate::dbs::Options;
@ -38,6 +37,28 @@ pub enum DefineStatement {
Index(DefineIndexStatement), Index(DefineIndexStatement),
} }
impl DefineStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
DefineStatement::Namespace(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Database(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Login(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Token(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Scope(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Table(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Event(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Field(ref v) => v.compute(ctx, opt, exe, doc).await,
DefineStatement::Index(ref v) => v.compute(ctx, opt, exe, doc).await,
}
}
}
impl fmt::Display for DefineStatement { impl fmt::Display for DefineStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -54,28 +75,6 @@ impl fmt::Display for DefineStatement {
} }
} }
impl dbs::Process for DefineStatement {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
DefineStatement::Namespace(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Database(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Login(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Token(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Scope(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Table(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Event(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Field(ref v) => v.process(ctx, opt, exe, doc),
DefineStatement::Index(ref v) => v.process(ctx, opt, exe, doc),
}
}
}
pub fn define(i: &str) -> IResult<&str, DefineStatement> { pub fn define(i: &str) -> IResult<&str, DefineStatement> {
alt(( alt((
map(namespace, |v| DefineStatement::Namespace(v)), map(namespace, |v| DefineStatement::Namespace(v)),
@ -99,17 +98,11 @@ pub struct DefineNamespaceStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for DefineNamespaceStatement { impl DefineNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "DEFINE NAMESPACE {}", self.name)
}
}
impl dbs::Process for DefineNamespaceStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -120,6 +113,12 @@ impl dbs::Process for DefineNamespaceStatement {
} }
} }
impl fmt::Display for DefineNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE NAMESPACE {}", self.name)
}
}
fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> { fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -143,17 +142,11 @@ pub struct DefineDatabaseStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for DefineDatabaseStatement { impl DefineDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "DEFINE DATABASE {}", self.name)
}
}
impl dbs::Process for DefineDatabaseStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -164,6 +157,12 @@ impl dbs::Process for DefineDatabaseStatement {
} }
} }
impl fmt::Display for DefineDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE DATABASE {}", self.name)
}
}
fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> { fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -192,24 +191,11 @@ pub struct DefineLoginStatement {
pub hash: Option<String>, pub hash: Option<String>,
} }
impl fmt::Display for DefineLoginStatement { impl DefineLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
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(())
}
}
impl dbs::Process for DefineLoginStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -224,6 +210,19 @@ impl dbs::Process for DefineLoginStatement {
} }
} }
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(())
}
}
fn login(i: &str) -> IResult<&str, DefineLoginStatement> { fn login(i: &str) -> IResult<&str, DefineLoginStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -290,21 +289,11 @@ pub struct DefineTokenStatement {
pub code: String, pub code: String,
} }
impl fmt::Display for DefineTokenStatement { impl DefineTokenStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(
f,
"DEFINE TOKEN {} ON {} TYPE {} VALUE {}",
self.name, self.base, self.kind, self.code
)
}
}
impl dbs::Process for DefineTokenStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -319,6 +308,16 @@ impl dbs::Process for DefineTokenStatement {
} }
} }
impl fmt::Display for DefineTokenStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"DEFINE TOKEN {} ON {} TYPE {} VALUE {}",
self.name, self.base, self.kind, self.code
)
}
}
fn token(i: &str) -> IResult<&str, DefineTokenStatement> { fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -365,6 +364,21 @@ pub struct DefineScopeStatement {
pub connect: Option<Value>, pub connect: Option<Value>,
} }
impl DefineScopeStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
impl fmt::Display for DefineScopeStatement { impl fmt::Display for DefineScopeStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE SCOPE {}", self.name)?; write!(f, "DEFINE SCOPE {}", self.name)?;
@ -384,21 +398,6 @@ impl fmt::Display for DefineScopeStatement {
} }
} }
impl dbs::Process for DefineScopeStatement {
fn process(
&self,
_ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
fn scope(i: &str) -> IResult<&str, DefineScopeStatement> { fn scope(i: &str) -> IResult<&str, DefineScopeStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -488,6 +487,21 @@ pub struct DefineTableStatement {
pub permissions: Permissions, pub permissions: Permissions,
} }
impl DefineTableStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
impl fmt::Display for DefineTableStatement { impl fmt::Display for DefineTableStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE TABLE {}", self.name)?; write!(f, "DEFINE TABLE {}", self.name)?;
@ -508,21 +522,6 @@ impl fmt::Display for DefineTableStatement {
} }
} }
impl dbs::Process for DefineTableStatement {
fn process(
&self,
_ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
fn table(i: &str) -> IResult<&str, DefineTableStatement> { fn table(i: &str) -> IResult<&str, DefineTableStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -619,21 +618,11 @@ pub struct DefineEventStatement {
pub then: Values, pub then: Values,
} }
impl fmt::Display for DefineEventStatement { impl DefineEventStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(
f,
"DEFINE EVENT {} ON {} WHEN {} THEN {}",
self.name, self.what, self.when, self.then
)
}
}
impl dbs::Process for DefineEventStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -644,6 +633,16 @@ impl dbs::Process for DefineEventStatement {
} }
} }
impl fmt::Display for DefineEventStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"DEFINE EVENT {} ON {} WHEN {} THEN {}",
self.name, self.what, self.when, self.then
)
}
}
fn event(i: &str) -> IResult<&str, DefineEventStatement> { fn event(i: &str) -> IResult<&str, DefineEventStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -693,6 +692,21 @@ pub struct DefineFieldStatement {
pub permissions: Permissions, pub permissions: Permissions,
} }
impl DefineFieldStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
impl fmt::Display for DefineFieldStatement { impl fmt::Display for DefineFieldStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE FIELD {} ON {}", self.name, self.what)?; write!(f, "DEFINE FIELD {} ON {}", self.name, self.what)?;
@ -710,21 +724,6 @@ impl fmt::Display for DefineFieldStatement {
} }
} }
impl dbs::Process for DefineFieldStatement {
fn process(
&self,
_ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::Db)?;
// Continue
todo!()
}
}
fn field(i: &str) -> IResult<&str, DefineFieldStatement> { fn field(i: &str) -> IResult<&str, DefineFieldStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -832,21 +831,11 @@ pub struct DefineIndexStatement {
pub uniq: bool, pub uniq: bool,
} }
impl fmt::Display for DefineIndexStatement { impl DefineIndexStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "DEFINE INDEX {} ON {} COLUMNS {}", self.name, self.what, self.cols)?;
if self.uniq == true {
write!(f, " UNIQUE")?
}
Ok(())
}
}
impl dbs::Process for DefineIndexStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -857,6 +846,16 @@ impl dbs::Process for DefineIndexStatement {
} }
} }
impl fmt::Display for DefineIndexStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE INDEX {} ON {} COLUMNS {}", self.name, self.what, self.cols)?;
if self.uniq == true {
write!(f, " UNIQUE")?
}
Ok(())
}
}
fn index(i: &str) -> IResult<&str, DefineIndexStatement> { fn index(i: &str) -> IResult<&str, DefineIndexStatement> {
let (i, _) = tag_no_case("DEFINE")(i)?; let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -29,27 +28,11 @@ pub struct DeleteStatement {
pub timeout: Option<Timeout>, pub timeout: Option<Timeout>,
} }
impl fmt::Display for DeleteStatement { impl DeleteStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "DELETE {}", self.what)?;
if let Some(ref v) = self.cond {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
impl dbs::Process for DeleteStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -63,7 +46,7 @@ impl dbs::Process for DeleteStatement {
let opt = &opt.futures(false); let opt = &opt.futures(false);
// Loop over the delete targets // Loop over the delete targets
for w in self.what.0.iter() { for w in self.what.0.iter() {
match w.process(ctx, opt, exe, doc)? { match w.compute(ctx, opt, exe, doc).await? {
Value::Table(v) => { Value::Table(v) => {
i.process_table(ctx, exe, v); i.process_table(ctx, exe, v);
} }
@ -91,6 +74,22 @@ impl dbs::Process for DeleteStatement {
} }
} }
impl fmt::Display for DeleteStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DELETE {}", self.what)?;
if let Some(ref v) = self.cond {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
pub fn delete(i: &str) -> IResult<&str, DeleteStatement> { pub fn delete(i: &str) -> IResult<&str, DeleteStatement> {
let (i, _) = tag_no_case("DELETE")(i)?; let (i, _) = tag_no_case("DELETE")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("FROM"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("FROM"))))(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -19,6 +18,27 @@ pub struct IfelseStatement {
pub close: Option<Value>, pub close: Option<Value>,
} }
impl IfelseStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
for (ref cond, ref then) in &self.exprs {
let v = cond.compute(ctx, opt, exe, doc).await?;
if v.is_truthy() {
return then.compute(ctx, opt, exe, doc).await;
}
}
match self.close {
Some(ref v) => v.compute(ctx, opt, exe, doc).await,
None => Ok(Value::None),
}
}
}
impl fmt::Display for IfelseStatement { impl fmt::Display for IfelseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
@ -38,27 +58,6 @@ impl fmt::Display for IfelseStatement {
} }
} }
impl dbs::Process for IfelseStatement {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
for (ref cond, ref then) in &self.exprs {
let v = cond.process(ctx, opt, exe, doc)?;
if v.is_truthy() {
return then.process(ctx, opt, exe, doc);
}
}
match self.close {
Some(ref v) => v.process(ctx, opt, exe, doc),
None => Ok(Value::None),
}
}
}
pub fn ifelse(i: &str) -> IResult<&str, IfelseStatement> { pub fn ifelse(i: &str) -> IResult<&str, IfelseStatement> {
let (i, exprs) = separated_list0(split, exprs)(i)?; let (i, exprs) = separated_list0(split, exprs)(i)?;
let (i, close) = opt(close)(i)?; let (i, close) = opt(close)(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Level; use crate::dbs::Level;
use crate::dbs::Options; use crate::dbs::Options;
@ -21,22 +20,11 @@ pub enum InfoStatement {
Table(String), Table(String),
} }
impl fmt::Display for InfoStatement { impl InfoStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
match self {
InfoStatement::Namespace => write!(f, "INFO FOR NAMESPACE"),
InfoStatement::Database => write!(f, "INFO FOR DATABASE"),
InfoStatement::Scope(ref s) => write!(f, "INFO FOR SCOPE {}", s),
InfoStatement::Table(ref t) => write!(f, "INFO FOR TABLE {}", t),
}
}
}
impl dbs::Process for InfoStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -52,6 +40,17 @@ impl dbs::Process for InfoStatement {
} }
} }
impl fmt::Display for InfoStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InfoStatement::Namespace => write!(f, "INFO FOR NAMESPACE"),
InfoStatement::Database => write!(f, "INFO FOR DATABASE"),
InfoStatement::Scope(ref s) => write!(f, "INFO FOR SCOPE {}", s),
InfoStatement::Table(ref t) => write!(f, "INFO FOR TABLE {}", t),
}
}
}
pub fn info(i: &str) -> IResult<&str, InfoStatement> { pub fn info(i: &str) -> IResult<&str, InfoStatement> {
let (i, _) = tag_no_case("INFO")(i)?; let (i, _) = tag_no_case("INFO")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -32,28 +31,11 @@ pub struct InsertStatement {
pub timeout: Option<Timeout>, pub timeout: Option<Timeout>,
} }
impl fmt::Display for InsertStatement { impl InsertStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "INSERT")?;
if self.ignore {
write!(f, " IGNORE")?
}
write!(f, " INTO {} {}", self.into, self.data)?;
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
impl dbs::Process for InsertStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -71,7 +53,7 @@ impl dbs::Process for InsertStatement {
Data::ValuesExpression(_) => { Data::ValuesExpression(_) => {
todo!() // TODO: loop over each todo!() // TODO: loop over each
} }
Data::SingleExpression(v) => match v.process(ctx, opt, exe, doc)? { Data::SingleExpression(v) => match v.compute(ctx, opt, exe, doc).await? {
Value::Array(v) => { Value::Array(v) => {
i.process_array(ctx, exe, v); i.process_array(ctx, exe, v);
} }
@ -91,6 +73,23 @@ impl dbs::Process for InsertStatement {
} }
} }
impl fmt::Display for InsertStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "INSERT")?;
if self.ignore {
write!(f, " IGNORE")?
}
write!(f, " INTO {} {}", self.into, self.data)?;
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
pub fn insert(i: &str) -> IResult<&str, InsertStatement> { pub fn insert(i: &str) -> IResult<&str, InsertStatement> {
let (i, _) = tag_no_case("INSERT")(i)?; let (i, _) = tag_no_case("INSERT")(i)?;
let (i, ignore) = opt(preceded(shouldbespace, tag_no_case("IGNORE")))(i)?; let (i, ignore) = opt(preceded(shouldbespace, tag_no_case("IGNORE")))(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -16,17 +15,11 @@ pub struct KillStatement {
pub id: Ident, pub id: Ident,
} }
impl fmt::Display for KillStatement { impl KillStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "KILL {}", self.id)
}
}
impl dbs::Process for KillStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
_opt: &Options, _opt: &Options<'_>,
_exe: &mut Executor, _exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -34,6 +27,12 @@ impl dbs::Process for KillStatement {
} }
} }
impl fmt::Display for KillStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "KILL {}", self.id)
}
}
pub fn kill(i: &str) -> IResult<&str, KillStatement> { pub fn kill(i: &str) -> IResult<&str, KillStatement> {
let (i, _) = tag_no_case("KILL")(i)?; let (i, _) = tag_no_case("KILL")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -26,6 +25,18 @@ pub struct LiveStatement {
pub fetch: Option<Fetchs>, pub fetch: Option<Fetchs>,
} }
impl LiveStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
_opt: &Options<'_>,
_exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
todo!()
}
}
impl fmt::Display for LiveStatement { impl fmt::Display for LiveStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "LIVE SELECT {} FROM {}", self.expr, self.what)?; write!(f, "LIVE SELECT {} FROM {}", self.expr, self.what)?;
@ -39,18 +50,6 @@ impl fmt::Display for LiveStatement {
} }
} }
impl dbs::Process for LiveStatement {
fn process(
&self,
_ctx: &Runtime,
_opt: &Options,
_exe: &mut Executor,
_doc: Option<&Value>,
) -> Result<Value, Error> {
todo!()
}
}
pub fn live(i: &str) -> IResult<&str, LiveStatement> { pub fn live(i: &str) -> IResult<&str, LiveStatement> {
let (i, _) = tag_no_case("LIVE SELECT")(i)?; let (i, _) = tag_no_case("LIVE SELECT")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Level; use crate::dbs::Level;
use crate::dbs::Options; use crate::dbs::Options;
@ -23,21 +22,11 @@ pub struct OptionStatement {
pub what: bool, pub what: bool,
} }
impl fmt::Display for OptionStatement { impl OptionStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
if self.what {
write!(f, "OPTION {}", self.name)
} else {
write!(f, "OPTION {} = FALSE", self.name)
}
}
}
impl dbs::Process for OptionStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -48,6 +37,16 @@ impl dbs::Process for OptionStatement {
} }
} }
impl fmt::Display for OptionStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.what {
write!(f, "OPTION {}", self.name)
} else {
write!(f, "OPTION {} = FALSE", self.name)
}
}
}
pub fn option(i: &str) -> IResult<&str, OptionStatement> { pub fn option(i: &str) -> IResult<&str, OptionStatement> {
let (i, _) = tag_no_case("OPTION")(i)?; let (i, _) = tag_no_case("OPTION")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -15,24 +14,24 @@ pub struct OutputStatement {
pub what: Value, pub what: Value,
} }
impl fmt::Display for OutputStatement { impl OutputStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "RETURN {}", self.what)
}
}
impl dbs::Process for OutputStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
// Ensure futures are processed // Ensure futures are processed
let opt = &opt.futures(true); let opt = &opt.futures(true);
// Process the output value // Process the output value
self.what.process(ctx, opt, exe, doc) self.what.compute(ctx, opt, exe, doc).await
}
}
impl fmt::Display for OutputStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "RETURN {}", self.what)
} }
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -35,30 +34,11 @@ pub struct RelateStatement {
pub timeout: Option<Timeout>, pub timeout: Option<Timeout>,
} }
impl fmt::Display for RelateStatement { impl RelateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "RELATE {} -> {} -> {}", self.from, self.kind, self.with)?;
if self.uniq {
write!(f, " UNIQUE")?
}
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
impl dbs::Process for RelateStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -70,7 +50,7 @@ impl dbs::Process for RelateStatement {
let opt = &opt.futures(false); let opt = &opt.futures(false);
// Loop over the select targets // Loop over the select targets
for f in self.from.0.iter() { for f in self.from.0.iter() {
match f.process(ctx, opt, exe, doc)? { match f.compute(ctx, opt, exe, doc).await? {
Value::Table(v) => { Value::Table(v) => {
i.process_table(ctx, exe, v); i.process_table(ctx, exe, v);
} }
@ -98,6 +78,25 @@ impl dbs::Process for RelateStatement {
} }
} }
impl fmt::Display for RelateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "RELATE {} -> {} -> {}", self.from, self.kind, self.with)?;
if self.uniq {
write!(f, " UNIQUE")?
}
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
pub fn relate(i: &str) -> IResult<&str, RelateStatement> { pub fn relate(i: &str) -> IResult<&str, RelateStatement> {
let (i, _) = tag_no_case("RELATE")(i)?; let (i, _) = tag_no_case("RELATE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Level; use crate::dbs::Level;
use crate::dbs::Options; use crate::dbs::Options;
@ -29,6 +28,28 @@ pub enum RemoveStatement {
Index(RemoveIndexStatement), Index(RemoveIndexStatement),
} }
impl RemoveStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
RemoveStatement::Namespace(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Database(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Login(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Token(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Scope(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Table(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Event(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Field(ref v) => v.compute(ctx, opt, exe, doc).await,
RemoveStatement::Index(ref v) => v.compute(ctx, opt, exe, doc).await,
}
}
}
impl fmt::Display for RemoveStatement { impl fmt::Display for RemoveStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -45,28 +66,6 @@ impl fmt::Display for RemoveStatement {
} }
} }
impl dbs::Process for RemoveStatement {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
match self {
RemoveStatement::Namespace(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Database(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Login(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Token(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Scope(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Table(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Event(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Field(ref v) => v.process(ctx, opt, exe, doc),
RemoveStatement::Index(ref v) => v.process(ctx, opt, exe, doc),
}
}
}
pub fn remove(i: &str) -> IResult<&str, RemoveStatement> { pub fn remove(i: &str) -> IResult<&str, RemoveStatement> {
alt(( alt((
map(namespace, |v| RemoveStatement::Namespace(v)), map(namespace, |v| RemoveStatement::Namespace(v)),
@ -90,17 +89,11 @@ pub struct RemoveNamespaceStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for RemoveNamespaceStatement { impl RemoveNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE NAMESPACE {}", self.name)
}
}
impl dbs::Process for RemoveNamespaceStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -111,6 +104,12 @@ impl dbs::Process for RemoveNamespaceStatement {
} }
} }
impl fmt::Display for RemoveNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE NAMESPACE {}", self.name)
}
}
fn namespace(i: &str) -> IResult<&str, RemoveNamespaceStatement> { fn namespace(i: &str) -> IResult<&str, RemoveNamespaceStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -134,17 +133,11 @@ pub struct RemoveDatabaseStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for RemoveDatabaseStatement { impl RemoveDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE DATABASE {}", self.name)
}
}
impl dbs::Process for RemoveDatabaseStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -155,6 +148,12 @@ impl dbs::Process for RemoveDatabaseStatement {
} }
} }
impl fmt::Display for RemoveDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE DATABASE {}", self.name)
}
}
fn database(i: &str) -> IResult<&str, RemoveDatabaseStatement> { fn database(i: &str) -> IResult<&str, RemoveDatabaseStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -179,17 +178,11 @@ pub struct RemoveLoginStatement {
pub base: Base, pub base: Base,
} }
impl fmt::Display for RemoveLoginStatement { impl RemoveLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE LOGIN {} ON {}", self.name, self.base)
}
}
impl dbs::Process for RemoveLoginStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -204,6 +197,12 @@ impl dbs::Process for RemoveLoginStatement {
} }
} }
impl fmt::Display for RemoveLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE LOGIN {} ON {}", self.name, self.base)
}
}
fn login(i: &str) -> IResult<&str, RemoveLoginStatement> { fn login(i: &str) -> IResult<&str, RemoveLoginStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -233,17 +232,11 @@ pub struct RemoveTokenStatement {
pub base: Base, pub base: Base,
} }
impl fmt::Display for RemoveTokenStatement { impl RemoveTokenStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE TOKEN {} ON {}", self.name, self.base)
}
}
impl dbs::Process for RemoveTokenStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -258,6 +251,12 @@ impl dbs::Process for RemoveTokenStatement {
} }
} }
impl fmt::Display for RemoveTokenStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE TOKEN {} ON {}", self.name, self.base)
}
}
fn token(i: &str) -> IResult<&str, RemoveTokenStatement> { fn token(i: &str) -> IResult<&str, RemoveTokenStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -286,17 +285,11 @@ pub struct RemoveScopeStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for RemoveScopeStatement { impl RemoveScopeStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE SCOPE {}", self.name)
}
}
impl dbs::Process for RemoveScopeStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -307,6 +300,12 @@ impl dbs::Process for RemoveScopeStatement {
} }
} }
impl fmt::Display for RemoveScopeStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE SCOPE {}", self.name)
}
}
fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> { fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -330,17 +329,11 @@ pub struct RemoveTableStatement {
pub name: String, pub name: String,
} }
impl fmt::Display for RemoveTableStatement { impl RemoveTableStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE TABLE {}", self.name)
}
}
impl dbs::Process for RemoveTableStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -351,6 +344,12 @@ impl dbs::Process for RemoveTableStatement {
} }
} }
impl fmt::Display for RemoveTableStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE TABLE {}", self.name)
}
}
fn table(i: &str) -> IResult<&str, RemoveTableStatement> { fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -375,17 +374,11 @@ pub struct RemoveEventStatement {
pub what: String, pub what: String,
} }
impl fmt::Display for RemoveEventStatement { impl RemoveEventStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE EVENT {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveEventStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -396,6 +389,12 @@ impl dbs::Process for RemoveEventStatement {
} }
} }
impl fmt::Display for RemoveEventStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE EVENT {} ON {}", self.name, self.what)
}
}
fn event(i: &str) -> IResult<&str, RemoveEventStatement> { fn event(i: &str) -> IResult<&str, RemoveEventStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -426,17 +425,11 @@ pub struct RemoveFieldStatement {
pub what: String, pub what: String,
} }
impl fmt::Display for RemoveFieldStatement { impl RemoveFieldStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE FIELD {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveFieldStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -447,6 +440,12 @@ impl dbs::Process for RemoveFieldStatement {
} }
} }
impl fmt::Display for RemoveFieldStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE FIELD {} ON {}", self.name, self.what)
}
}
fn field(i: &str) -> IResult<&str, RemoveFieldStatement> { fn field(i: &str) -> IResult<&str, RemoveFieldStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -477,17 +476,11 @@ pub struct RemoveIndexStatement {
pub what: String, pub what: String,
} }
impl fmt::Display for RemoveIndexStatement { impl RemoveIndexStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "REMOVE INDEX {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveIndexStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -498,6 +491,12 @@ impl dbs::Process for RemoveIndexStatement {
} }
} }
impl fmt::Display for RemoveIndexStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE INDEX {} ON {}", self.name, self.what)
}
}
fn index(i: &str) -> IResult<&str, RemoveIndexStatement> { fn index(i: &str) -> IResult<&str, RemoveIndexStatement> {
let (i, _) = tag_no_case("REMOVE")(i)?; let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -63,6 +62,58 @@ impl SelectStatement {
} }
} }
impl SelectStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::No)?;
// Create a new iterator
let mut i = Iterator::new();
// Pass in statement config
i.expr = Some(&self.expr);
i.cond = self.cond.as_ref();
i.split = self.split.as_ref();
i.group = self.group.as_ref();
i.order = self.order.as_ref();
i.limit = self.limit.as_ref();
i.start = self.start.as_ref();
// Ensure futures are processed
let opt = &opt.futures(true);
// Specify the document version
let opt = &opt.version(self.version.as_ref());
// Loop over the select targets
for w in self.what.0.iter() {
match w.compute(ctx, opt, exe, doc).await? {
Value::Table(v) => {
i.process_table(ctx, exe, v);
}
Value::Thing(v) => {
i.process_thing(ctx, exe, v);
}
Value::Model(v) => {
i.process_model(ctx, exe, v);
}
Value::Array(v) => {
i.process_array(ctx, exe, v);
}
Value::Object(v) => {
i.process_object(ctx, exe, v);
}
v => {
i.process_value(ctx, exe, v);
}
};
}
// Output the results
i.output(ctx, exe)
}
}
impl fmt::Display for SelectStatement { impl fmt::Display for SelectStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SELECT {} FROM {}", self.expr, self.what)?; write!(f, "SELECT {} FROM {}", self.expr, self.what)?;
@ -97,58 +148,6 @@ impl fmt::Display for SelectStatement {
} }
} }
impl dbs::Process for SelectStatement {
fn process(
&self,
ctx: &Runtime,
opt: &Options,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
// Allowed to run?
exe.check(opt, Level::No)?;
// Create a new iterator
let mut i = Iterator::new();
// Pass in statement config
i.expr = Some(&self.expr);
i.cond = self.cond.as_ref();
i.split = self.split.as_ref();
i.group = self.group.as_ref();
i.order = self.order.as_ref();
i.limit = self.limit.as_ref();
i.start = self.start.as_ref();
// Ensure futures are processed
let opt = &opt.futures(true);
// Specify the document version
let opt = &opt.version(self.version.as_ref());
// Loop over the select targets
for w in self.what.0.iter() {
match w.process(ctx, opt, exe, doc)? {
Value::Table(v) => {
i.process_table(ctx, exe, v);
}
Value::Thing(v) => {
i.process_thing(ctx, exe, v);
}
Value::Model(v) => {
i.process_model(ctx, exe, v);
}
Value::Array(v) => {
i.process_array(ctx, exe, v);
}
Value::Object(v) => {
i.process_object(ctx, exe, v);
}
v => {
i.process_value(ctx, exe, v);
}
};
}
// Output the results
i.output(ctx, exe)
}
}
pub fn select(i: &str) -> IResult<&str, SelectStatement> { pub fn select(i: &str) -> IResult<&str, SelectStatement> {
let (i, _) = tag_no_case("SELECT")(i)?; let (i, _) = tag_no_case("SELECT")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -20,21 +19,21 @@ pub struct SetStatement {
pub what: Value, pub what: Value,
} }
impl fmt::Display for SetStatement { impl SetStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "LET ${} = {}", self.name, self.what)
}
}
impl dbs::Process for SetStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
self.what.process(ctx, opt, exe, doc) self.what.compute(ctx, opt, exe, doc).await
}
}
impl fmt::Display for SetStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "LET ${} = {}", self.name, self.what)
} }
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Iterator; use crate::dbs::Iterator;
use crate::dbs::Level; use crate::dbs::Level;
@ -31,30 +30,11 @@ pub struct UpdateStatement {
pub timeout: Option<Timeout>, pub timeout: Option<Timeout>,
} }
impl fmt::Display for UpdateStatement { impl UpdateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "UPDATE {}", self.what)?;
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.cond {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
impl dbs::Process for UpdateStatement {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -69,7 +49,7 @@ impl dbs::Process for UpdateStatement {
let opt = &opt.futures(false); let opt = &opt.futures(false);
// Loop over the update targets // Loop over the update targets
for w in self.what.0.iter() { for w in self.what.0.iter() {
match w.process(ctx, opt, exe, doc)? { match w.compute(ctx, opt, exe, doc).await? {
Value::Table(v) => { Value::Table(v) => {
i.process_table(ctx, exe, v); i.process_table(ctx, exe, v);
} }
@ -97,6 +77,25 @@ impl dbs::Process for UpdateStatement {
} }
} }
impl fmt::Display for UpdateStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UPDATE {}", self.what)?;
if let Some(ref v) = self.data {
write!(f, " {}", v)?
}
if let Some(ref v) = self.cond {
write!(f, " {}", v)?
}
if let Some(ref v) = self.output {
write!(f, " {}", v)?
}
if let Some(ref v) = self.timeout {
write!(f, " {}", v)?
}
Ok(())
}
}
pub fn update(i: &str) -> IResult<&str, UpdateStatement> { pub fn update(i: &str) -> IResult<&str, UpdateStatement> {
let (i, _) = tag_no_case("UPDATE")(i)?; let (i, _) = tag_no_case("UPDATE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Auth; use crate::dbs::Auth;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
@ -21,24 +20,11 @@ pub struct UseStatement {
pub db: Option<String>, pub db: Option<String>,
} }
impl fmt::Display for UseStatement { impl UseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
write!(f, "USE")?;
if let Some(ref ns) = self.ns {
write!(f, " NS {}", ns)?;
}
if let Some(ref db) = self.db {
write!(f, " DB {}", db)?;
}
Ok(())
}
}
impl dbs::Process for UseStatement {
fn process(
&self, &self,
_ctx: &Runtime, _ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
_doc: Option<&Value>, _doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
@ -73,6 +59,19 @@ impl dbs::Process for UseStatement {
} }
} }
impl fmt::Display for UseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "USE")?;
if let Some(ref ns) = self.ns {
write!(f, " NS {}", ns)?;
}
if let Some(ref db) = self.db {
write!(f, " DB {}", db)?;
}
Ok(())
}
}
pub fn yuse(i: &str) -> IResult<&str, UseStatement> { pub fn yuse(i: &str) -> IResult<&str, UseStatement> {
alt((both, ns, db))(i) alt((both, ns, db))(i)
} }

View file

@ -1,5 +1,4 @@
use crate::ctx::Context; use crate::ctx::Context;
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -39,32 +38,17 @@ impl PartialOrd for Subquery {
} }
} }
impl fmt::Display for Subquery { impl Subquery {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub async fn compute(
match self {
Subquery::Value(v) => write!(f, "({})", v),
Subquery::Select(v) => write!(f, "({})", v),
Subquery::Create(v) => write!(f, "({})", v),
Subquery::Update(v) => write!(f, "({})", v),
Subquery::Delete(v) => write!(f, "({})", v),
Subquery::Relate(v) => write!(f, "({})", v),
Subquery::Insert(v) => write!(f, "({})", v),
Subquery::Ifelse(v) => write!(f, "{}", v),
}
}
}
impl dbs::Process for Subquery {
fn process(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
match self { match self {
Subquery::Value(ref v) => v.process(ctx, opt, exe, doc), Subquery::Value(ref v) => v.compute(ctx, opt, exe, doc).await,
Subquery::Ifelse(ref v) => v.process(ctx, opt, exe, doc), Subquery::Ifelse(ref v) => v.compute(ctx, opt, exe, doc).await,
Subquery::Select(ref v) => { Subquery::Select(ref v) => {
// Duplicate options // Duplicate options
let opt = opt.dive()?; let opt = opt.dive()?;
@ -78,15 +62,17 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
let res = v.process(&ctx, &opt, exe, doc)?; let res = v.compute(&ctx, &opt, exe, doc).await?;
// Process result // Process result
match v.limit() { match v.limit() {
1 => match v.expr.single() { 1 => match v.expr.single() {
Some(v) => res.first(&ctx, &opt, exe).get(&ctx, &opt, exe, &v).ok(), Some(v) => {
None => res.first(&ctx, &opt, exe).ok(), res.first(&ctx, &opt, exe).await.get(&ctx, &opt, exe, &v).await.ok()
}
None => res.first(&ctx, &opt, exe).await.ok(),
}, },
_ => match v.expr.single() { _ => match v.expr.single() {
Some(v) => res.get(&ctx, &opt, exe, &v).ok(), Some(v) => res.get(&ctx, &opt, exe, &v).await.ok(),
None => res.ok(), None => res.ok(),
}, },
} }
@ -104,7 +90,7 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
match v.process(&ctx, &opt, exe, doc)? { match v.compute(&ctx, &opt, exe, doc).await? {
Value::Array(mut v) => match v.len() { Value::Array(mut v) => match v.len() {
1 => Ok(v.value.remove(0)), 1 => Ok(v.value.remove(0)),
_ => Ok(v.into()), _ => Ok(v.into()),
@ -125,7 +111,7 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
match v.process(&ctx, &opt, exe, doc)? { match v.compute(&ctx, &opt, exe, doc).await? {
Value::Array(mut v) => match v.len() { Value::Array(mut v) => match v.len() {
1 => Ok(v.value.remove(0)), 1 => Ok(v.value.remove(0)),
_ => Ok(v.into()), _ => Ok(v.into()),
@ -146,7 +132,7 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
match v.process(&ctx, &opt, exe, doc)? { match v.compute(&ctx, &opt, exe, doc).await? {
Value::Array(mut v) => match v.len() { Value::Array(mut v) => match v.len() {
1 => Ok(v.value.remove(0)), 1 => Ok(v.value.remove(0)),
_ => Ok(v.into()), _ => Ok(v.into()),
@ -167,7 +153,7 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
match v.process(&ctx, &opt, exe, doc)? { match v.compute(&ctx, &opt, exe, doc).await? {
Value::Array(mut v) => match v.len() { Value::Array(mut v) => match v.len() {
1 => Ok(v.value.remove(0)), 1 => Ok(v.value.remove(0)),
_ => Ok(v.into()), _ => Ok(v.into()),
@ -188,7 +174,7 @@ impl dbs::Process for Subquery {
// Prepare context // Prepare context
let ctx = ctx.freeze(); let ctx = ctx.freeze();
// Process subquery // Process subquery
match v.process(&ctx, &opt, exe, doc)? { match v.compute(&ctx, &opt, exe, doc).await? {
Value::Array(mut v) => match v.len() { Value::Array(mut v) => match v.len() {
1 => Ok(v.value.remove(0)), 1 => Ok(v.value.remove(0)),
_ => Ok(v.into()), _ => Ok(v.into()),
@ -200,6 +186,21 @@ impl dbs::Process for Subquery {
} }
} }
impl fmt::Display for Subquery {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Subquery::Value(v) => write!(f, "({})", v),
Subquery::Select(v) => write!(f, "({})", v),
Subquery::Create(v) => write!(f, "({})", v),
Subquery::Update(v) => write!(f, "({})", v),
Subquery::Delete(v) => write!(f, "({})", v),
Subquery::Relate(v) => write!(f, "({})", v),
Subquery::Insert(v) => write!(f, "({})", v),
Subquery::Ifelse(v) => write!(f, "{}", v),
}
}
}
pub fn subquery(i: &str) -> IResult<&str, Subquery> { pub fn subquery(i: &str) -> IResult<&str, Subquery> {
alt((subquery_ifelse, subquery_others))(i) alt((subquery_ifelse, subquery_others))(i)
} }

View file

@ -6,8 +6,14 @@ use crate::sql::idiom::Idiom;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn array(&mut self, ctx: &Runtime, opt: &Options, exe: &mut Executor, path: &Idiom) { pub async fn array(
&mut self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
) {
let val = Value::from(Array::default()); let val = Value::from(Array::default());
self.set(ctx, opt, exe, path, Value::from(val)) self.set(ctx, opt, exe, path, Value::from(val)).await
} }
} }

View file

@ -6,25 +6,37 @@ use crate::sql::number::Number;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn decrement( pub async fn decrement(
&mut self, &mut self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
) { ) {
match self.get(ctx, opt, exe, path) { match self.get(ctx, opt, exe, path).await {
Value::Number(v) => match val { Value::Number(v) => match val {
Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(v - x)), Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(v - x)).await;
()
}
_ => (), _ => (),
}, },
Value::Array(v) => match val { Value::Array(v) => match val {
Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(v - x)), Value::Array(x) => {
x => self.set(ctx, opt, exe, path, Value::from(v - x)), self.set(ctx, opt, exe, path, Value::from(v - x)).await;
()
}
x => {
self.set(ctx, opt, exe, path, Value::from(v - x)).await;
()
}
}, },
Value::None => match val { Value::None => match val {
Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(Number::from(0) - x)), Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(Number::from(0) - x)).await;
()
}
_ => (), _ => (),
}, },
_ => (), _ => (),
@ -39,53 +51,53 @@ mod tests {
use crate::dbs::test::mock; use crate::dbs::test::mock;
use crate::sql::test::Parse; use crate::sql::test::Parse;
#[test] #[tokio::test]
fn dec_none() { async fn dec_none() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("other"); let idi = Idiom::parse("other");
let mut val = Value::parse("{ test: 100 }"); let mut val = Value::parse("{ test: 100 }");
let res = Value::parse("{ test: 100, other: -10 }"); let res = Value::parse("{ test: 100, other: -10 }");
val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn dec_number() { async fn dec_number() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: 100 }"); let mut val = Value::parse("{ test: 100 }");
let res = Value::parse("{ test: 90 }"); let res = Value::parse("{ test: 90 }");
val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn dec_array_number() { async fn dec_array_number() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test[1]"); let idi = Idiom::parse("test[1]");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [100, 190, 300] }"); let res = Value::parse("{ test: [100, 190, 300] }");
val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn dec_array_value() { async fn dec_array_value() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [100, 300] }"); let res = Value::parse("{ test: [100, 300] }");
val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(200)); val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(200)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn dec_array_array() { async fn dec_array_array() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [200] }"); let res = Value::parse("{ test: [200] }");
val.decrement(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300]")); val.decrement(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300]")).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -1,13 +1,22 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::sql::array::Abolish;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::part::Part; use crate::sql::part::Part;
use crate::sql::value::Value; use crate::sql::value::Value;
use async_recursion::async_recursion;
use std::collections::HashMap;
impl Value { impl Value {
pub fn del(&mut self, ctx: &Runtime, opt: &Options, exe: &mut Executor, path: &Idiom) { #[async_recursion]
pub async fn del(
&mut self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
) {
match path.parts.first() { match path.parts.first() {
// Get the current path part // Get the current path part
Some(p) => match self { Some(p) => match self {
@ -16,7 +25,7 @@ impl Value {
Part::Field(p) => match path.parts.len() { Part::Field(p) => match path.parts.len() {
1 => v.remove(&p.name), 1 => v.remove(&p.name),
_ => match v.value.get_mut(&p.name) { _ => match v.value.get_mut(&p.name) {
Some(v) if v.is_some() => v.del(ctx, opt, exe, &path.next()), Some(v) if v.is_some() => v.del(ctx, opt, exe, &path.next()).await,
_ => (), _ => (),
}, },
}, },
@ -26,7 +35,11 @@ impl Value {
Value::Array(v) => match p { Value::Array(v) => match p {
Part::All => match path.parts.len() { Part::All => match path.parts.len() {
1 => v.value.clear(), 1 => v.value.clear(),
_ => v.value.iter_mut().for_each(|v| v.del(ctx, opt, exe, &path.next())), _ => {
for v in &mut v.value {
v.del(ctx, opt, exe, &path.next()).await
}
}
}, },
Part::First => match path.parts.len() { Part::First => match path.parts.len() {
1 => { 1 => {
@ -36,7 +49,7 @@ impl Value {
} }
} }
_ => match v.value.first_mut() { _ => match v.value.first_mut() {
Some(v) => v.del(ctx, opt, exe, &path.next()), Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => (),
}, },
}, },
@ -48,7 +61,7 @@ impl Value {
} }
} }
_ => match v.value.last_mut() { _ => match v.value.last_mut() {
Some(v) => v.del(ctx, opt, exe, &path.next()), Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => (),
}, },
}, },
@ -61,22 +74,32 @@ impl Value {
} }
_ => match path.parts.len() { _ => match path.parts.len() {
_ => match v.value.get_mut(i.to_usize()) { _ => match v.value.get_mut(i.to_usize()) {
Some(v) => v.del(ctx, opt, exe, &path.next()), Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => (),
}, },
}, },
}, },
Part::Where(w) => match path.parts.len() { Part::Where(w) => match path.parts.len() {
1 => v.value.retain(|v| match w.process(ctx, opt, exe, Some(v)) { 1 => {
Ok(v) if v.is_truthy() => false, let mut m = HashMap::new();
_ => true, for (i, v) in v.value.iter().enumerate() {
}), match w.compute(ctx, opt, exe, Some(&v)).await {
_ => v.value.iter_mut().for_each(|v| { Ok(o) if o.is_truthy() => m.insert(i, ()),
match w.process(ctx, opt, exe, Some(v)) { _ => None,
Ok(mut v) if v.is_truthy() => v.del(ctx, opt, exe, &path.next()), };
_ => (),
} }
}), v.value.abolish(|i| m.contains_key(&i))
}
_ => {
for v in &mut v.value {
match w.compute(ctx, opt, exe, Some(&v)).await {
Ok(o) if o.is_truthy() => {
v.del(ctx, opt, exe, &path.next()).await
}
_ => (),
};
}
}
}, },
_ => (), _ => (),
}, },
@ -96,85 +119,105 @@ mod tests {
use crate::dbs::test::mock; use crate::dbs::test::mock;
use crate::sql::test::Parse; use crate::sql::test::Parse;
#[test] #[tokio::test]
fn del_none() { async fn del_none() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom { let idi = Idiom {
parts: vec![], parts: vec![],
}; };
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null, something: 123 } }"); let res = Value::parse("{ test: { other: null, something: 123 } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_reset() { async fn del_reset() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ }"); let res = Value::parse("{ }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_basic() { async fn del_basic() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something"); let idi = Idiom::parse("test.something");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null } }"); let res = Value::parse("{ test: { other: null } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_wrong() { async fn del_wrong() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something.wrong"); let idi = Idiom::parse("test.something.wrong");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null, something: 123 } }"); let res = Value::parse("{ test: { other: null, something: 123 } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_other() { async fn del_other() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.other.something"); let idi = Idiom::parse("test.other.something");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null, something: 123 } }"); let res = Value::parse("{ test: { other: null, something: 123 } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_array() { async fn del_array() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]"); let idi = Idiom::parse("test.something[1]");
let mut val = Value::parse("{ test: { something: [123, 456, 789] } }"); let mut val = Value::parse("{ test: { something: [123, 456, 789] } }");
let res = Value::parse("{ test: { something: [123, 789] } }"); let res = Value::parse("{ test: { something: [123, 789] } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_array_field() { async fn del_array_field() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1].age"); let idi = Idiom::parse("test.something[1].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }, { }] } }"); let res = Value::parse("{ test: { something: [{ age: 34 }, { }] } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn del_array_fields() { async fn del_array_fields() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[*].age"); let idi = Idiom::parse("test.something[*].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ }, { }] } }"); let res = Value::parse("{ test: { something: [{ }, { }] } }");
val.del(&ctx, &opt, &mut exe, &idi); val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val);
}
#[tokio::test]
async fn del_array_where_field() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }, { }] } }");
val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val);
}
#[tokio::test]
async fn del_array_where_fields() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35]");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }] } }");
val.del(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -6,7 +6,7 @@ use crate::sql::part::Part;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn first(&self, ctx: &Runtime, opt: &Options, exe: &mut Executor) -> Self { pub async fn first(&self, ctx: &Runtime, opt: &Options<'_>, exe: &mut Executor) -> Self {
self.get(ctx, opt, exe, &Idiom::from(vec![Part::First])) self.get(ctx, opt, exe, &Idiom::from(vec![Part::First])).await
} }
} }

View file

@ -1,55 +1,66 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::sql::field::{Field, Fields}; use crate::sql::field::{Field, Fields};
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::part::Part; use crate::sql::part::Part;
use crate::sql::statements::select::SelectStatement; use crate::sql::statements::select::SelectStatement;
use crate::sql::value::{Value, Values}; use crate::sql::value::{Value, Values};
use async_recursion::async_recursion;
impl Value { impl Value {
pub fn get(&self, ctx: &Runtime, opt: &Options, exe: &mut Executor, path: &Idiom) -> Self { #[async_recursion]
pub async fn get(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
) -> Self {
match path.parts.first() { match path.parts.first() {
// Get the current path part // Get the current path part
Some(p) => match self { Some(p) => match self {
// Current path part is an object // Current path part is an object
Value::Object(v) => match p { Value::Object(v) => match p {
Part::Field(p) => match v.value.get(&p.name) { Part::Field(p) => match v.value.get(&p.name) {
Some(v) => v.get(ctx, opt, exe, &path.next()), Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Value::None,
}, },
_ => Value::None, _ => Value::None,
}, },
// Current path part is an array // Current path part is an array
Value::Array(v) => match p { Value::Array(v) => match p {
Part::All => v Part::All => {
.value let mut a = Vec::new();
.iter() for v in &v.value {
.map(|v| v.get(ctx, opt, exe, &path.next())) a.push(v.get(ctx, opt, exe, &path.next()).await)
.collect::<Vec<Value>>() }
.into(), a.into()
}
Part::First => match v.value.first() { Part::First => match v.value.first() {
Some(v) => v.get(ctx, opt, exe, &path.next()), Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Value::None,
}, },
Part::Last => match v.value.last() { Part::Last => match v.value.last() {
Some(v) => v.get(ctx, opt, exe, &path.next()), Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Value::None,
}, },
Part::Index(i) => match v.value.get(i.to_usize()) { Part::Index(i) => match v.value.get(i.to_usize()) {
Some(v) => v.get(ctx, opt, exe, &path.next()), Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Value::None,
}, },
Part::Where(w) => v Part::Where(w) => {
.value let mut a = Vec::new();
.iter() for v in &v.value {
.filter_map(|v| match w.process(ctx, opt, exe, Some(v)) { match w.compute(ctx, opt, exe, Some(&v)).await {
Ok(v) if v.is_truthy() => Some(v.get(ctx, opt, exe, &path.next())), Ok(x) if x.is_truthy() => {
_ => None, a.push(v.get(ctx, opt, exe, &path.next()).await)
}) }
.collect::<Vec<Value>>() _ => (),
.into(), };
}
a.into()
}
_ => Value::None, _ => Value::None,
}, },
// Current path part is a thing // Current path part is a thing
@ -63,8 +74,8 @@ impl Value {
what: Values(vec![Value::Thing(v.clone())]), what: Values(vec![Value::Thing(v.clone())]),
..SelectStatement::default() ..SelectStatement::default()
}; };
match stm.process(ctx, opt, exe, None) { match stm.compute(ctx, opt, exe, None).await {
Ok(v) => v.get(ctx, opt, exe, &path.next()), Ok(v) => v.get(ctx, opt, exe, &path.next()).await,
Err(_) => Value::None, Err(_) => Value::None,
} }
} }
@ -86,32 +97,32 @@ mod tests {
use crate::sql::test::Parse; use crate::sql::test::Parse;
use crate::sql::thing::Thing; use crate::sql::thing::Thing;
#[test] #[tokio::test]
fn get_none() { async fn get_none() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom { let idi = Idiom {
parts: vec![], parts: vec![],
}; };
let val = Value::parse("{ test: { other: null, something: 123 } }"); let val = Value::parse("{ test: { other: null, something: 123 } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn get_basic() { async fn get_basic() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something"); let idi = Idiom::parse("test.something");
let val = Value::parse("{ test: { other: null, something: 123 } }"); let val = Value::parse("{ test: { other: null, something: 123 } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, Value::from(123)); assert_eq!(res, Value::from(123));
} }
#[test] #[tokio::test]
fn get_thing() { async fn get_thing() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.other"); let idi = Idiom::parse("test.other");
let val = Value::parse("{ test: { other: test:tobie, something: 123 } }"); let val = Value::parse("{ test: { other: test:tobie, something: 123 } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!( assert_eq!(
res, res,
Value::from(Thing { Value::from(Thing {
@ -121,21 +132,21 @@ mod tests {
); );
} }
#[test] #[tokio::test]
fn get_array() { async fn get_array() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]"); let idi = Idiom::parse("test.something[1]");
let val = Value::parse("{ test: { something: [123, 456, 789] } }"); let val = Value::parse("{ test: { something: [123, 456, 789] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, Value::from(456)); assert_eq!(res, Value::from(456));
} }
#[test] #[tokio::test]
fn get_array_thing() { async fn get_array_thing() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]"); let idi = Idiom::parse("test.something[1]");
let val = Value::parse("{ test: { something: [test:tobie, test:jaime] } }"); let val = Value::parse("{ test: { something: [test:tobie, test:jaime] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!( assert_eq!(
res, res,
Value::from(Thing { Value::from(Thing {
@ -145,21 +156,44 @@ mod tests {
); );
} }
#[test] #[tokio::test]
fn get_array_field() { async fn get_array_field() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1].age"); let idi = Idiom::parse("test.something[1].age");
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, Value::from(36)); assert_eq!(res, Value::from(36));
} }
#[test] #[tokio::test]
fn get_array_fields() { async fn get_array_fields() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[*].age"); let idi = Idiom::parse("test.something[*].age");
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi); let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, Value::from(vec![34, 36])); assert_eq!(res, Value::from(vec![34, 36]));
} }
#[tokio::test]
async fn get_array_where_field() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35].age");
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(res, Value::from(vec![36]));
}
#[tokio::test]
async fn get_array_where_fields() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35]");
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = val.get(&ctx, &opt, &mut exe, &idi).await;
assert_eq!(
res,
Value::from(vec![Value::from(map! {
"age".to_string() => Value::from(36),
})])
);
}
} }

View file

@ -6,27 +6,45 @@ use crate::sql::number::Number;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn increment( pub async fn increment(
&mut self, &mut self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
) { ) {
match self.get(ctx, opt, exe, path) { match self.get(ctx, opt, exe, path).await {
Value::Number(v) => match val { Value::Number(v) => match val {
Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(v + x)), Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(v + x)).await;
()
}
_ => (), _ => (),
}, },
Value::Array(v) => match val { Value::Array(v) => match val {
Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(v + x)), Value::Array(x) => {
x => self.set(ctx, opt, exe, path, Value::from(v + x)), self.set(ctx, opt, exe, path, Value::from(v + x)).await;
()
}
x => {
self.set(ctx, opt, exe, path, Value::from(v + x)).await;
()
}
}, },
Value::None => match val { Value::None => match val {
Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(Number::from(0) + x)), Value::Number(x) => {
Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(x)), self.set(ctx, opt, exe, path, Value::from(Number::from(0) + x)).await;
x => self.set(ctx, opt, exe, path, Value::from(vec![x])), ()
}
Value::Array(x) => {
self.set(ctx, opt, exe, path, Value::from(x)).await;
()
}
x => {
self.set(ctx, opt, exe, path, Value::from(vec![x])).await;
()
}
}, },
_ => (), _ => (),
} }
@ -40,53 +58,53 @@ mod tests {
use crate::dbs::test::mock; use crate::dbs::test::mock;
use crate::sql::test::Parse; use crate::sql::test::Parse;
#[test] #[tokio::test]
fn inc_none() { async fn inc_none() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("other"); let idi = Idiom::parse("other");
let mut val = Value::parse("{ test: 100 }"); let mut val = Value::parse("{ test: 100 }");
let res = Value::parse("{ test: 100, other: +10 }"); let res = Value::parse("{ test: 100, other: +10 }");
val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn inc_number() { async fn inc_number() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: 100 }"); let mut val = Value::parse("{ test: 100 }");
let res = Value::parse("{ test: 110 }"); let res = Value::parse("{ test: 110 }");
val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn inc_array_number() { async fn inc_array_number() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test[1]"); let idi = Idiom::parse("test[1]");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [100, 210, 300] }"); let res = Value::parse("{ test: [100, 210, 300] }");
val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)); val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn inc_array_value() { async fn inc_array_value() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [100, 200, 300] }"); let res = Value::parse("{ test: [100, 200, 300] }");
val.increment(&ctx, &opt, &mut exe, &idi, Value::from(200)); val.increment(&ctx, &opt, &mut exe, &idi, Value::from(200)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn inc_array_array() { async fn inc_array_array() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }"); let mut val = Value::parse("{ test: [100, 200, 300] }");
let res = Value::parse("{ test: [100, 200, 300, 400, 500] }"); let res = Value::parse("{ test: [100, 200, 300, 400, 500] }");
val.increment(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300, 400, 500]")); val.increment(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300, 400, 500]")).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -6,7 +6,7 @@ use crate::sql::part::Part;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn last(&self, ctx: &Runtime, opt: &Options, exe: &mut Executor) -> Self { pub async fn last(&self, ctx: &Runtime, opt: &Options<'_>, exe: &mut Executor) -> Self {
self.get(ctx, opt, exe, &Idiom::from(vec![Part::Last])) self.get(ctx, opt, exe, &Idiom::from(vec![Part::Last])).await
} }
} }

View file

@ -6,8 +6,14 @@ use crate::sql::object::Object;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn object(&mut self, ctx: &Runtime, opt: &Options, exe: &mut Executor, path: &Idiom) { pub async fn object(
&mut self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
) {
let val = Value::from(Object::default()); let val = Value::from(Object::default());
self.set(ctx, opt, exe, path, val) self.set(ctx, opt, exe, path, val).await
} }
} }

View file

@ -1,17 +1,18 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::object::Object; use crate::sql::object::Object;
use crate::sql::part::Part; use crate::sql::part::Part;
use crate::sql::value::Value; use crate::sql::value::Value;
use async_recursion::async_recursion;
impl Value { impl Value {
pub fn set( #[async_recursion]
pub async fn set(
&mut self, &mut self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
@ -22,10 +23,10 @@ impl Value {
// Current path part is an object // Current path part is an object
Value::Object(v) => match p { Value::Object(v) => match p {
Part::Field(p) => match v.value.get_mut(&p.name) { Part::Field(p) => match v.value.get_mut(&p.name) {
Some(v) if v.is_some() => v.set(ctx, opt, exe, &path.next(), val), Some(v) if v.is_some() => v.set(ctx, opt, exe, &path.next(), val).await,
_ => { _ => {
let mut obj = Value::from(Object::default()); let mut obj = Value::from(Object::default());
obj.set(ctx, opt, exe, &path.next(), val); obj.set(ctx, opt, exe, &path.next(), val).await;
v.insert(&p.name, obj) v.insert(&p.name, obj)
} }
}, },
@ -33,29 +34,32 @@ impl Value {
}, },
// Current path part is an array // Current path part is an array
Value::Array(v) => match p { Value::Array(v) => match p {
Part::All => v Part::All => {
.value for v in &mut v.value {
.iter_mut() v.set(ctx, opt, exe, &path.next(), val.clone()).await
.for_each(|v| v.set(ctx, opt, exe, &path.next(), val.clone())), }
}
Part::First => match v.value.first_mut() { Part::First => match v.value.first_mut() {
Some(v) => v.set(ctx, opt, exe, &path.next(), val), Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => (),
}, },
Part::Last => match v.value.last_mut() { Part::Last => match v.value.last_mut() {
Some(v) => v.set(ctx, opt, exe, &path.next(), val), Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => (),
}, },
Part::Index(i) => match v.value.get_mut(i.to_usize()) { Part::Index(i) => match v.value.get_mut(i.to_usize()) {
Some(v) => v.set(ctx, opt, exe, &path.next(), val), Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => (),
}, },
Part::Where(w) => { Part::Where(w) => {
v.value.iter_mut().for_each(|v| match w.process(ctx, opt, exe, Some(v)) { for v in &mut v.value {
Ok(mut v) if v.is_truthy() => { match w.compute(ctx, opt, exe, Some(&v)).await {
v.set(ctx, opt, exe, &path.next(), val.clone()) Ok(x) if x.is_truthy() => {
} v.set(ctx, opt, exe, &path.next(), val.clone()).await
_ => (), }
}) _ => (),
};
}
} }
_ => (), _ => (),
}, },
@ -75,85 +79,105 @@ mod tests {
use crate::dbs::test::mock; use crate::dbs::test::mock;
use crate::sql::test::Parse; use crate::sql::test::Parse;
#[test] #[tokio::test]
fn set_none() { async fn set_none() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom { let idi = Idiom {
parts: vec![], parts: vec![],
}; };
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("999"); let res = Value::parse("999");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_reset() { async fn set_reset() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test"); let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: 999 }"); let res = Value::parse("{ test: 999 }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_basic() { async fn set_basic() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something"); let idi = Idiom::parse("test.something");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null, something: 999 } }"); let res = Value::parse("{ test: { other: null, something: 999 } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_wrong() { async fn set_wrong() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something.wrong"); let idi = Idiom::parse("test.something.wrong");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: null, something: 123 } }"); let res = Value::parse("{ test: { other: null, something: 123 } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_other() { async fn set_other() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.other.something"); let idi = Idiom::parse("test.other.something");
let mut val = Value::parse("{ test: { other: null, something: 123 } }"); let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ test: { other: { something: 999 }, something: 123 } }"); let res = Value::parse("{ test: { other: { something: 999 }, something: 123 } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_array() { async fn set_array() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]"); let idi = Idiom::parse("test.something[1]");
let mut val = Value::parse("{ test: { something: [123, 456, 789] } }"); let mut val = Value::parse("{ test: { something: [123, 456, 789] } }");
let res = Value::parse("{ test: { something: [123, 999, 789] } }"); let res = Value::parse("{ test: { something: [123, 999, 789] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_array_field() { async fn set_array_field() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1].age"); let idi = Idiom::parse("test.something[1].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }, { age: 21 }] } }"); let res = Value::parse("{ test: { something: [{ age: 34 }, { age: 21 }] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
#[test] #[tokio::test]
fn set_array_fields() { async fn set_array_fields() {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[*].age"); let idi = Idiom::parse("test.something[*].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }"); let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 21 }, { age: 21 }] } }"); let res = Value::parse("{ test: { something: [{ age: 21 }, { age: 21 }] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)); val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await;
assert_eq!(res, val);
}
#[tokio::test]
async fn set_array_where_field() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }, { age: 21 }] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await;
assert_eq!(res, val);
}
#[tokio::test]
async fn set_array_where_fields() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35]");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
let res = Value::parse("{ test: { something: [{ age: 34 }, 21] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await;
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
@ -21,6 +20,7 @@ use crate::sql::strand::{strand, Strand};
use crate::sql::subquery::{subquery, Subquery}; use crate::sql::subquery::{subquery, Subquery};
use crate::sql::table::{table, Table}; use crate::sql::table::{table, Table};
use crate::sql::thing::{thing, Thing}; use crate::sql::thing::{thing, Thing};
use async_recursion::async_recursion;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use dec::Decimal; use dec::Decimal;
use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::skim::SkimMatcherV2;
@ -762,13 +762,14 @@ impl fmt::Display for Value {
} }
} }
impl dbs::Process for Value { impl Value {
fn process( #[async_recursion]
pub async fn compute(
&self, &self,
ctx: &Runtime, ctx: &Runtime,
opt: &Options, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
doc: Option<&Value>, doc: Option<&'async_recursion Value>,
) -> Result<Value, Error> { ) -> Result<Value, Error> {
match self { match self {
Value::None => Ok(Value::None), Value::None => Ok(Value::None),
@ -776,13 +777,13 @@ impl dbs::Process for Value {
Value::Null => Ok(Value::Null), Value::Null => Ok(Value::Null),
Value::True => Ok(Value::True), Value::True => Ok(Value::True),
Value::False => Ok(Value::False), Value::False => Ok(Value::False),
Value::Param(v) => v.process(ctx, opt, exe, doc), Value::Param(v) => v.compute(ctx, opt, exe, doc).await,
Value::Idiom(v) => v.process(ctx, opt, exe, doc), Value::Idiom(v) => v.compute(ctx, opt, exe, doc).await,
Value::Array(v) => v.process(ctx, opt, exe, doc), Value::Array(v) => v.compute(ctx, opt, exe, doc).await,
Value::Object(v) => v.process(ctx, opt, exe, doc), Value::Object(v) => v.compute(ctx, opt, exe, doc).await,
Value::Function(v) => v.process(ctx, opt, exe, doc), Value::Function(v) => v.compute(ctx, opt, exe, doc).await,
Value::Subquery(v) => v.process(ctx, opt, exe, doc), Value::Subquery(v) => v.compute(ctx, opt, exe, doc).await,
Value::Expression(v) => v.process(ctx, opt, exe, doc), Value::Expression(v) => v.compute(ctx, opt, exe, doc).await,
_ => Ok(self.to_owned()), _ => Ok(self.to_owned()),
} }
} }