fix relationship collection of filter and order by clauses (#323)

This fixes a bug with collection_relationships not being populated by relationships constructed from where and/or order by clauses.

We fix this by not only collecting relationships from field selection, but also considering relationships introduced by order by and where clauses.

V3_GIT_ORIGIN_REV_ID: c612ceed8b3831257ca2c7d23ec9ed23261efedf
This commit is contained in:
Gil Mizrahi 2024-02-23 10:29:23 +02:00 committed by hasura-bot
parent d4740a08a1
commit 8071b11194
9 changed files with 131 additions and 7 deletions

View File

@ -1,5 +1,6 @@
mod commands;
mod model_selection;
mod relationships;
pub(crate) mod selection_set;
use gql::normalized_ast;

View File

@ -61,7 +61,7 @@ pub(crate) fn ndc_query_ir<'s, 'ir>(
let (query, jl) = ndc_query(&ir.command_info, join_id_counter)?;
let mut collection_relationships = BTreeMap::new();
selection_set::collect_relationships(
selection_set::collect_relationships_from_selection(
&ir.command_info.selection,
&mut collection_relationships,
)?;
@ -96,7 +96,7 @@ pub(crate) fn ndc_mutation_ir<'s, 'ir>(
)),
};
let mut collection_relationships = BTreeMap::new();
selection_set::collect_relationships(
selection_set::collect_relationships_from_selection(
&ir.command_info.selection,
&mut collection_relationships,
)?;

View File

@ -3,6 +3,7 @@
use ndc_client as ndc;
use std::collections::BTreeMap;
use super::relationships;
use super::selection_set;
use crate::execute::error;
use crate::execute::ir::model_selection::ModelSelection;
@ -43,7 +44,8 @@ pub(crate) fn ndc_ir<'s, 'ir>(
error::Error,
> {
let mut collection_relationships = BTreeMap::new();
selection_set::collect_relationships(&ir.selection, &mut collection_relationships)?;
relationships::collect_relationships(ir, &mut collection_relationships)?;
let (query, join_locations) = ndc_query(ir, join_id_counter)?;
let query_request = ndc::models::QueryRequest {
query,

View File

@ -0,0 +1,70 @@
//! NDC query generation from 'ModelSelection' IR for relationships.
use ndc_client as ndc;
use std::collections::BTreeMap;
use super::selection_set;
use crate::execute::error;
use crate::execute::ir::model_selection::ModelSelection;
use crate::execute::ir::relationship;
use crate::execute::ir::selection_set::FieldSelection;
/// collect relationships recursively from IR components containing relationships,
/// and create NDC relationship definitions which will be added to the `relationships`
/// variable.
pub(crate) fn collect_relationships(
ir: &ModelSelection<'_>,
relationships: &mut BTreeMap<String, ndc::models::Relationship>,
) -> Result<(), error::Error> {
// from selection fields
for field in ir.selection.fields.values() {
match field {
FieldSelection::Column { .. } => (),
FieldSelection::ModelRelationshipLocal {
query,
name,
relationship_info,
} => {
relationships.insert(
name.to_string(),
relationship::process_model_relationship_definition(relationship_info)?,
);
collect_relationships(query, relationships)?;
}
FieldSelection::CommandRelationshipLocal {
ir,
name,
relationship_info,
} => {
relationships.insert(
name.to_string(),
relationship::process_command_relationship_definition(relationship_info)?,
);
selection_set::collect_relationships_from_selection(
&ir.command_info.selection,
relationships,
)?;
}
// we ignore remote relationships as we are generating relationship
// definition for one data connector
FieldSelection::ModelRelationshipRemote { .. } => (),
FieldSelection::CommandRelationshipRemote { .. } => (),
};
}
// from filter clause
for (name, relationship) in ir.filter_clause.relationships.iter() {
let result = relationship::process_model_relationship_definition(relationship)?;
relationships.insert(name.to_string(), result);
}
// from order by clause
if let Some(order_by) = &ir.order_by {
for (name, relationship) in order_by.relationships.iter() {
let result = relationship::process_model_relationship_definition(relationship)?;
relationships.insert(name.to_string(), result);
}
};
Ok(())
}

View File

@ -4,6 +4,7 @@ use std::collections::{BTreeMap, HashMap};
use super::commands;
use super::model_selection;
use super::relationships;
use super::ProcessResponseAs;
use crate::execute::error;
use crate::execute::ir::relationship;
@ -202,7 +203,7 @@ fn make_hasura_phantom_field(field_name: &str) -> String {
/// From the fields in `ResultSelectionSet`, collect relationships recursively
/// and create NDC relationship definitions
pub(crate) fn collect_relationships(
pub(crate) fn collect_relationships_from_selection(
selection: &ResultSelectionSet,
relationships: &mut BTreeMap<String, ndc::models::Relationship>,
) -> Result<(), error::Error> {
@ -218,7 +219,7 @@ pub(crate) fn collect_relationships(
name.to_string(),
relationship::process_model_relationship_definition(relationship_info)?,
);
collect_relationships(&query.selection, relationships)?;
relationships::collect_relationships(query, relationships)?;
}
FieldSelection::CommandRelationshipLocal {
ir,
@ -229,7 +230,7 @@ pub(crate) fn collect_relationships(
name.to_string(),
relationship::process_command_relationship_definition(relationship_info)?,
);
collect_relationships(&ir.command_info.selection, relationships)?;
collect_relationships_from_selection(&ir.command_info.selection, relationships)?;
}
// we ignore remote relationships as we are generating relationship
// definition for one data connector

View File

@ -21,6 +21,17 @@
}
}
],
"TrackOrderByWithoutRelationshipField": [
{
"Name": "Koyaanisqatsi"
},
{
"Name": "Quintet for Horn, Violin, 2 Violas, and Cello in E Flat Major, K. 407/386c: III. Allegro"
},
{
"Name": "L'orfeo, Act 3, Sinfonia (Orchestra)"
}
],
"TrackOrderByWithFilter": [
{
"TrackId": 5,
@ -83,6 +94,17 @@
}
}
],
"TrackOrderByWithoutRelationshipField": [
{
"Name": "Koyaanisqatsi"
},
{
"Name": "Quintet for Horn, Violin, 2 Violas, and Cello in E Flat Major, K. 407/386c: III. Allegro"
},
{
"Name": "L'orfeo, Act 3, Sinfonia (Orchestra)"
}
],
"TrackOrderByWithFilter": [
{
"TrackId": 5,

View File

@ -5,6 +5,9 @@ query MyQuery {
Title
}
}
TrackOrderByWithoutRelationshipField: Track(order_by: [{Album: {ArtistId: Desc}}, {Name: Asc}], limit: 3) {
Name
}
TrackOrderByWithFilter: Track(
order_by: [{Album: {ArtistId: Asc}}, {TrackId: Desc}]
where: {Album: {Artist: {ArtistId: {_eq: 2}}}}

View File

@ -24,6 +24,17 @@
}
}
],
"TrackWithoutRelationshipField": [
{
"Name": "Fast As a Shark"
},
{
"Name": "Restless and Wild"
},
{
"Name": "Princess of the Dawn"
}
],
"TrackAnd": [
{
"AlbumId": 3,
@ -104,6 +115,17 @@
}
}
],
"TrackWithoutRelationshipField": [
{
"Name": "Fast As a Shark"
},
{
"Name": "Restless and Wild"
},
{
"Name": "Princess of the Dawn"
}
],
"TrackAnd": [
{
"AlbumId": 3,

View File

@ -6,6 +6,9 @@ query MyQuery {
Title
}
}
TrackWithoutRelationshipField: Track(where: {Album: {Title: {_eq: "Restless and Wild"}}}) {
Name
}
TrackAnd: Track(where: {_and: [{Album: {Title: {_eq: "Restless and Wild"}}}, {AlbumId: {_eq: 3}} ]} ) {
AlbumId
Name