Return a Result from async methods on Value

Instead of silently failing, the async methods on a Value for getting, setting, and updating the value, now return a Result. This means we can chain the awaited result using the ? operator.
This commit is contained in:
Tobie Morgan Hitchcock 2022-01-20 23:00:57 +00:00
parent c86a53502d
commit 63747612e3
17 changed files with 343 additions and 169 deletions

View file

@ -32,6 +32,14 @@ pub struct Idiom {
pub parts: Vec<Part>, pub parts: Vec<Part>,
} }
impl From<String> for Idiom {
fn from(v: String) -> Self {
Idiom {
parts: vec![Part::from(v)],
}
}
}
impl From<Vec<Part>> for Idiom { impl From<Vec<Part>> for Idiom {
fn from(v: Vec<Part>) -> Self { fn from(v: Vec<Part>) -> Self {
Idiom { Idiom {
@ -59,7 +67,7 @@ impl Idiom {
) -> Result<Value, Error> { ) -> Result<Value, Error> {
match doc { match doc {
// There is a current document // There is a current document
Some(v) => v.get(ctx, opt, exe, self).await.ok(), Some(v) => v.get(ctx, opt, exe, self).await,
// There isn't any document // There isn't any document
None => Ok(Value::None), None => Ok(Value::None),
} }

View file

@ -42,7 +42,7 @@ impl Param {
// Process the paramater value // Process the paramater value
let res = v.compute(ctx, opt, exe, doc).await?; 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()).await.ok() res.get(ctx, opt, exe, &self.name.next()).await
} }
// The base variable does not exist // The base variable does not exist
None => Ok(Value::None), None => Ok(Value::None),

View file

@ -66,13 +66,11 @@ impl Subquery {
// Process result // Process result
match v.limit() { match v.limit() {
1 => match v.expr.single() { 1 => match v.expr.single() {
Some(v) => { Some(v) => res.first(&ctx, &opt, exe).await?.get(&ctx, &opt, exe, &v).await,
res.first(&ctx, &opt, exe).await.get(&ctx, &opt, exe, &v).await.ok() None => res.first(&ctx, &opt, exe).await,
}
None => res.first(&ctx, &opt, exe).await.ok(),
}, },
_ => match v.expr.single() { _ => match v.expr.single() {
Some(v) => res.get(&ctx, &opt, exe, &v).await.ok(), Some(v) => res.get(&ctx, &opt, exe, &v).await,
None => res.ok(), None => res.ok(),
}, },
} }

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::array::Array; use crate::sql::array::Array;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::value::Value; use crate::sql::value::Value;
@ -12,8 +13,36 @@ impl Value {
opt: &Options<'_>, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
) { ) -> Result<(), Error> {
let val = Value::from(Array::default()); let val = Value::from(Array::default());
self.set(ctx, opt, exe, path, Value::from(val)).await self.set(ctx, opt, exe, path, val).await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dbs::test::mock;
use crate::sql::test::Parse;
#[tokio::test]
async fn array_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::default();
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("[]");
val.array(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val);
}
#[tokio::test]
async fn array_path() {
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: [] }");
val.array(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val);
} }
} }

44
src/sql/value/clear.rs Normal file
View file

@ -0,0 +1,44 @@
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::object::Object;
use crate::sql::value::Value;
impl Value {
pub async fn clear(
&mut self,
_ctx: &Runtime,
_opt: &Options<'_>,
_exe: &mut Executor,
) -> Result<(), Error> {
*self = Value::from(Object::default());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dbs::test::mock;
use crate::sql::test::Parse;
#[tokio::test]
async fn clear_none() {
let (ctx, opt, mut exe) = mock();
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{}");
val.clear(&ctx, &opt, &mut exe).await.unwrap();
assert_eq!(res, val);
}
#[tokio::test]
async fn clear_path() {
let (ctx, opt, mut exe) = mock();
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{}");
val.clear(&ctx, &opt, &mut exe).await.unwrap();
assert_eq!(res, val);
}
}

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::number::Number; use crate::sql::number::Number;
use crate::sql::value::Value; use crate::sql::value::Value;
@ -13,33 +14,23 @@ impl Value {
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
) { ) -> Result<(), Error> {
match self.get(ctx, opt, exe, path).await { match self.get(ctx, opt, exe, path).await? {
Value::Number(v) => match val { Value::Number(v) => match val {
Value::Number(x) => { Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(v - x)).await,
self.set(ctx, opt, exe, path, Value::from(v - x)).await; _ => Ok(()),
()
}
_ => (),
}, },
Value::Array(v) => match val { Value::Array(v) => match val {
Value::Array(x) => { Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(v - x)).await,
self.set(ctx, opt, exe, path, Value::from(v - x)).await; 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) => { Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(Number::from(0) - x)).await; self.set(ctx, opt, exe, path, Value::from(Number::from(0) - x)).await
()
} }
_ => (), _ => Ok(()),
}, },
_ => (), _ => Ok(()),
} }
} }
} }
@ -57,7 +48,7 @@ mod tests {
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)).await; val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -67,7 +58,7 @@ mod tests {
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)).await; val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -77,7 +68,7 @@ mod tests {
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)).await; val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -87,7 +78,7 @@ mod tests {
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)).await; val.decrement(&ctx, &opt, &mut exe, &idi, Value::from(200)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -97,7 +88,7 @@ mod tests {
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]")).await; val.decrement(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300]")).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::array::Abolish; 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;
@ -16,66 +17,73 @@ impl Value {
opt: &Options<'_>, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
) { ) -> Result<(), Error> {
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 path.parts.len() { Part::Field(p) => match path.parts.len() {
1 => v.remove(&p.name), 1 => {
v.remove(&p.name);
Ok(())
}
_ => 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()).await, Some(v) if v.is_some() => v.del(ctx, opt, exe, &path.next()).await,
_ => (), _ => Ok(()),
}, },
}, },
_ => (), _ => Ok(()),
}, },
// Current path part is an array // Current path part is an array
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();
Ok(())
}
_ => { _ => {
for v in &mut v.value { for v in &mut v.value {
v.del(ctx, opt, exe, &path.next()).await v.del(ctx, opt, exe, &path.next()).await?;
} }
Ok(())
} }
}, },
Part::First => match path.parts.len() { Part::First => match path.parts.len() {
1 => { 1 => {
if v.value.len().gt(&0) { if v.value.len().gt(&0) {
v.value.remove(0); v.value.remove(0);
()
} }
Ok(())
} }
_ => match v.value.first_mut() { _ => match v.value.first_mut() {
Some(v) => v.del(ctx, opt, exe, &path.next()).await, Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => Ok(()),
}, },
}, },
Part::Last => match path.parts.len() { Part::Last => match path.parts.len() {
1 => { 1 => {
if v.value.len().gt(&0) { if v.value.len().gt(&0) {
v.value.remove(v.value.len() - 1); v.value.remove(v.value.len() - 1);
()
} }
Ok(())
} }
_ => match v.value.last_mut() { _ => match v.value.last_mut() {
Some(v) => v.del(ctx, opt, exe, &path.next()).await, Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => Ok(()),
}, },
}, },
Part::Index(i) => match path.parts.len() { Part::Index(i) => match path.parts.len() {
1 => { 1 => {
if v.value.len().gt(&i.to_usize()) { if v.value.len().gt(&i.to_usize()) {
v.value.remove(i.to_usize()); v.value.remove(i.to_usize());
()
} }
Ok(())
} }
_ => 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()).await, Some(v) => v.del(ctx, opt, exe, &path.next()).await,
None => (), None => Ok(()),
}, },
}, },
}, },
@ -83,31 +91,29 @@ impl Value {
1 => { 1 => {
let mut m = HashMap::new(); let mut m = HashMap::new();
for (i, v) in v.value.iter().enumerate() { for (i, v) in v.value.iter().enumerate() {
match w.compute(ctx, opt, exe, Some(&v)).await { if w.compute(ctx, opt, exe, Some(&v)).await?.is_truthy() {
Ok(o) if o.is_truthy() => m.insert(i, ()), m.insert(i, ());
_ => None,
}; };
} }
v.value.abolish(|i| m.contains_key(&i)) v.value.abolish(|i| m.contains_key(&i));
Ok(())
} }
_ => { _ => {
for v in &mut v.value { for v in &mut v.value {
match w.compute(ctx, opt, exe, Some(&v)).await { if w.compute(ctx, opt, exe, Some(&v)).await?.is_truthy() {
Ok(o) if o.is_truthy() => { v.del(ctx, opt, exe, &path.next()).await?;
v.del(ctx, opt, exe, &path.next()).await
} }
_ => (),
};
} }
Ok(())
} }
}, },
_ => (), _ => Ok(()),
}, },
// Ignore everything else // Ignore everything else
_ => (), _ => Ok(()),
}, },
// We are done // We are done
None => (), None => Ok(()),
} }
} }
} }
@ -122,12 +128,10 @@ mod tests {
#[tokio::test] #[tokio::test]
async 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::default();
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -137,7 +141,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -147,7 +151,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -157,7 +161,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -167,7 +171,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -177,7 +181,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -187,7 +191,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -197,7 +201,7 @@ mod tests {
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -207,7 +211,7 @@ mod tests {
let idi = Idiom::parse("test.something[WHERE age > 35].age"); let idi = Idiom::parse("test.something[WHERE age > 35].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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -217,7 +221,7 @@ mod tests {
let idi = Idiom::parse("test.something[WHERE age > 35]"); let idi = Idiom::parse("test.something[WHERE age > 35]");
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).await; val.del(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -1,12 +1,18 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
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;
impl Value { impl Value {
pub async fn first(&self, ctx: &Runtime, opt: &Options<'_>, exe: &mut Executor) -> Self { pub async fn first(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
) -> Result<Self, Error> {
self.get(ctx, opt, exe, &Idiom::from(vec![Part::First])).await self.get(ctx, opt, exe, &Idiom::from(vec![Part::First])).await
} }
} }

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
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;
@ -16,7 +17,7 @@ impl Value {
opt: &Options<'_>, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
) -> Self { ) -> Result<Self, Error> {
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 {
@ -24,49 +25,46 @@ impl Value {
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()).await, Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Ok(Value::None),
}, },
_ => Value::None, _ => Ok(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 => { Part::All => {
let mut a = Vec::new(); let mut a = Vec::new();
for v in &v.value { for v in &v.value {
a.push(v.get(ctx, opt, exe, &path.next()).await) a.push(v.get(ctx, opt, exe, &path.next()).await?)
} }
a.into() Ok(a.into())
} }
Part::First => match v.value.first() { Part::First => match v.value.first() {
Some(v) => v.get(ctx, opt, exe, &path.next()).await, Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Ok(Value::None),
}, },
Part::Last => match v.value.last() { Part::Last => match v.value.last() {
Some(v) => v.get(ctx, opt, exe, &path.next()).await, Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Ok(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()).await, Some(v) => v.get(ctx, opt, exe, &path.next()).await,
None => Value::None, None => Ok(Value::None),
}, },
Part::Where(w) => { Part::Where(w) => {
let mut a = Vec::new(); let mut a = Vec::new();
for v in &v.value { for v in &v.value {
match w.compute(ctx, opt, exe, Some(&v)).await { if w.compute(ctx, opt, exe, Some(&v)).await?.is_truthy() {
Ok(x) if x.is_truthy() => { a.push(v.get(ctx, opt, exe, &path.next()).await?)
a.push(v.get(ctx, opt, exe, &path.next()).await)
} }
_ => (),
};
} }
a.into() Ok(a.into())
} }
_ => Value::None, _ => Ok(Value::None),
}, },
// Current path part is a thing // Current path part is a thing
Value::Thing(v) => match path.parts.len() { Value::Thing(v) => match path.parts.len() {
// No remote embedded fields, so just return this // No remote embedded fields, so just return this
1 => Value::Thing(v.clone()), 1 => Ok(Value::Thing(v.clone())),
// Remote embedded field, so fetch the thing // Remote embedded field, so fetch the thing
_ => { _ => {
let stm = SelectStatement { let stm = SelectStatement {
@ -76,15 +74,15 @@ impl Value {
}; };
match stm.compute(ctx, opt, exe, None).await { match stm.compute(ctx, opt, exe, None).await {
Ok(v) => v.get(ctx, opt, exe, &path.next()).await, Ok(v) => v.get(ctx, opt, exe, &path.next()).await,
Err(_) => Value::None, Err(_) => Ok(Value::None),
} }
} }
}, },
// Ignore everything else // Ignore everything else
_ => Value::None, _ => Ok(Value::None),
}, },
// No more parts so get the value // No more parts so get the value
None => self.clone(), None => Ok(self.clone()),
} }
} }
} }
@ -100,11 +98,9 @@ mod tests {
#[tokio::test] #[tokio::test]
async 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::default();
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -113,7 +109,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, Value::from(123)); assert_eq!(res, Value::from(123));
} }
@ -122,7 +118,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!( assert_eq!(
res, res,
Value::from(Thing { Value::from(Thing {
@ -137,7 +133,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, Value::from(456)); assert_eq!(res, Value::from(456));
} }
@ -146,7 +142,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!( assert_eq!(
res, res,
Value::from(Thing { Value::from(Thing {
@ -161,7 +157,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, Value::from(36)); assert_eq!(res, Value::from(36));
} }
@ -170,7 +166,7 @@ mod tests {
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, Value::from(vec![34, 36])); assert_eq!(res, Value::from(vec![34, 36]));
} }
@ -179,7 +175,7 @@ mod tests {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35].age"); let idi = Idiom::parse("test.something[WHERE age > 35].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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, Value::from(vec![36])); assert_eq!(res, Value::from(vec![36]));
} }
@ -188,7 +184,7 @@ mod tests {
let (ctx, opt, mut exe) = mock(); let (ctx, opt, mut exe) = mock();
let idi = Idiom::parse("test.something[WHERE age > 35]"); let idi = Idiom::parse("test.something[WHERE age > 35]");
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).await; let res = val.get(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!( assert_eq!(
res, res,
Value::from(vec![Value::from(map! { Value::from(vec![Value::from(map! {

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::number::Number; use crate::sql::number::Number;
use crate::sql::value::Value; use crate::sql::value::Value;
@ -13,40 +14,24 @@ impl Value {
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
) { ) -> Result<(), Error> {
match self.get(ctx, opt, exe, path).await { match self.get(ctx, opt, exe, path).await? {
Value::Number(v) => match val { Value::Number(v) => match val {
Value::Number(x) => { Value::Number(x) => self.set(ctx, opt, exe, path, Value::from(v + x)).await,
self.set(ctx, opt, exe, path, Value::from(v + x)).await; _ => Ok(()),
()
}
_ => (),
}, },
Value::Array(v) => match val { Value::Array(v) => match val {
Value::Array(x) => { Value::Array(x) => self.set(ctx, opt, exe, path, Value::from(v + x)).await,
self.set(ctx, opt, exe, path, Value::from(v + x)).await; 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) => { Value::Number(x) => {
self.set(ctx, opt, exe, path, Value::from(Number::from(0) + x)).await; 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;
()
} }
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,
}, },
_ => (), _ => Ok(()),
} }
} }
} }
@ -64,7 +49,7 @@ mod tests {
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)).await; val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -74,7 +59,7 @@ mod tests {
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)).await; val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -84,7 +69,7 @@ mod tests {
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)).await; val.increment(&ctx, &opt, &mut exe, &idi, Value::from(10)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -94,7 +79,7 @@ mod tests {
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)).await; val.increment(&ctx, &opt, &mut exe, &idi, Value::from(200)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -104,7 +89,9 @@ mod tests {
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]")).await; val.increment(&ctx, &opt, &mut exe, &idi, Value::parse("[100, 300, 400, 500]"))
.await
.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
} }

View file

@ -1,12 +1,18 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
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;
impl Value { impl Value {
pub async fn last(&self, ctx: &Runtime, opt: &Options<'_>, exe: &mut Executor) -> Self { pub async fn last(
&self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
) -> Result<Self, Error> {
self.get(ctx, opt, exe, &Idiom::from(vec![Part::Last])).await self.get(ctx, opt, exe, &Idiom::from(vec![Part::Last])).await
} }
} }

26
src/sql/value/merge.rs Normal file
View file

@ -0,0 +1,26 @@
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::object::Object;
use crate::sql::value::Value;
impl Value {
pub async fn merge(
&mut self,
ctx: &Runtime,
opt: &Options<'_>,
exe: &mut Executor,
val: &Object,
) -> Result<(), Error> {
match val.compute(ctx, opt, exe, Some(self)).await? {
Value::Object(v) => {
for (k, v) in v.value.into_iter() {
self.set(ctx, opt, exe, &k.into(), v).await?;
}
Ok(())
}
_ => unreachable!(),
}
}
}

View file

@ -1,6 +1,7 @@
pub use self::value::*; pub use self::value::*;
pub mod array; pub mod array;
pub mod clear;
pub mod decrement; pub mod decrement;
pub mod del; pub mod del;
pub mod diff; pub mod diff;
@ -9,7 +10,9 @@ pub mod first;
pub mod get; pub mod get;
pub mod increment; pub mod increment;
pub mod last; pub mod last;
pub mod merge;
pub mod object; pub mod object;
pub mod patch; pub mod patch;
pub mod replace;
pub mod set; pub mod set;
pub mod value; pub mod value;

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::idiom::Idiom; use crate::sql::idiom::Idiom;
use crate::sql::object::Object; use crate::sql::object::Object;
use crate::sql::value::Value; use crate::sql::value::Value;
@ -12,8 +13,36 @@ impl Value {
opt: &Options<'_>, opt: &Options<'_>,
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
) { ) -> Result<(), Error> {
let val = Value::from(Object::default()); let val = Value::from(Object::default());
self.set(ctx, opt, exe, path, val).await self.set(ctx, opt, exe, path, val).await
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::dbs::test::mock;
use crate::sql::test::Parse;
#[tokio::test]
async fn object_none() {
let (ctx, opt, mut exe) = mock();
let idi = Idiom::default();
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{}");
val.object(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val);
}
#[tokio::test]
async fn object_path() {
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: {} }");
val.object(&ctx, &opt, &mut exe, &idi).await.unwrap();
assert_eq!(res, val);
}
}

View file

@ -1,11 +1,18 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::operation::Operations; use crate::sql::operation::Operations;
use crate::sql::value::Value; use crate::sql::value::Value;
impl Value { impl Value {
pub fn patch(self, _: &Runtime, _: &Options, _: &mut Executor, ops: Operations) -> Self { pub async fn patch(
self &self,
_ctx: &Runtime,
_opt: &Options<'_>,
_exe: &mut Executor,
ops: Operations,
) -> Result<(), Error> {
Ok(())
} }
} }

38
src/sql/value/replace.rs Normal file
View file

@ -0,0 +1,38 @@
use crate::dbs::Executor;
use crate::dbs::Options;
use crate::dbs::Runtime;
use crate::err::Error;
use crate::sql::object::Object;
use crate::sql::value::Value;
impl Value {
pub async fn replace(
&mut self,
_ctx: &Runtime,
_opt: &Options<'_>,
_exe: &mut Executor,
val: &Object,
) -> Result<(), Error> {
// Clear all entries
*self = Value::from(val.clone());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dbs::test::mock;
use crate::sql::test::Parse;
#[tokio::test]
async fn replace() {
let (ctx, opt, mut exe) = mock();
let mut val = Value::parse("{ test: { other: null, something: 123 } }");
let res = Value::parse("{ other: true }");
let obj = Object::from(map! {String::from("other") => Value::from(true) });
val.replace(&ctx, &opt, &mut exe, &obj).await.unwrap();
assert_eq!(res, val);
}
}

View file

@ -1,6 +1,7 @@
use crate::dbs::Executor; use crate::dbs::Executor;
use crate::dbs::Options; use crate::dbs::Options;
use crate::dbs::Runtime; use crate::dbs::Runtime;
use crate::err::Error;
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;
@ -16,7 +17,7 @@ impl Value {
exe: &mut Executor, exe: &mut Executor,
path: &Idiom, path: &Idiom,
val: Value, val: Value,
) { ) -> Result<(), Error> {
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 {
@ -26,48 +27,51 @@ impl Value {
Some(v) if v.is_some() => v.set(ctx, opt, exe, &path.next(), val).await, 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).await; obj.set(ctx, opt, exe, &path.next(), val).await?;
v.insert(&p.name, obj) v.insert(&p.name, obj);
Ok(())
} }
}, },
_ => (), _ => Ok(()),
}, },
// Current path part is an array // Current path part is an array
Value::Array(v) => match p { Value::Array(v) => match p {
Part::All => { Part::All => {
for v in &mut v.value { for v in &mut v.value {
v.set(ctx, opt, exe, &path.next(), val.clone()).await v.set(ctx, opt, exe, &path.next(), val.clone()).await?;
} }
Ok(())
} }
Part::First => match v.value.first_mut() { Part::First => match v.value.first_mut() {
Some(v) => v.set(ctx, opt, exe, &path.next(), val).await, Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => Ok(()),
}, },
Part::Last => match v.value.last_mut() { Part::Last => match v.value.last_mut() {
Some(v) => v.set(ctx, opt, exe, &path.next(), val).await, Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => Ok(()),
}, },
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).await, Some(v) => v.set(ctx, opt, exe, &path.next(), val).await,
None => (), None => Ok(()),
}, },
Part::Where(w) => { Part::Where(w) => {
for v in &mut v.value { for v in &mut v.value {
match w.compute(ctx, opt, exe, Some(&v)).await { if w.compute(ctx, opt, exe, Some(&v)).await?.is_truthy() {
Ok(x) if x.is_truthy() => { v.set(ctx, opt, exe, &path.next(), val.clone()).await?;
v.set(ctx, opt, exe, &path.next(), val.clone()).await
}
_ => (),
};
} }
} }
_ => (), Ok(())
}
_ => Ok(()),
}, },
// Ignore everything else // Ignore everything else
_ => (), _ => Ok(()),
}, },
// No more parts so set the value // No more parts so set the value
None => *self = val.clone(), None => {
*self = val.clone();
Ok(())
}
} }
} }
} }
@ -82,12 +86,10 @@ mod tests {
#[tokio::test] #[tokio::test]
async 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::default();
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -97,7 +99,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -107,7 +109,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -117,7 +119,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -127,7 +129,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -137,7 +139,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(999)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -147,7 +149,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -157,7 +159,7 @@ mod tests {
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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -167,7 +169,7 @@ mod tests {
let idi = Idiom::parse("test.something[WHERE age > 35].age"); let idi = Idiom::parse("test.something[WHERE age > 35].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)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
@ -177,7 +179,7 @@ mod tests {
let idi = Idiom::parse("test.something[WHERE age > 35]"); let idi = Idiom::parse("test.something[WHERE age > 35]");
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 }, 21] } }"); let res = Value::parse("{ test: { something: [{ age: 34 }, 21] } }");
val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await; val.set(&ctx, &opt, &mut exe, &idi, Value::from(21)).await.unwrap();
assert_eq!(res, val); assert_eq!(res, val);
} }
} }