Start of GraphQL -> OpenDD IR pipeline (#1156)

<!-- The PR description should answer 2 important questions: -->

### What

We are going to need tests for our OpenDD IR pipeline, and we are going
to need to convert GraphQL requests into OpenDD IR at some point, so
this makes the most basic `normalized_ast -> OpenDD IR QueryRequest`
pipeline and implements / tests it for the simplest possible query.

This only affects tests at this point, so is a functional no-op.

### How

This PR adds the most basic `normalized_ast -> OpenDD IR QueryRequest`
pipeline and implements / tests it for the simplest possible query.

```rust
enum TestOpenDDPipeline {
    Skip,
    GenerateOpenDDQuery,
    GenerateExecutionPlan,
}
```

It adds a flag for each engine test to opt-in for testing with the new
pipeline. Currently one passes `GenerateOpenDDQuery`, and tests the
result against a snapshot, and the rest pass `Skip`.

The unblocks two following steps:
- we can improve the GraphQL -> OpenDD IR generation, enabling more
tests by passing `GenerateOpenDDQuery`
- once the main new `plan` pipeline generates the same types as the
existing `execute` crate, we can compare the old `execute::plan` with
the new one, and enable that per test by passing
`GenerateExecutionPlan`.

Once all the tests are passing `GenerateExecutionPlan` we can remove the
flag and we know we'll have parity in plan creation.

V3_GIT_ORIGIN_REV_ID: 607dfce77b68849c7fc66fc652e38182fa0c83ea
This commit is contained in:
Daniel Harvey 2024-09-25 20:43:16 +01:00 committed by hasura-bot
parent 531dc88622
commit a3efbc98d7
8 changed files with 706 additions and 73 deletions

1
v3/Cargo.lock generated
View File

@ -1798,6 +1798,7 @@ dependencies = [
"hasura-authn-core",
"hasura-authn-noauth",
"indexmap 2.5.0",
"insta",
"json_value_merge",
"jsonapi 0.7.0",
"jsonapi 3.0.0",

View File

@ -64,12 +64,13 @@ build-data = { workspace = true } # To set short commit-sha at build time
[dev-dependencies]
criterion = { workspace = true, features = ["html_reports", "async_tokio"] }
goldenfile = { workspace = true }
insta = { workspace = true }
pretty_assertions = { workspace = true }
tokio-test = { workspace = true }
[package.metadata.cargo-machete]
ignored = [
"build-data", # cargo-machete ignores build dependencies
"build_data", "build-data" # cargo-machete ignores build dependencies
]
[lints]

View File

@ -26,6 +26,15 @@ extern crate json_value_merge;
use json_value_merge::Merge;
use serde_json::Value;
// which OpenDD IR pipeline tests should we include for this test?
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum TestOpenDDPipeline {
Skip,
GenerateOpenDDQuery,
GenerateExecutionPlan,
}
pub struct GoldenTestContext {
pub(crate) http_context: HttpContext,
pub(crate) mint: Mint,
@ -157,11 +166,13 @@ pub(crate) fn test_introspection_expectation(
pub fn test_execution_expectation(
test_path_string: &str,
common_metadata_paths: &[&str],
opendd_tests: TestOpenDDPipeline,
) -> anyhow::Result<()> {
test_execution_expectation_for_multiple_ndc_versions(
test_path_string,
common_metadata_paths,
BTreeMap::new(),
opendd_tests,
)
}
@ -170,6 +181,7 @@ pub fn test_execution_expectation_for_multiple_ndc_versions(
test_path_string: &str,
common_metadata_paths: &[&str],
common_metadata_paths_per_ndc_version: BTreeMap<NdcVersion, Vec<&str>>,
opendd_tests: TestOpenDDPipeline,
) -> anyhow::Result<()> {
tokio_test::block_on(async {
let root_test_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests");
@ -279,10 +291,20 @@ pub fn test_execution_expectation_for_multiple_ndc_versions(
None => {
let raw_request = RawRequest {
operation_name: None,
query,
query: query.clone(),
variables: None,
};
for session in &sessions {
// attempt to create open ir for this request
open_dd_pipeline_test(
opendd_tests,
&query,
&schema,
session,
raw_request.clone(),
);
// do actual test
let (_, response) = execute_query(
execute::ExposeInternalErrors::Expose,
&test_ctx.http_context,
@ -315,6 +337,15 @@ pub fn test_execution_expectation_for_multiple_ndc_versions(
query: query.clone(),
variables: Some(variables),
};
// attempt to create open ir for this request
open_dd_pipeline_test(
opendd_tests,
&query,
&schema,
session,
raw_request.clone(),
);
// do actual test
let (_, response) = execute_query(
execute::ExposeInternalErrors::Expose,
&test_ctx.http_context,
@ -375,6 +406,38 @@ pub fn test_execution_expectation_for_multiple_ndc_versions(
})
}
// generate open_dd_ir for each test and see what happens
fn open_dd_pipeline_test(
opendd_tests: TestOpenDDPipeline,
query: &str,
schema: &Schema<GDS>,
session: &Session,
raw_request: lang_graphql::http::RawRequest,
) {
match opendd_tests {
TestOpenDDPipeline::Skip => {}
TestOpenDDPipeline::GenerateOpenDDQuery => {
// parse the raw request into a GQL query
let query = graphql_frontend::parse_query(query).unwrap();
// normalize the parsed GQL query
if let Ok(normalized_request) =
graphql_frontend::normalize_request(schema, session, query, raw_request)
{
// we can only generate for queries that would have worked,
// `normalize_request` fails when we try and access a field we're not allowed to,
// for instance
let ir = graphql_frontend::to_opendd_ir(&normalized_request);
insta::assert_debug_snapshot!("opendd_ir", ir);
}
}
TestOpenDDPipeline::GenerateExecutionPlan => {
todo!("GenerateExecutionPlan not implemented yet")
}
}
}
fn read_json(path: &Path) -> anyhow::Result<Value> {
let json_string = read_to_string(path)?;
let value = serde_json::from_str(&json_string)?;

File diff suppressed because it is too large Load Diff

View File

@ -26,14 +26,22 @@ mod common;
fn test_local_relationships_model_to_model_object() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/object";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_local_relationships_model_to_model_multi_mapping() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/multi_mapping";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -45,6 +53,7 @@ fn test_local_relationships_model_to_model_array() -> anyhow::Result<()> {
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string, common_metadata_graphql_config],
common::TestOpenDDPipeline::Skip,
)
}
@ -52,7 +61,11 @@ fn test_local_relationships_model_to_model_array() -> anyhow::Result<()> {
fn test_local_relationships_model_to_model_array_with_arguments() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/array/arguments";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -64,6 +77,7 @@ fn test_relationships_array_with_arguments_with_graphql_config() -> anyhow::Resu
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string, common_metadata_graphql_config],
common::TestOpenDDPipeline::Skip,
)
}
@ -83,6 +97,7 @@ fn test_local_relationships_command_to_model() -> anyhow::Result<()> {
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -101,6 +116,7 @@ fn test_relationships_command_to_model_with_graphql_config() -> anyhow::Result<(
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -119,6 +135,7 @@ fn test_local_relationships_model_to_command() -> anyhow::Result<()> {
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -137,6 +154,7 @@ fn test_local_relationships_command_to_command() -> anyhow::Result<()> {
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -155,6 +173,7 @@ fn test_local_mutually_recursive_relationships_to_command() -> anyhow::Result<()
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -173,6 +192,7 @@ fn test_local_relationships_permissions_target_model_filter_predicate() -> anyho
vec!["execute/common_metadata/custom_connector_v02_schema.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -183,7 +203,11 @@ fn test_relationships_model_to_model_across_namespace() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/across_namespace";
let common_metadata_path_string =
"execute/relationships/across_namespace/namespaced_connectors.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -191,7 +215,11 @@ fn test_relationships_command_to_model_across_namespace() -> anyhow::Result<()>
let test_path_string = "execute/relationships/command_to_model/across_namespace";
let common_metadata_path_string =
"execute/relationships/command_to_model/across_namespace/namespaced_connectors.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -199,7 +227,11 @@ fn test_relationships_command_to_command_across_namespace() -> anyhow::Result<()
let test_path_string = "execute/relationships/command_to_command/across_namespace";
let common_metadata_path_string =
"execute/relationships/command_to_command/across_namespace/namespaced_connectors.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -218,6 +250,8 @@ fn test_remote_mutually_recursive_relationships_to_command_across_namespace() ->
vec!["execute/relationships/command_to_command/mutually_recursive_across_namespace/namespaced_connectors_v02.json"],
),
]),
common::TestOpenDDPipeline::Skip,
)
}
@ -226,35 +260,55 @@ fn test_remote_relationships_remote_object_in_local_array_1() -> anyhow::Result<
let test_path_string =
"execute/remote_relationships/remote_in_local/local_array_remote_object/two_pg_ndc";
let common_metadata_path_string = "execute/common_metadata/two_postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_remote_object_in_local_array_2() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/remote_in_local/local_array_remote_object/custom_ndc_and_pg_ndc";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_model_to_model_array() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/array";
let common_metadata_path_string = "execute/common_metadata/two_postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_model_to_model_array_aggregate() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/array/aggregate";
let common_metadata_path_string = "execute/common_metadata/two_postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_model_to_command_array() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/command/model_to_command";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
@ -268,6 +322,7 @@ fn test_remote_relationships_model_to_multiple_commands_not_nested() -> anyhow::
common::test_execution_expectation(
test_path_string,
&[multiple_commands_metadata, common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
@ -282,6 +337,7 @@ fn test_remote_relationships_model_to_multiple_commands_nested() -> anyhow::Resu
common::test_execution_expectation(
test_path_string,
&[multiple_commands_metadata, common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
@ -296,6 +352,7 @@ fn test_remote_relationships_model_to_multiple_commands_very_nested() -> anyhow:
common::test_execution_expectation(
test_path_string,
&[multiple_commands_metadata, common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
@ -304,70 +361,110 @@ fn test_remote_mutually_recursive_relationships_model_to_command() -> anyhow::Re
let test_path_string =
"execute/remote_relationships/command/model_to_command/mutually_recursive";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_model_to_model_array_with_arguments() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/array/arguments";
let common_metadata_path_string = "execute/common_metadata/two_postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_remote_in_local() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/remote_in_local";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_from_nested() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/from_nested";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_model_to_command_remote_in_local() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/command/remote_in_local";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_mutually_recursive() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/mutually_recursive";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_mutually_recursive_with_where() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/mutually_recursive_with_where";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_remote_relationships_multi_field_mapping() -> anyhow::Result<()> {
let test_path_string = "execute/remote_relationships/multi_field_mapping";
let common_metadata_path_string = "execute/common_metadata/two_connectors_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_relationships_permissions_target_model_type_permission() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/permissions/target_model_type_permission";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_relationships_permissions_source_type_permission() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/permissions/source_type_permission";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
// Miscellaneous tests
@ -382,7 +479,11 @@ fn test_relationships_permissions_target_model_type_field_not_selectable() -> an
let test_path_string =
"execute/relationships/permissions/target_model_type_field_not_selectable";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
// TODO: This should ideally be a schema test
@ -390,7 +491,11 @@ fn test_relationships_permissions_target_model_type_field_not_selectable() -> an
fn test_relationships_permissions_target_model_not_selectable() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/permissions/target_model_not_selectable";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
// What is being tested? - We are testing if unique names are being generated
@ -410,11 +515,15 @@ fn test_relationships_permissions_target_model_not_selectable() -> anyhow::Resul
fn test_relationships_with_same_name() -> anyhow::Result<()> {
let test_path_string = "execute/relationships/same_relationship_name";
let common_metadata_path_string = "execute/common_metadata/postgres_connector_schema.json";
common::test_execution_expectation(test_path_string, &[common_metadata_path_string])
common::test_execution_expectation(
test_path_string,
&[common_metadata_path_string],
common::TestOpenDDPipeline::Skip,
)
}
#[test]
fn test_relationship_with_no_relationship_capability() -> anyhow::Result<()> {
let test_path_string: &str = "execute/relationships/no_relationship_capability";
common::test_execution_expectation(test_path_string, &[])
common::test_execution_expectation(test_path_string, &[], common::TestOpenDDPipeline::Skip)
}

View File

@ -0,0 +1,94 @@
---
source: crates/engine/tests/common.rs
expression: ir
---
V1(
QueryRequestV1 {
queries: {
Alias(
Identifier(
"AuthorByID",
),
): Model(
ModelSelection {
target: ModelTarget {
subgraph: SubgraphName(
"default",
),
model_name: ModelName(
Identifier(
"Authors",
),
),
arguments: {
ArgumentName(
Identifier(
"author_id",
),
): Literal(
Number(1),
),
},
filter: None,
order_by: [],
limit: None,
offset: None,
},
selection: {
Alias(
Identifier(
"author_id",
),
): Field(
ObjectFieldSelection {
target: ObjectFieldTarget {
field_name: FieldName(
Identifier(
"author_id",
),
),
arguments: {},
},
selection: None,
},
),
Alias(
Identifier(
"first_name",
),
): Field(
ObjectFieldSelection {
target: ObjectFieldTarget {
field_name: FieldName(
Identifier(
"first_name",
),
),
arguments: {},
},
selection: None,
},
),
Alias(
Identifier(
"last_name",
),
): Field(
ObjectFieldSelection {
target: ObjectFieldTarget {
field_name: FieldName(
Identifier(
"last_name",
),
),
arguments: {},
},
selection: None,
},
),
},
},
),
},
},
)

View File

@ -1,14 +1,15 @@
mod explain;
mod query;
mod steps;
mod to_opendd_ir;
mod types;
pub use explain::execute_explain;
pub use explain::types::{redact_ndc_explain, ExplainResponse};
pub use steps::{build_ir, build_request_plan, normalize_request, parse_query};
pub use steps::{build_ir, build_request_plan, generate_ir, normalize_request, parse_query};
pub use to_opendd_ir::to_opendd_ir;
pub use query::{execute_query, execute_query_internal};
pub use steps::generate_ir;
pub use types::{GraphQLErrors, GraphQLResponse};
#[cfg(test)]

View File

@ -0,0 +1,106 @@
use graphql_schema::GDS;
use lang_graphql::ast::common::{self as ast};
use lang_graphql::normalized_ast::Operation;
use open_dds::query::{
Alias, ModelSelection, ModelTarget, ObjectFieldSelection, ObjectFieldTarget,
ObjectSubSelection, Query, QueryRequest, QueryRequestV1, Value,
};
use open_dds::{arguments::ArgumentName, identifier::Identifier};
use indexmap::IndexMap;
// given a resolved GraphQL request, turn it into OpenDD IR
pub fn to_opendd_ir(operation: &Operation<GDS>) -> QueryRequest {
if operation.ty != ast::OperationType::Query {
todo!("Convert non-queries");
}
let mut queries = IndexMap::new();
for query in operation.selection_set.fields.values() {
for field_call in query.field_calls.values() {
match field_call.info.generic {
graphql_schema::Annotation::Output(
graphql_schema::OutputAnnotation::RootField(
graphql_schema::RootFieldAnnotation::Model {
data_type: _,
source: _,
kind: _,
name,
},
),
) => {
let opendd_alias =
Alias::new(Identifier::new(field_call.name.as_str()).unwrap());
let selection = to_model_selection(&query.selection_set.fields);
let arguments = to_model_arguments(&field_call.arguments);
let query = Query::Model(ModelSelection {
selection,
target: ModelTarget {
arguments,
filter: None,
limit: None,
offset: None,
order_by: vec![],
model_name: name.name.clone(),
subgraph: name.subgraph.clone(),
},
});
queries.insert(opendd_alias, query);
}
_ => todo!("not implemented yet"),
}
}
}
QueryRequest::V1(QueryRequestV1 { queries })
}
fn to_model_arguments(
arguments: &IndexMap<ast::Name, lang_graphql::normalized_ast::InputField<GDS>>,
) -> IndexMap<ArgumentName, Value> {
let mut model_arguments = IndexMap::new();
for (name, argument) in arguments {
let argument_name = ArgumentName::new(Identifier::new(name.as_str()).unwrap());
let argument_value = open_dds::query::Value::Literal(argument.value.as_json());
model_arguments.insert(argument_name, argument_value);
}
model_arguments
}
fn to_model_selection(
fields: &IndexMap<ast::Alias, lang_graphql::normalized_ast::Field<GDS>>,
) -> IndexMap<Alias, ObjectSubSelection> {
let mut selection: IndexMap<Alias, ObjectSubSelection> = IndexMap::new();
for field in fields.values() {
let field_alias = Alias::new(Identifier::new(field.alias.0.as_str()).unwrap());
let field_name = match field.field_calls.iter().next() {
Some((_, field_call)) => match field_call.info.generic {
graphql_schema::Annotation::Output(graphql_schema::OutputAnnotation::Field {
name,
..
}) => name,
_ => todo!("only the simplest fields supported"),
},
_ => todo!("error: a field call must exist"),
};
let object_sub_selection = ObjectSubSelection::Field(ObjectFieldSelection {
selection: None,
target: ObjectFieldTarget {
field_name: field_name.clone(),
arguments: IndexMap::new(),
},
});
selection.insert(field_alias, object_sub_selection);
}
selection
}