Skip to content

Commit

Permalink
Sorting an interface by child-level entity
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilkisiela committed Mar 21, 2023
1 parent c2ba787 commit aefeff1
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 56 deletions.
51 changes: 38 additions & 13 deletions graphql/src/store/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,22 +561,47 @@ fn build_order_by(
})
}
OrderByValue::Child(parent_field_name, child_field_name) => {
if entity.is_interface() {
return Err(QueryExecutionError::OrderByNotSupportedError(
entity.name().to_owned(),
parent_field_name,
));
}
// Finds the field that connects the parent entity to the child entity.
// In the case of an interface, we need to find the field on one of the types that implement the interface,
// as the `@derivedFrom` directive is only allowed on object types.
let field = match entity {
ObjectOrInterface::Object(_) => {
sast::get_field(entity, parent_field_name.as_str()).ok_or_else(|| {
QueryExecutionError::EntityFieldError(
entity.name().to_owned(),
parent_field_name.clone(),
)
})?
}
ObjectOrInterface::Interface(_) => {
let object_types = schema
.types_for_interface()
.get(&EntityType::new(entity.name().to_string()))
.ok_or(QueryExecutionError::EntityFieldError(
entity.name().to_owned(),
parent_field_name.clone(),
))?;

let field =
sast::get_field(entity, parent_field_name.as_str()).ok_or_else(|| {
QueryExecutionError::EntityFieldError(
entity.name().to_owned(),
parent_field_name.clone(),
)
})?;
if let Some(first_entity) = object_types.first() {
sast::get_field(first_entity, parent_field_name.as_str()).ok_or_else(
|| {
QueryExecutionError::EntityFieldError(
entity.name().to_owned(),
parent_field_name.clone(),
)
},
)?
} else {
Err(QueryExecutionError::EntityFieldError(
entity.name().to_owned(),
parent_field_name.clone(),
))?
}
}
};
let derived = field.is_derived();
let base_type = field.field_type.get_base_type();

let child_entity = schema
.object_or_interface(base_type)
.ok_or_else(|| QueryExecutionError::NamedTypeError(base_type.into()))?;
Expand Down
48 changes: 43 additions & 5 deletions graphql/tests/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ fn can_query_with_sorting_by_child_interface() {
}

#[test]
fn can_not_query_interface_with_sorting_by_child_entity() {
fn can_query_interface_with_sorting_by_child_entity() {
const QUERY: &str = "
query {
desc: medias(first: 100, orderBy: author__name, orderDirection: desc) {
Expand All @@ -996,8 +996,27 @@ fn can_not_query_interface_with_sorting_by_child_entity() {
}";

run_query(QUERY, |result, _| {
// Sorting an interface by child-level entity (derived) is not supported
assert!(result.has_errors());
let author1 = object! { name: "Baden" };
let author2 = object! { name: "Goodwill" };
let desc_medias = vec![
object! { title: "Folk Tune Music Video", author: author2.clone() },
object! { title: "Rock Tune Music Video", author: author2.clone() },
object! { title: "Cheesy Tune Music Video", author: author2.clone() },
object! { title: "Pop Tune Single Cover", author: author1.clone() },
object! { title: "Rock Tune Single Cover", author: author1.clone() },
object! { title: "Cheesy Tune Single Cover", author: author1.clone() },
];
let mut asc_medias = desc_medias.clone();

asc_medias.reverse();

let exp = object! {
desc: desc_medias,
asc: asc_medias,
};

let data = extract_data!(result).unwrap();
assert_eq!(data, exp);
});
}

Expand All @@ -1020,8 +1039,27 @@ fn can_not_query_interface_with_sorting_by_derived_child_entity() {
}";

run_query(QUERY, |result, _| {
// Sorting an interface by child-level entity is not supported
assert!(result.has_errors());
let exp = object! {
desc: vec![
object! { title: "Rock Tune Music Video", song : object! { title: "Rock Tune" } },
object! { title: "Rock Tune Single Cover", song : object! { title: "Rock Tune" } },
object! { title: "Pop Tune Single Cover", song : object! { title: "Pop Tune" } },
object! { title: "Folk Tune Music Video", song : object! { title: "Folk Tune" } },
object! { title: "Cheesy Tune Music Video", song : object! { title: "Cheesy Tune" } },
object! { title: "Cheesy Tune Single Cover", song : object! { title: "Cheesy Tune" } },
],
asc: vec![
object! { title: "Cheesy Tune Single Cover", song : object! { title: "Cheesy Tune" } },
object! { title: "Cheesy Tune Music Video", song : object! { title: "Cheesy Tune" } },
object! { title: "Folk Tune Music Video", song : object! { title: "Folk Tune" } },
object! { title: "Pop Tune Single Cover", song : object! { title: "Pop Tune" } },
object! { title: "Rock Tune Single Cover", song : object! { title: "Rock Tune" } },
object! { title: "Rock Tune Music Video", song : object! { title: "Rock Tune" } },
]
};

let data = extract_data!(result).unwrap();
assert_eq!(data, exp);
});
}

Expand Down
Loading

0 comments on commit aefeff1

Please sign in to comment.