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:
parent
c86a53502d
commit
63747612e3
17 changed files with 343 additions and 169 deletions
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
44
src/sql/value/clear.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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! {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
26
src/sql/value/merge.rs
Normal 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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
38
src/sql/value/replace.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue