Skip to content

Commit

Permalink
Project node's selection result into dependent's field selection
Browse files Browse the repository at this point in the history
- Change `FieldSelection::matches` to mean that the current field
  selection is a subset of `SelectionResult` instead of a superset.

- Project the selected tuple into the expected cardinality.
  • Loading branch information
aqrln committed Nov 30, 2023
1 parent 23801aa commit 6ee982b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 15 deletions.
2 changes: 1 addition & 1 deletion query-engine/core/src/interpreter/interpreter_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down
5 changes: 3 additions & 2 deletions query-engine/query-structure/src/field_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
28 changes: 16 additions & 12 deletions query-engine/query-structure/src/selection_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,25 @@ impl SelectionResult {
pub fn split_into(self, field_selections: &[FieldSelection]) -> Vec<SelectionResult> {
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<Vec<ScalarFieldRef>> {
Expand Down

0 comments on commit 6ee982b

Please sign in to comment.