Ensure chained future
values have access to current document context (#1939)
This commit is contained in:
parent
53212b23be
commit
531e75a5b0
8 changed files with 68 additions and 38 deletions
|
@ -225,7 +225,7 @@ impl Iterator {
|
|||
Value::Function(f) if f.is_aggregate() => {
|
||||
let x = vals
|
||||
.all()
|
||||
.get(ctx, opt, txn, v.to_idiom().as_ref())
|
||||
.get(ctx, opt, txn, None, v.to_idiom().as_ref())
|
||||
.await?;
|
||||
let x = f.aggregate(x).compute(ctx, opt, txn, None).await?;
|
||||
obj.set(ctx, opt, txn, v.to_idiom().as_ref(), x).await?;
|
||||
|
@ -241,7 +241,7 @@ impl Iterator {
|
|||
if let Field::Alias(v, i) = field {
|
||||
match v {
|
||||
Value::Function(f) if f.is_aggregate() => {
|
||||
let x = vals.all().get(ctx, opt, txn, i).await?;
|
||||
let x = vals.all().get(ctx, opt, txn, None, i).await?;
|
||||
let x = f.aggregate(x).compute(ctx, opt, txn, None).await?;
|
||||
obj.set(ctx, opt, txn, i, x).await?;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ impl Fields {
|
|||
};
|
||||
// Continue fetching the next idiom part
|
||||
let x = x
|
||||
.get(ctx, opt, txn, v)
|
||||
.get(ctx, opt, txn, Some(doc), v)
|
||||
.await?
|
||||
.compute(ctx, opt, txn, Some(doc))
|
||||
.await?
|
||||
|
@ -174,7 +174,7 @@ impl Fields {
|
|||
};
|
||||
// Continue fetching the next idiom part
|
||||
let x = x
|
||||
.get(ctx, opt, txn, v)
|
||||
.get(ctx, opt, txn, Some(doc), v)
|
||||
.await?
|
||||
.compute(ctx, opt, txn, Some(doc))
|
||||
.await?
|
||||
|
|
|
@ -135,7 +135,7 @@ impl Idiom {
|
|||
Some(Part::Value(v)) => {
|
||||
v.compute(ctx, opt, txn, doc)
|
||||
.await?
|
||||
.get(ctx, opt, txn, self.as_ref().next())
|
||||
.get(ctx, opt, txn, doc, self.as_ref().next())
|
||||
.await?
|
||||
.compute(ctx, opt, txn, doc)
|
||||
.await
|
||||
|
@ -143,7 +143,7 @@ impl Idiom {
|
|||
// Otherwise use the current document
|
||||
_ => match doc {
|
||||
// There is a current document
|
||||
Some(v) => v.get(ctx, opt, txn, self).await?.compute(ctx, opt, txn, doc).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, self).await?.compute(ctx, opt, txn, doc).await,
|
||||
// There isn't any document
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ impl Value {
|
|||
path: &[Part],
|
||||
val: Value,
|
||||
) -> Result<(), Error> {
|
||||
match self.get(ctx, opt, txn, path).await? {
|
||||
match self.get(ctx, opt, txn, None, path).await? {
|
||||
Value::Number(v) => match val {
|
||||
Value::Number(x) => self.set(ctx, opt, txn, path, Value::from(v - x)).await,
|
||||
_ => Ok(()),
|
||||
|
|
|
@ -15,7 +15,7 @@ impl Value {
|
|||
path: &[Part],
|
||||
val: Value,
|
||||
) -> Result<(), Error> {
|
||||
match self.get(ctx, opt, txn, path).await? {
|
||||
match self.get(ctx, opt, txn, None, path).await? {
|
||||
Value::Array(v) => match val {
|
||||
Value::Array(x) => self.set(ctx, opt, txn, path, Value::from((v + x).uniq())).await,
|
||||
x => self.set(ctx, opt, txn, path, Value::from((v + x).uniq())).await,
|
||||
|
|
|
@ -94,7 +94,7 @@ impl Value {
|
|||
.compute(ctx, opt, txn, None)
|
||||
.await?
|
||||
.all()
|
||||
.get(ctx, opt, txn, path.next())
|
||||
.get(ctx, opt, txn, None, path.next())
|
||||
.await?
|
||||
.flatten()
|
||||
.ok()?;
|
||||
|
|
|
@ -23,6 +23,7 @@ impl Value {
|
|||
ctx: &Context<'_>,
|
||||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
doc: Option<&'async_recursion Value>,
|
||||
path: &[Part],
|
||||
) -> Result<Self, Error> {
|
||||
match path.first() {
|
||||
|
@ -39,9 +40,9 @@ impl Value {
|
|||
// Ensure the future is processed
|
||||
let fut = &opt.futures(true);
|
||||
// Get the future return value
|
||||
let val = v.compute(ctx, fut, txn, None).await?;
|
||||
let val = v.compute(ctx, fut, txn, doc).await?;
|
||||
// Fetch the embedded field
|
||||
val.get(ctx, opt, txn, path).await
|
||||
val.get(ctx, opt, txn, doc, path).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,42 +53,42 @@ impl Value {
|
|||
Some(Value::Thing(Thing {
|
||||
id: Id::Object(v),
|
||||
..
|
||||
})) => Value::Object(v.clone()).get(ctx, opt, txn, path.next()).await,
|
||||
})) => Value::Object(v.clone()).get(ctx, opt, txn, doc, path.next()).await,
|
||||
Some(Value::Thing(Thing {
|
||||
id: Id::Array(v),
|
||||
..
|
||||
})) => Value::Array(v.clone()).get(ctx, opt, txn, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||
})) => Value::Array(v.clone()).get(ctx, opt, txn, doc, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, path.next()).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::Graph(_) => match v.rid() {
|
||||
Some(v) => Value::Thing(v).get(ctx, opt, txn, path).await,
|
||||
Some(v) => Value::Thing(v).get(ctx, opt, txn, doc, path).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::Field(f) => match v.get(f as &str) {
|
||||
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, path.next()).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::All => self.get(ctx, opt, txn, path.next()).await,
|
||||
Part::All => self.get(ctx, opt, txn, doc, path.next()).await,
|
||||
_ => Ok(Value::None),
|
||||
},
|
||||
// Current path part is an array
|
||||
Value::Array(v) => match p {
|
||||
Part::All => {
|
||||
let path = path.next();
|
||||
let futs = v.iter().map(|v| v.get(ctx, opt, txn, path));
|
||||
let futs = v.iter().map(|v| v.get(ctx, opt, txn, doc, path));
|
||||
try_join_all_buffered(futs).await.map(Into::into)
|
||||
}
|
||||
Part::First => match v.first() {
|
||||
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, path.next()).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::Last => match v.last() {
|
||||
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, path.next()).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::Index(i) => match v.get(i.to_usize()) {
|
||||
Some(v) => v.get(ctx, opt, txn, path.next()).await,
|
||||
Some(v) => v.get(ctx, opt, txn, doc, path.next()).await,
|
||||
None => Ok(Value::None),
|
||||
},
|
||||
Part::Where(w) => {
|
||||
|
@ -95,13 +96,13 @@ impl Value {
|
|||
let mut a = Vec::new();
|
||||
for v in v.iter() {
|
||||
if w.compute(ctx, opt, txn, Some(v)).await?.is_truthy() {
|
||||
a.push(v.get(ctx, opt, txn, path).await?)
|
||||
a.push(v.get(ctx, opt, txn, doc, path).await?)
|
||||
}
|
||||
}
|
||||
Ok(a.into())
|
||||
}
|
||||
_ => {
|
||||
let futs = v.iter().map(|v| v.get(ctx, opt, txn, path));
|
||||
let futs = v.iter().map(|v| v.get(ctx, opt, txn, doc, path));
|
||||
try_join_all_buffered(futs).await.map(Into::into)
|
||||
}
|
||||
},
|
||||
|
@ -123,7 +124,7 @@ impl Value {
|
|||
stm.compute(ctx, opt, txn, None)
|
||||
.await?
|
||||
.first()
|
||||
.get(ctx, opt, txn, path)
|
||||
.get(ctx, opt, txn, None, path)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +156,7 @@ impl Value {
|
|||
.compute(ctx, opt, txn, None)
|
||||
.await?
|
||||
.all()
|
||||
.get(ctx, opt, txn, ID.as_ref())
|
||||
.get(ctx, opt, txn, None, ID.as_ref())
|
||||
.await?
|
||||
.flatten()
|
||||
.ok(),
|
||||
|
@ -163,7 +164,7 @@ impl Value {
|
|||
.compute(ctx, opt, txn, None)
|
||||
.await?
|
||||
.all()
|
||||
.get(ctx, opt, txn, path.next())
|
||||
.get(ctx, opt, txn, None, path.next())
|
||||
.await?
|
||||
.flatten()
|
||||
.ok(),
|
||||
|
@ -179,7 +180,7 @@ impl Value {
|
|||
stm.compute(ctx, opt, txn, None)
|
||||
.await?
|
||||
.first()
|
||||
.get(ctx, opt, txn, path)
|
||||
.get(ctx, opt, txn, None, path)
|
||||
.await
|
||||
}
|
||||
},
|
||||
|
@ -209,7 +210,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::default();
|
||||
let val = Value::parse("{ test: { other: null, something: 123 } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, val);
|
||||
}
|
||||
|
||||
|
@ -218,7 +219,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something");
|
||||
let val = Value::parse("{ test: { other: null, something: 123 } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(123));
|
||||
}
|
||||
|
||||
|
@ -227,7 +228,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.other");
|
||||
let val = Value::parse("{ test: { other: test:tobie, something: 123 } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Value::from(Thing {
|
||||
|
@ -242,7 +243,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[1]");
|
||||
let val = Value::parse("{ test: { something: [123, 456, 789] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(456));
|
||||
}
|
||||
|
||||
|
@ -251,7 +252,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[1]");
|
||||
let val = Value::parse("{ test: { something: [test:tobie, test:jaime] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Value::from(Thing {
|
||||
|
@ -266,7 +267,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[1].age");
|
||||
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(36));
|
||||
}
|
||||
|
||||
|
@ -275,7 +276,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[*].age");
|
||||
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(vec![34, 36]));
|
||||
}
|
||||
|
||||
|
@ -284,7 +285,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something.age");
|
||||
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(vec![34, 36]));
|
||||
}
|
||||
|
||||
|
@ -293,7 +294,7 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[WHERE age > 35].age");
|
||||
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(res, Value::from(vec![36]));
|
||||
}
|
||||
|
||||
|
@ -302,7 +303,36 @@ mod tests {
|
|||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[WHERE age > 35]");
|
||||
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Value::from(vec![Value::from(map! {
|
||||
"age".to_string() => Value::from(36),
|
||||
})])
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_future_embedded_field() {
|
||||
let (ctx, opt, txn) = mock().await;
|
||||
let idi = Idiom::parse("test.something[WHERE age > 35]");
|
||||
let val = Value::parse("{ test: <future> { { something: [{ age: 34 }, { age: 36 }] } } }");
|
||||
let res = val.get(&ctx, &opt, &txn, None, &idi).await.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Value::from(vec![Value::from(map! {
|
||||
"age".to_string() => Value::from(36),
|
||||
})])
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_future_embedded_field_with_reference() {
|
||||
let (ctx, opt, txn) = mock().await;
|
||||
let doc = Value::parse("{ name: 'Tobie', something: [{ age: 34 }, { age: 36 }] }");
|
||||
let idi = Idiom::parse("test.something[WHERE age > 35]");
|
||||
let val = Value::parse("{ test: <future> { { something: something } } }");
|
||||
let res = val.get(&ctx, &opt, &txn, Some(&doc), &idi).await.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Value::from(vec![Value::from(map! {
|
||||
|
|
|
@ -16,7 +16,7 @@ impl Value {
|
|||
path: &[Part],
|
||||
val: Value,
|
||||
) -> Result<(), Error> {
|
||||
match self.get(ctx, opt, txn, path).await? {
|
||||
match self.get(ctx, opt, txn, None, path).await? {
|
||||
Value::Number(v) => match val {
|
||||
Value::Number(x) => self.set(ctx, opt, txn, path, Value::from(v + x)).await,
|
||||
_ => Ok(()),
|
||||
|
|
Loading…
Reference in a new issue