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
exe.ns = session.ns;
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> {
@ -30,7 +30,7 @@ pub async fn process(ast: Query, session: Session, vars: Variables) -> Result<Re
// Process all statements
exe.ns = session.ns;
exe.db = session.db;
exe.execute(ctx, ast)
exe.execute(ctx, ast).await
}
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::Level;
use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::query::Query;
@ -47,7 +46,7 @@ impl Executor {
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
let mut out: Vec<Response> = vec![];
// Create a new options
@ -75,25 +74,25 @@ impl Executor {
}
// Begin a new transaction
Statement::Begin(stm) => {
let res = stm.process(&ctx, &opt, self, None);
let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err();
continue;
}
// Cancel a running transaction
Statement::Cancel(stm) => {
let res = stm.process(&ctx, &opt, self, None);
let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err();
continue;
}
// Commit a running transaction
Statement::Commit(stm) => {
let res = stm.process(&ctx, &opt, self, None);
let res = stm.compute(&ctx, &opt, self, None).await;
self.err = res.err();
continue;
}
// Process param definition statements
Statement::Set(stm) => {
match stm.process(&ctx, &opt, self, None) {
match stm.compute(&ctx, &opt, self, None).await {
Ok(val) => {
let mut new = Context::new(&ctx);
let key = stm.name.to_owned();
@ -115,7 +114,7 @@ impl Executor {
ctx = new.freeze();
}
// Process statement
let res = stm.process(&ctx, &opt, self, None);
let res = stm.compute(&ctx, &opt, self, None).await;
// Catch statement timeout
if let Some(timeout) = stm.timeout() {
if ctx.is_timedout() {

View file

@ -3,7 +3,6 @@ mod dbs;
mod executor;
mod iterator;
mod options;
mod process;
mod response;
mod runtime;
mod session;
@ -13,7 +12,6 @@ pub use self::dbs::*;
pub use self::executor::*;
pub use self::iterator::*;
pub use self::options::*;
pub use self::process::*;
pub use self::response::*;
pub use self::runtime::*;
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::Options;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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> {
fn uniq(self) -> Vec<T>;
}

View file

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

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
alt((casts, langs, future, normal))(i)
}
@ -397,7 +396,7 @@ mod tests {
let res = function(sql);
assert!(res.is_ok());
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()));
}
@ -407,7 +406,7 @@ mod tests {
let res = function(sql);
assert!(res.is_ok());
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()));
}

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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
pub fn local(i: &str) -> IResult<&str, Idiom> {
let (i, p) = first(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
@ -26,17 +25,11 @@ impl From<Idiom> for Param {
}
}
impl fmt::Display for Param {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "${}", &self.name)
}
}
impl dbs::Process for Param {
fn process(
impl Param {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -47,9 +40,9 @@ impl dbs::Process for Param {
// The base variable exists
Some(v) => {
// 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
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
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> {
let (i, _) = tag("$")(i)?;
let (i, v) = idiom::param(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
delimited(
mightbespace,

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Iterator;
use crate::dbs::Level;
@ -28,27 +27,11 @@ pub struct CreateStatement {
pub timeout: Option<Timeout>,
}
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(())
}
}
impl dbs::Process for CreateStatement {
fn process(
impl CreateStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -62,7 +45,7 @@ impl dbs::Process for CreateStatement {
let opt = &opt.futures(false);
// Loop over the create targets
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) => {
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> {
let (i, _) = tag_no_case("CREATE")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Level;
use crate::dbs::Options;
@ -38,6 +37,28 @@ pub enum DefineStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
alt((
map(namespace, |v| DefineStatement::Namespace(v)),
@ -99,17 +98,11 @@ pub struct DefineNamespaceStatement {
pub name: String,
}
impl fmt::Display for DefineNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE NAMESPACE {}", self.name)
}
}
impl dbs::Process for DefineNamespaceStatement {
fn process(
impl DefineNamespaceStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -143,17 +142,11 @@ pub struct DefineDatabaseStatement {
pub name: String,
}
impl fmt::Display for DefineDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE DATABASE {}", self.name)
}
}
impl dbs::Process for DefineDatabaseStatement {
fn process(
impl DefineDatabaseStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -192,24 +191,11 @@ pub struct DefineLoginStatement {
pub hash: Option<String>,
}
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(())
}
}
impl dbs::Process for DefineLoginStatement {
fn process(
impl DefineLoginStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -290,21 +289,11 @@ pub struct DefineTokenStatement {
pub code: String,
}
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
)
}
}
impl dbs::Process for DefineTokenStatement {
fn process(
impl DefineTokenStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -365,6 +364,21 @@ pub struct DefineScopeStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -488,6 +487,21 @@ pub struct DefineTableStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -619,21 +618,11 @@ pub struct DefineEventStatement {
pub then: Values,
}
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
)
}
}
impl dbs::Process for DefineEventStatement {
fn process(
impl DefineEventStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -693,6 +692,21 @@ pub struct DefineFieldStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -832,21 +831,11 @@ pub struct DefineIndexStatement {
pub uniq: bool,
}
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(())
}
}
impl dbs::Process for DefineIndexStatement {
fn process(
impl DefineIndexStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("DEFINE")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Iterator;
use crate::dbs::Level;
@ -29,27 +28,11 @@ pub struct DeleteStatement {
pub timeout: Option<Timeout>,
}
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(())
}
}
impl dbs::Process for DeleteStatement {
fn process(
impl DeleteStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -63,7 +46,7 @@ impl dbs::Process for DeleteStatement {
let opt = &opt.futures(false);
// Loop over the delete targets
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) => {
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> {
let (i, _) = tag_no_case("DELETE")(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::Options;
use crate::dbs::Runtime;
@ -19,6 +18,27 @@ pub struct IfelseStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, exprs) = separated_list0(split, exprs)(i)?;
let (i, close) = opt(close)(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Level;
use crate::dbs::Options;
@ -21,22 +20,11 @@ pub enum InfoStatement {
Table(String),
}
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),
}
}
}
impl dbs::Process for InfoStatement {
fn process(
impl InfoStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("INFO")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Iterator;
use crate::dbs::Level;
@ -32,28 +31,11 @@ pub struct InsertStatement {
pub timeout: Option<Timeout>,
}
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(())
}
}
impl dbs::Process for InsertStatement {
fn process(
impl InsertStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -71,7 +53,7 @@ impl dbs::Process for InsertStatement {
Data::ValuesExpression(_) => {
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) => {
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> {
let (i, _) = tag_no_case("INSERT")(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::Options;
use crate::dbs::Runtime;
@ -16,17 +15,11 @@ pub struct KillStatement {
pub id: Ident,
}
impl fmt::Display for KillStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "KILL {}", self.id)
}
}
impl dbs::Process for KillStatement {
fn process(
impl KillStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
_opt: &Options,
_opt: &Options<'_>,
_exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("KILL")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
@ -26,6 +25,18 @@ pub struct LiveStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, _) = tag_no_case("LIVE SELECT")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Level;
use crate::dbs::Options;
@ -23,21 +22,11 @@ pub struct OptionStatement {
pub what: bool,
}
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)
}
}
}
impl dbs::Process for OptionStatement {
fn process(
impl OptionStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("OPTION")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
@ -15,24 +14,24 @@ pub struct OutputStatement {
pub what: Value,
}
impl fmt::Display for OutputStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "RETURN {}", self.what)
}
}
impl dbs::Process for OutputStatement {
fn process(
impl OutputStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
// Ensure futures are processed
let opt = &opt.futures(true);
// 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::Iterator;
use crate::dbs::Level;
@ -35,30 +34,11 @@ pub struct RelateStatement {
pub timeout: Option<Timeout>,
}
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(())
}
}
impl dbs::Process for RelateStatement {
fn process(
impl RelateStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -70,7 +50,7 @@ impl dbs::Process for RelateStatement {
let opt = &opt.futures(false);
// Loop over the select targets
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) => {
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> {
let (i, _) = tag_no_case("RELATE")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Level;
use crate::dbs::Options;
@ -29,6 +28,28 @@ pub enum RemoveStatement {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
alt((
map(namespace, |v| RemoveStatement::Namespace(v)),
@ -90,17 +89,11 @@ pub struct RemoveNamespaceStatement {
pub name: String,
}
impl fmt::Display for RemoveNamespaceStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE NAMESPACE {}", self.name)
}
}
impl dbs::Process for RemoveNamespaceStatement {
fn process(
impl RemoveNamespaceStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -134,17 +133,11 @@ pub struct RemoveDatabaseStatement {
pub name: String,
}
impl fmt::Display for RemoveDatabaseStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE DATABASE {}", self.name)
}
}
impl dbs::Process for RemoveDatabaseStatement {
fn process(
impl RemoveDatabaseStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -179,17 +178,11 @@ pub struct RemoveLoginStatement {
pub base: Base,
}
impl fmt::Display for RemoveLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE LOGIN {} ON {}", self.name, self.base)
}
}
impl dbs::Process for RemoveLoginStatement {
fn process(
impl RemoveLoginStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -233,17 +232,11 @@ pub struct RemoveTokenStatement {
pub base: Base,
}
impl fmt::Display for RemoveTokenStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE TOKEN {} ON {}", self.name, self.base)
}
}
impl dbs::Process for RemoveTokenStatement {
fn process(
impl RemoveTokenStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -286,17 +285,11 @@ pub struct RemoveScopeStatement {
pub name: String,
}
impl fmt::Display for RemoveScopeStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE SCOPE {}", self.name)
}
}
impl dbs::Process for RemoveScopeStatement {
fn process(
impl RemoveScopeStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -330,17 +329,11 @@ pub struct RemoveTableStatement {
pub name: String,
}
impl fmt::Display for RemoveTableStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE TABLE {}", self.name)
}
}
impl dbs::Process for RemoveTableStatement {
fn process(
impl RemoveTableStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -375,17 +374,11 @@ pub struct RemoveEventStatement {
pub what: String,
}
impl fmt::Display for RemoveEventStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE EVENT {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveEventStatement {
fn process(
impl RemoveEventStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -426,17 +425,11 @@ pub struct RemoveFieldStatement {
pub what: String,
}
impl fmt::Display for RemoveFieldStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE FIELD {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveFieldStatement {
fn process(
impl RemoveFieldStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;
@ -477,17 +476,11 @@ pub struct RemoveIndexStatement {
pub what: String,
}
impl fmt::Display for RemoveIndexStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "REMOVE INDEX {} ON {}", self.name, self.what)
}
}
impl dbs::Process for RemoveIndexStatement {
fn process(
impl RemoveIndexStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
let (i, _) = tag_no_case("REMOVE")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Iterator;
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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> {
let (i, _) = tag_no_case("SELECT")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
@ -20,21 +19,21 @@ pub struct SetStatement {
pub what: Value,
}
impl fmt::Display for SetStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "LET ${} = {}", self.name, self.what)
}
}
impl dbs::Process for SetStatement {
fn process(
impl SetStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> 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::Iterator;
use crate::dbs::Level;
@ -31,30 +30,11 @@ pub struct UpdateStatement {
pub timeout: Option<Timeout>,
}
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(())
}
}
impl dbs::Process for UpdateStatement {
fn process(
impl UpdateStatement {
pub async fn compute(
&self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
doc: Option<&Value>,
) -> Result<Value, Error> {
@ -69,7 +49,7 @@ impl dbs::Process for UpdateStatement {
let opt = &opt.futures(false);
// Loop over the update targets
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) => {
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> {
let (i, _) = tag_no_case("UPDATE")(i)?;
let (i, _) = shouldbespace(i)?;

View file

@ -1,4 +1,3 @@
use crate::dbs;
use crate::dbs::Auth;
use crate::dbs::Executor;
use crate::dbs::Options;
@ -21,24 +20,11 @@ pub struct UseStatement {
pub db: Option<String>,
}
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(())
}
}
impl dbs::Process for UseStatement {
fn process(
impl UseStatement {
pub async fn compute(
&self,
_ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
_doc: Option<&Value>,
) -> 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> {
alt((both, ns, db))(i)
}

View file

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

View file

@ -6,8 +6,14 @@ use crate::sql::idiom::Idiom;
use crate::sql::value::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());
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;
impl Value {
pub fn decrement(
pub async fn decrement(
&mut self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
val: Value,
) {
match self.get(ctx, opt, exe, path) {
match self.get(ctx, opt, exe, path).await {
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(x) => self.set(ctx, opt, exe, path, Value::from(v - x)),
x => self.set(ctx, opt, exe, path, Value::from(v - x)),
Value::Array(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::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::sql::test::Parse;
#[test]
fn dec_none() {
#[tokio::test]
async fn dec_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("other");
let mut val = Value::parse("{ test: 100 }");
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);
}
#[test]
fn dec_number() {
#[tokio::test]
async fn dec_number() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: 100 }");
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);
}
#[test]
fn dec_array_number() {
#[tokio::test]
async fn dec_array_number() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test[1]");
let mut val = Value::parse("{ test: [100, 200, 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);
}
#[test]
fn dec_array_value() {
#[tokio::test]
async fn dec_array_value() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 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);
}
#[test]
fn dec_array_array() {
#[tokio::test]
async fn dec_array_array() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }");
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);
}
}

View file

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

View file

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

View file

@ -1,55 +1,66 @@
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Process;
use crate::dbs::Runtime;
use crate::sql::field::{Field, Fields};
use crate::sql::idiom::Idiom;
use crate::sql::part::Part;
use crate::sql::statements::select::SelectStatement;
use crate::sql::value::{Value, Values};
use async_recursion::async_recursion;
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() {
// Get the current path part
Some(p) => match self {
// Current path part is an object
Value::Object(v) => match p {
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,
},
_ => Value::None,
},
// Current path part is an array
Value::Array(v) => match p {
Part::All => v
.value
.iter()
.map(|v| v.get(ctx, opt, exe, &path.next()))
.collect::<Vec<Value>>()
.into(),
Part::All => {
let mut a = Vec::new();
for v in &v.value {
a.push(v.get(ctx, opt, exe, &path.next()).await)
}
a.into()
}
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,
},
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,
},
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,
},
Part::Where(w) => v
.value
.iter()
.filter_map(|v| match w.process(ctx, opt, exe, Some(v)) {
Ok(v) if v.is_truthy() => Some(v.get(ctx, opt, exe, &path.next())),
_ => None,
})
.collect::<Vec<Value>>()
.into(),
Part::Where(w) => {
let mut a = Vec::new();
for v in &v.value {
match w.compute(ctx, opt, exe, Some(&v)).await {
Ok(x) if x.is_truthy() => {
a.push(v.get(ctx, opt, exe, &path.next()).await)
}
_ => (),
};
}
a.into()
}
_ => Value::None,
},
// Current path part is a thing
@ -63,8 +74,8 @@ impl Value {
what: Values(vec![Value::Thing(v.clone())]),
..SelectStatement::default()
};
match stm.process(ctx, opt, exe, None) {
Ok(v) => v.get(ctx, opt, exe, &path.next()),
match stm.compute(ctx, opt, exe, None).await {
Ok(v) => v.get(ctx, opt, exe, &path.next()).await,
Err(_) => Value::None,
}
}
@ -86,32 +97,32 @@ mod tests {
use crate::sql::test::Parse;
use crate::sql::thing::Thing;
#[test]
fn get_none() {
#[tokio::test]
async fn get_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom {
parts: vec![],
};
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);
}
#[test]
fn get_basic() {
#[tokio::test]
async fn get_basic() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something");
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));
}
#[test]
fn get_thing() {
#[tokio::test]
async fn get_thing() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.other");
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!(
res,
Value::from(Thing {
@ -121,21 +132,21 @@ mod tests {
);
}
#[test]
fn get_array() {
#[tokio::test]
async fn get_array() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]");
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));
}
#[test]
fn get_array_thing() {
#[tokio::test]
async fn get_array_thing() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]");
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!(
res,
Value::from(Thing {
@ -145,21 +156,44 @@ mod tests {
);
}
#[test]
fn get_array_field() {
#[tokio::test]
async fn get_array_field() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1].age");
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));
}
#[test]
fn get_array_fields() {
#[tokio::test]
async fn get_array_fields() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[*].age");
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]));
}
#[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;
impl Value {
pub fn increment(
pub async fn increment(
&mut self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
val: Value,
) {
match self.get(ctx, opt, exe, path) {
match self.get(ctx, opt, exe, path).await {
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(x) => self.set(ctx, opt, exe, path, Value::from(v + x)),
x => self.set(ctx, opt, exe, path, Value::from(v + x)),
Value::Array(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::Number(x) => self.set(ctx, opt, exe, path, Value::from(Number::from(0) + x)),
Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(x)),
x => self.set(ctx, opt, exe, path, Value::from(vec![x])),
Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(Number::from(0) + x)).await;
()
}
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::sql::test::Parse;
#[test]
fn inc_none() {
#[tokio::test]
async fn inc_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("other");
let mut val = Value::parse("{ test: 100 }");
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);
}
#[test]
fn inc_number() {
#[tokio::test]
async fn inc_number() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: 100 }");
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);
}
#[test]
fn inc_array_number() {
#[tokio::test]
async fn inc_array_number() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test[1]");
let mut val = Value::parse("{ test: [100, 200, 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);
}
#[test]
fn inc_array_value() {
#[tokio::test]
async fn inc_array_value() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = 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);
}
#[test]
fn inc_array_array() {
#[tokio::test]
async fn inc_array_array() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: [100, 200, 300] }");
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);
}
}

View file

@ -6,7 +6,7 @@ use crate::sql::part::Part;
use crate::sql::value::Value;
impl Value {
pub fn last(&self, ctx: &Runtime, opt: &Options, exe: &mut Executor) -> Self {
self.get(ctx, opt, exe, &Idiom::from(vec![Part::Last]))
pub async fn last(&self, ctx: &Runtime, opt: &Options<'_>, exe: &mut Executor) -> Self {
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;
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());
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::Options;
use crate::dbs::Process;
use crate::dbs::Runtime;
use crate::sql::idiom::Idiom;
use crate::sql::object::Object;
use crate::sql::part::Part;
use crate::sql::value::Value;
use async_recursion::async_recursion;
impl Value {
pub fn set(
#[async_recursion]
pub async fn set(
&mut self,
ctx: &Runtime,
opt: &Options,
opt: &Options<'_>,
exe: &mut Executor,
path: &Idiom,
val: Value,
@ -22,10 +23,10 @@ impl Value {
// Current path part is an object
Value::Object(v) => match p {
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());
obj.set(ctx, opt, exe, &path.next(), val);
obj.set(ctx, opt, exe, &path.next(), val).await;
v.insert(&p.name, obj)
}
},
@ -33,29 +34,32 @@ impl Value {
},
// Current path part is an array
Value::Array(v) => match p {
Part::All => v
.value
.iter_mut()
.for_each(|v| v.set(ctx, opt, exe, &path.next(), val.clone())),
Part::All => {
for v in &mut v.value {
v.set(ctx, opt, exe, &path.next(), val.clone()).await
}
}
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 => (),
},
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 => (),
},
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 => (),
},
Part::Where(w) => {
v.value.iter_mut().for_each(|v| match w.process(ctx, opt, exe, Some(v)) {
Ok(mut v) if v.is_truthy() => {
v.set(ctx, opt, exe, &path.next(), val.clone())
}
_ => (),
})
for v in &mut v.value {
match w.compute(ctx, opt, exe, Some(&v)).await {
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::sql::test::Parse;
#[test]
fn set_none() {
#[tokio::test]
async fn set_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom {
parts: vec![],
};
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
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);
}
#[test]
fn set_reset() {
#[tokio::test]
async fn set_reset() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test");
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
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);
}
#[test]
fn set_basic() {
#[tokio::test]
async fn set_basic() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something");
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
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);
}
#[test]
fn set_wrong() {
#[tokio::test]
async fn set_wrong() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something.wrong");
let mut val = 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);
}
#[test]
fn set_other() {
#[tokio::test]
async fn set_other() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.other.something");
let mut val = Value::parse("{ test: { other: null, 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);
}
#[test]
fn set_array() {
#[tokio::test]
async fn set_array() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1]");
let mut val = Value::parse("{ test: { something: [123, 456, 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);
}
#[test]
fn set_array_field() {
#[tokio::test]
async fn set_array_field() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[1].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));
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await;
assert_eq!(res, val);
}
#[test]
fn set_array_fields() {
#[tokio::test]
async fn set_array_fields() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[*].age");
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
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);
}
}

View file

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