Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support all comparison and aggregation functions on extended json fields #99

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ This changelog documents the changes between release versions.

## [Unreleased]

### Added

- Extended JSON fields no support all comparison and aggregation functions ([#99](https://github.com/hasura/ndc-mongodb/pull/99))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Extended JSON fields no support all comparison and aggregation functions ([#99](https://github.com/hasura/ndc-mongodb/pull/99))
- Extended JSON fields now support all comparison and aggregation functions ([#99](https://github.com/hasura/ndc-mongodb/pull/99))


### Fixed

### Changed

## [1.1.0] - 2024-08-16

- Accept predicate arguments in native mutations and native queries ([#92](https://github.com/hasura/ndc-mongodb/pull/92))
Expand Down
86 changes: 86 additions & 0 deletions crates/integration-tests/src/tests/aggregation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,89 @@ async fn runs_aggregation_over_top_level_fields() -> anyhow::Result<()> {
);
Ok(())
}

#[tokio::test]
async fn aggregates_extended_json_representing_mixture_of_numeric_types() -> anyhow::Result<()> {
// Skip this test in MongoDB 5 because the example fails there. We're getting an error:
//
// > Kind: Command failed: Error code 5491300 (Location5491300): $documents' is not allowed in user requests, labels: {}
//
// This doesn't affect native queries that don't use the $documents stage.
if let Ok(image) = std::env::var("MONGODB_IMAGE") {
if image == "mongo:5" {
return Ok(());
}
}

assert_yaml_snapshot!(
graphql_query(
r#"
query ($types: String!) {
extendedJsonTestDataAggregate(
filter_input: { where: { type: { _regex: $types } } }
) {
value {
_avg
_count
_max
_min
_sum
_count_distinct
}
}
extendedJsonTestData(where: { type: { _regex: $types } }) {
type
value
}
}
"#
)
.variables(json!({ "types": "decimal|double|int|long" }))
.run()
.await?
);
Ok(())
}

#[tokio::test]
async fn aggregates_mixture_of_numeric_and_null_values() -> anyhow::Result<()> {
// Skip this test in MongoDB 5 because the example fails there. We're getting an error:
//
// > Kind: Command failed: Error code 5491300 (Location5491300): $documents' is not allowed in user requests, labels: {}
//
// This doesn't affect native queries that don't use the $documents stage.
if let Ok(image) = std::env::var("MONGODB_IMAGE") {
if image == "mongo:5" {
return Ok(());
}
}

assert_yaml_snapshot!(
graphql_query(
r#"
query ($types: String!) {
extendedJsonTestDataAggregate(
filter_input: { where: { type: { _regex: $types } } }
) {
value {
_avg
_count
_max
_min
_sum
_count_distinct
}
}
extendedJsonTestData(where: { type: { _regex: $types } }) {
type
value
}
}
"#
)
.variables(json!({ "types": "double|null" }))
.run()
.await?
);
Ok(())
}
35 changes: 35 additions & 0 deletions crates/integration-tests/src/tests/filtering.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use insta::assert_yaml_snapshot;
use serde_json::json;

use crate::graphql_query;

#[tokio::test]
async fn filters_on_extended_json_using_string_comparison() -> anyhow::Result<()> {
// Skip this test in MongoDB 5 because the example fails there. We're getting an error:
//
// > Kind: Command failed: Error code 5491300 (Location5491300): $documents' is not allowed in user requests, labels: {}
//
// This doesn't affect native queries that don't use the $documents stage.
if let Ok(image) = std::env::var("MONGODB_IMAGE") {
if image == "mongo:5" {
return Ok(());
}
}

assert_yaml_snapshot!(
graphql_query(
r#"
query Filtering {
extendedJsonTestData(where: { value: { _regex: "hello" } }) {
type
value
}
}
"#
)
.variables(json!({ "types": "double|null" }))
.run()
.await?
);
Ok(())
}
1 change: 1 addition & 0 deletions crates/integration-tests/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

mod aggregation;
mod basic;
mod filtering;
mod local_relationship;
mod native_mutation;
mod native_query;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
source: crates/integration-tests/src/tests/aggregation.rs
expression: "graphql_query(r#\"\n query ($types: String!) {\n extendedJsonTestDataAggregate(\n filter_input: { where: { type: { _regex: $types } } }\n ) {\n value {\n _avg\n _count\n _max\n _min\n _sum\n _count_distinct\n }\n }\n extendedJsonTestData(where: { type: { _regex: $types } }) {\n type\n value\n }\n }\n \"#).variables(json!({\n \"types\": \"decimal|double|int|long\"\n })).run().await?"
---
data:
extendedJsonTestDataAggregate:
value:
_avg:
$numberDecimal: "4.5"
_count: 8
_max:
$numberLong: "8"
_min:
$numberDecimal: "1"
_sum:
$numberDecimal: "36"
_count_distinct: 8
extendedJsonTestData:
- type: decimal
value:
$numberDecimal: "1"
- type: decimal
value:
$numberDecimal: "2"
- type: double
value:
$numberDouble: "3.0"
- type: double
value:
$numberDouble: "4.0"
- type: int
value:
$numberInt: "5"
- type: int
value:
$numberInt: "6"
- type: long
value:
$numberLong: "7"
- type: long
value:
$numberLong: "8"
errors: ~
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
source: crates/integration-tests/src/tests/aggregation.rs
expression: "graphql_query(r#\"\n query ($types: String!) {\n extendedJsonTestDataAggregate(\n filter_input: { where: { type: { _regex: $types } } }\n ) {\n value {\n _avg\n _count\n _max\n _min\n _sum\n _count_distinct\n }\n }\n extendedJsonTestData(where: { type: { _regex: $types } }) {\n type\n value\n }\n }\n \"#).variables(json!({\n \"types\": \"double|null\"\n })).run().await?"
---
data:
extendedJsonTestDataAggregate:
value:
_avg:
$numberDouble: "3.5"
_count: 2
_max:
$numberDouble: "4.0"
_min:
$numberDouble: "3.0"
_sum:
$numberDouble: "7.0"
_count_distinct: 2
extendedJsonTestData:
- type: double
value:
$numberDouble: "3.0"
- type: double
value:
$numberDouble: "4.0"
- type: "null"
value: ~
errors: ~
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: crates/integration-tests/src/tests/filtering.rs
expression: "graphql_query(r#\"\n query Filtering {\n extendedJsonTestData(where: { value: { _regex: \"hello\" } }) {\n type\n value\n }\n }\n \"#).variables(json!({\n \"types\": \"double|null\"\n })).run().await?"
---
data:
extendedJsonTestData:
- type: string
value: "hello, world!"
errors: ~
43 changes: 41 additions & 2 deletions crates/mongodb-agent-common/src/scalar_types_capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,51 @@ pub fn scalar_types() -> BTreeMap<ndc_models::ScalarTypeName, ScalarType> {
}

fn extended_json_scalar_type() -> (ndc_models::ScalarTypeName, ScalarType) {
// Extended JSON could be anything, so allow all aggregation functions
let aggregation_functions = enum_iterator::all::<AggregationFunction>();

// Extended JSON could be anything, so allow all comparison operators
let comparison_operators = enum_iterator::all::<ComparisonFunction>();

let ext_json_type = Type::Named {
name: mongodb_support::EXTENDED_JSON_TYPE_NAME.into(),
};

(
mongodb_support::EXTENDED_JSON_TYPE_NAME.into(),
ScalarType {
representation: Some(TypeRepresentation::JSON),
aggregate_functions: BTreeMap::new(),
comparison_operators: BTreeMap::new(),
aggregate_functions: aggregation_functions
.into_iter()
.map(|aggregation_function| {
let name = aggregation_function.graphql_name().into();
let result_type = match aggregation_function {
AggregationFunction::Avg => ext_json_type.clone(),
AggregationFunction::Count => bson_to_named_type(S::Int),
AggregationFunction::Min => ext_json_type.clone(),
AggregationFunction::Max => ext_json_type.clone(),
AggregationFunction::Sum => ext_json_type.clone(),
};
let definition = AggregateFunctionDefinition { result_type };
(name, definition)
})
.collect(),
comparison_operators: comparison_operators
.into_iter()
.map(|comparison_fn| {
let name = comparison_fn.graphql_name().into();
let definition = match comparison_fn {
C::Equal => ComparisonOperatorDefinition::Equal,
C::Regex | C::IRegex => ComparisonOperatorDefinition::Custom {
argument_type: bson_to_named_type(S::String),
},
_ => ComparisonOperatorDefinition::Custom {
argument_type: ext_json_type.clone(),
},
};
(name, definition)
})
.collect(),
},
)
}
Expand Down
61 changes: 59 additions & 2 deletions fixtures/hasura/chinook/metadata/chinook.hml
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,65 @@ definition:
ExtendedJSON:
representation:
type: json
aggregate_functions: {}
comparison_operators: {}
aggregate_functions:
avg:
result_type:
type: named
name: ExtendedJSON
count:
result_type:
type: named
name: Int
max:
result_type:
type: named
name: ExtendedJSON
min:
result_type:
type: named
name: ExtendedJSON
sum:
result_type:
type: named
name: ExtendedJSON
comparison_operators:
_eq:
type: equal
_gt:
type: custom
argument_type:
type: named
name: ExtendedJSON
_gte:
type: custom
argument_type:
type: named
name: ExtendedJSON
_iregex:
type: custom
argument_type:
type: named
name: String
_lt:
type: custom
argument_type:
type: named
name: ExtendedJSON
_lte:
type: custom
argument_type:
type: named
name: ExtendedJSON
_neq:
type: custom
argument_type:
type: named
name: ExtendedJSON
_regex:
type: custom
argument_type:
type: named
name: String
Int:
representation:
type: int32
Expand Down
2 changes: 1 addition & 1 deletion fixtures/hasura/chinook/subgraph.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
kind: Subgraph
version: v1
version: v2
definition:
generator:
rootPath: .
Expand Down
Loading
Loading