diff --git a/query-engine/core/src/interpreter/interpreter_impl.rs b/query-engine/core/src/interpreter/interpreter_impl.rs index 8aa3d77ae761..e3454bfe8f2e 100644 --- a/query-engine/core/src/interpreter/interpreter_impl.rs +++ b/query-engine/core/src/interpreter/interpreter_impl.rs @@ -52,7 +52,7 @@ impl ExpressionResult { let converted = match self { Self::Query(ref result) => match result { QueryResult::Id(id) => match id { - Some(id) if field_selection.matches(id) => Some(vec![id.clone()]), + Some(id) if field_selection.matches(id) => Some(vec![id.project(field_selection)]), None => Some(vec![]), Some(id) => { trace!( diff --git a/query-engine/query-structure/src/field_selection.rs b/query-engine/query-structure/src/field_selection.rs index b44529793a5a..f7998af38154 100644 --- a/query-engine/query-structure/src/field_selection.rs +++ b/query-engine/query-structure/src/field_selection.rs @@ -111,9 +111,10 @@ impl FieldSelection { } } - /// Checks if a given `SelectionResult` belongs to this `FieldSelection`. + /// Checks if a given `SelectionResult` satisfies this `FieldSelection` + /// (i.e., if the fields from `SelectionResult` are a superset of this `FieldSelection`). pub fn matches(&self, result: &SelectionResult) -> bool { - result.pairs.iter().all(|(rt, _)| self.selections.contains(rt)) + self.selections().all(|s| result.get(s).is_some()) } /// Merges all given `FieldSelection` a set union of all. diff --git a/query-engine/query-structure/src/selection_result.rs b/query-engine/query-structure/src/selection_result.rs index d6e1ef46349d..10e3f5c2211b 100644 --- a/query-engine/query-structure/src/selection_result.rs +++ b/query-engine/query-structure/src/selection_result.rs @@ -70,21 +70,25 @@ impl SelectionResult { pub fn split_into(self, field_selections: &[FieldSelection]) -> Vec { field_selections .iter() - .map(|field_selection| { - let pairs: Vec<_> = field_selection - .selections() - .map(|selected_field| { - self.get(selected_field) - .map(|value| (selected_field.clone(), value.clone())) - .expect("Error splitting `ReturnValues`: `FieldSelection` doesn't match.") - }) - .collect(); - - SelectionResult::new(pairs) - }) + .map(|field_selection| self.project(field_selection)) .collect() } + /// Projects this `SelectionResult` into a smaller or equal `SelectionResult` + /// according to the provided [`FieldSelection`]. + pub fn project(&self, field_selection: &FieldSelection) -> SelectionResult { + let pairs: Vec<_> = field_selection + .selections() + .map(|selected_field| { + self.get(selected_field) + .map(|value| (selected_field.clone(), value.clone())) + .expect("Error splitting `ReturnValues`: `FieldSelection` doesn't match.") + }) + .collect(); + + SelectionResult::new(pairs) + } + /// Checks if `self` only contains scalar field selections and if so, returns them all in a list. /// If any other selection is contained, returns `None`. pub fn as_scalar_fields(&self) -> Option> {