Use references where possible instead of cloning. (#478)

When trying to reduce the number of dependencies we use in the engine, I
was blocked by a few `.clone()` calls that, on inspection, turned out to
be completely unnecessary.

I have replaced those with passing by reference, and then gone on a
pedant spree. I enabled the `needless_pass_by_value` Clippy warning and
fixed it everywhere that it highlighted. In most places, this meant
adding `&`, but I also marked some types as `Copy`, which makes
pass-by-value the right move.

In one place, I replaced calls to `async_map` with `if` and `else`, to
avoid constructing closures that capture across async boundaries. This
means I could just delete `async_map`.

V3_GIT_ORIGIN_REV_ID: 6ff71f0c553b707889d89552eff3e8c001e898cc
This commit is contained in:
Samir Talwar 2024-04-18 19:35:02 +02:00 committed by hasura-bot
parent 7b510d1373
commit c7d9baaf66
41 changed files with 201 additions and 257 deletions

View File

@ -23,7 +23,6 @@ must_use_candidate = "allow"
wildcard_imports = "allow" wildcard_imports = "allow"
# disable these for now, but we should probably fix them # disable these for now, but we should probably fix them
cast_precision_loss = "allow" cast_precision_loss = "allow"
cloned_instead_of_copied = "allow"
default_trait_access = "allow" default_trait_access = "allow"
explicit_into_iter_loop = "allow" explicit_into_iter_loop = "allow"
explicit_iter_loop = "allow" explicit_iter_loop = "allow"
@ -41,7 +40,6 @@ manual_string_new = "allow"
map_unwrap_or = "allow" map_unwrap_or = "allow"
match_same_arms = "allow" match_same_arms = "allow"
match_wildcard_for_single_variants = "allow" match_wildcard_for_single_variants = "allow"
needless_pass_by_value = "allow"
redundant_else = "allow" redundant_else = "allow"
result_large_err = "allow" result_large_err = "allow"
return_self_not_must_use = "allow" return_self_not_must_use = "allow"
@ -51,7 +49,6 @@ single_match_else = "allow"
struct_field_names = "allow" struct_field_names = "allow"
too_many_arguments = "allow" too_many_arguments = "allow"
too_many_lines = "allow" too_many_lines = "allow"
trivially_copy_pass_by_ref = "allow"
uninlined_format_args = "allow" uninlined_format_args = "allow"
unnecessary_box_returns = "allow" unnecessary_box_returns = "allow"
unnecessary_wraps = "allow" unnecessary_wraps = "allow"

View File

@ -73,14 +73,14 @@ pub async fn post_query(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(request): Json<ndc_models::QueryRequest>, Json(request): Json<ndc_models::QueryRequest>,
) -> Result<Json<ndc_models::QueryResponse>> { ) -> Result<Json<ndc_models::QueryResponse>> {
custom_connector::query::execute_query_request(state.borrow(), request).map(Json) custom_connector::query::execute_query_request(state.borrow(), &request).map(Json)
} }
async fn post_mutation( async fn post_mutation(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(request): Json<ndc_models::MutationRequest>, Json(request): Json<ndc_models::MutationRequest>,
) -> Result<Json<ndc_models::MutationResponse>> { ) -> Result<Json<ndc_models::MutationResponse>> {
custom_connector::mutation::execute_mutation_request(state.borrow(), request).map(Json) custom_connector::mutation::execute_mutation_request(state.borrow(), &request).map(Json)
} }
async fn post_explain( async fn post_explain(

View File

@ -9,7 +9,7 @@ type Result<A> = std::result::Result<A, (StatusCode, Json<ndc_models::ErrorRespo
pub fn execute_mutation_request( pub fn execute_mutation_request(
state: &AppState, state: &AppState,
request: ndc_models::MutationRequest, request: &ndc_models::MutationRequest,
) -> Result<ndc_models::MutationResponse> { ) -> Result<ndc_models::MutationResponse> {
let mut operation_results = vec![]; let mut operation_results = vec![];

View File

@ -16,14 +16,18 @@ use crate::{
pub type Result<A> = std::result::Result<A, (StatusCode, Json<ndc_models::ErrorResponse>)>; pub type Result<A> = std::result::Result<A, (StatusCode, Json<ndc_models::ErrorResponse>)>;
const DEFAULT_VARIABLE_SETS: &[BTreeMap<String, Value>] = &[BTreeMap::new()];
pub fn execute_query_request( pub fn execute_query_request(
state: &AppState, state: &AppState,
request: ndc_models::QueryRequest, request: &ndc_models::QueryRequest,
) -> Result<ndc_models::QueryResponse> { ) -> Result<ndc_models::QueryResponse> {
let variable_sets = request.variables.unwrap_or(vec![BTreeMap::new()]); let variable_sets: &[BTreeMap<String, Value>] = request
.variables
.as_deref()
.unwrap_or(DEFAULT_VARIABLE_SETS);
let mut row_sets = vec![]; let mut row_sets = vec![];
for variables in variable_sets.iter() { for variables in variable_sets {
let row_set = execute_query_with_variables( let row_set = execute_query_with_variables(
&request.collection, &request.collection,
&request.arguments, &request.arguments,
@ -106,6 +110,7 @@ pub(crate) fn parse_object_argument<'a>(
Ok(name_object) Ok(name_object)
} }
#[derive(Clone, Copy)]
enum Root<'a> { enum Root<'a> {
/// References to the root collection actually /// References to the root collection actually
/// refer to the current row, because the path to /// refer to the current row, because the path to
@ -272,14 +277,14 @@ fn eval_aggregate(
)) ))
}) })
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
eval_aggregate_function(function, values) eval_aggregate_function(function, &values)
} }
} }
} }
fn eval_aggregate_function( fn eval_aggregate_function(
function: &str, function: &str,
values: Vec<&serde_json::Value>, values: &[&serde_json::Value],
) -> Result<serde_json::Value> { ) -> Result<serde_json::Value> {
let int_values = values let int_values = values
.iter() .iter()
@ -416,7 +421,7 @@ fn eval_order_by_element(
element: &ndc_models::OrderByElement, element: &ndc_models::OrderByElement,
item: &Row, item: &Row,
) -> Result<serde_json::Value> { ) -> Result<serde_json::Value> {
match element.target.clone() { match &element.target {
ndc_models::OrderByTarget::Column { name, path } => { ndc_models::OrderByTarget::Column { name, path } => {
eval_order_by_column(collection_relationships, variables, state, item, path, name) eval_order_by_column(collection_relationships, variables, state, item, path, name)
} }
@ -450,9 +455,9 @@ fn eval_order_by_star_count_aggregate(
variables: &BTreeMap<String, serde_json::Value>, variables: &BTreeMap<String, serde_json::Value>,
state: &AppState, state: &AppState,
item: &BTreeMap<String, serde_json::Value>, item: &BTreeMap<String, serde_json::Value>,
path: Vec<ndc_models::PathElement>, path: &[ndc_models::PathElement],
) -> Result<serde_json::Value> { ) -> Result<serde_json::Value> {
let rows: Vec<Row> = eval_path(collection_relationships, variables, state, &path, item)?; let rows: Vec<Row> = eval_path(collection_relationships, variables, state, path, item)?;
Ok(rows.len().into()) Ok(rows.len().into())
} }
@ -461,15 +466,15 @@ fn eval_order_by_single_column_aggregate(
variables: &BTreeMap<String, serde_json::Value>, variables: &BTreeMap<String, serde_json::Value>,
state: &AppState, state: &AppState,
item: &BTreeMap<String, serde_json::Value>, item: &BTreeMap<String, serde_json::Value>,
path: Vec<ndc_models::PathElement>, path: &[ndc_models::PathElement],
column: String, column: &str,
function: String, function: &str,
) -> Result<serde_json::Value> { ) -> Result<serde_json::Value> {
let rows: Vec<Row> = eval_path(collection_relationships, variables, state, &path, item)?; let rows: Vec<Row> = eval_path(collection_relationships, variables, state, path, item)?;
let values = rows let values = rows
.iter() .iter()
.map(|row| { .map(|row| {
row.get(column.as_str()).ok_or(( row.get(column).ok_or((
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
Json(ndc_models::ErrorResponse { Json(ndc_models::ErrorResponse {
message: "invalid column name".into(), message: "invalid column name".into(),
@ -478,7 +483,7 @@ fn eval_order_by_single_column_aggregate(
)) ))
}) })
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
eval_aggregate_function(&function, values) eval_aggregate_function(function, &values)
} }
fn eval_order_by_column( fn eval_order_by_column(
@ -486,10 +491,10 @@ fn eval_order_by_column(
variables: &BTreeMap<String, serde_json::Value>, variables: &BTreeMap<String, serde_json::Value>,
state: &AppState, state: &AppState,
item: &BTreeMap<String, serde_json::Value>, item: &BTreeMap<String, serde_json::Value>,
path: Vec<ndc_models::PathElement>, path: &[ndc_models::PathElement],
name: String, name: &str,
) -> Result<serde_json::Value> { ) -> Result<serde_json::Value> {
let rows: Vec<Row> = eval_path(collection_relationships, variables, state, &path, item)?; let rows: Vec<Row> = eval_path(collection_relationships, variables, state, path, item)?;
if rows.len() > 1 { if rows.len() > 1 {
return Err(( return Err((
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
@ -500,7 +505,7 @@ fn eval_order_by_column(
)); ));
} }
match rows.first() { match rows.first() {
Some(row) => eval_column(row, name.as_str()), Some(row) => eval_column(row, name),
None => Ok(serde_json::Value::Null), None => Ok(serde_json::Value::Null),
} }
} }

View File

@ -6,7 +6,6 @@ use crate::execute::remote_joins::types::{JoinId, JoinLocations, RemoteJoin};
use crate::execute::{error, plan}; use crate::execute::{error, plan};
use crate::metadata::resolved; use crate::metadata::resolved;
use crate::schema::GDS; use crate::schema::GDS;
use crate::utils::async_map::AsyncMap;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use hasura_authn_core::Session; use hasura_authn_core::Session;
use lang_graphql as gql; use lang_graphql as gql;
@ -192,12 +191,8 @@ async fn get_execution_steps<'s>(
let mut sequence_steps = match process_response_as { let mut sequence_steps = match process_response_as {
ProcessResponseAs::CommandResponse { .. } => { ProcessResponseAs::CommandResponse { .. } => {
// A command execution node // A command execution node
let data_connector_explain = fetch_explain_from_data_connector( let data_connector_explain =
http_context, fetch_explain_from_data_connector(http_context, &ndc_request, data_connector).await;
ndc_request.clone(),
data_connector,
)
.await;
NonEmpty::new(Box::new(types::Step::CommandSelect( NonEmpty::new(Box::new(types::Step::CommandSelect(
types::CommandSelectIR { types::CommandSelectIR {
command_name: alias.to_string(), command_name: alias.to_string(),
@ -208,12 +203,8 @@ async fn get_execution_steps<'s>(
} }
ProcessResponseAs::Array { .. } | ProcessResponseAs::Object { .. } => { ProcessResponseAs::Array { .. } | ProcessResponseAs::Object { .. } => {
// A model execution node // A model execution node
let data_connector_explain = fetch_explain_from_data_connector( let data_connector_explain =
http_context, fetch_explain_from_data_connector(http_context, &ndc_request, data_connector).await;
ndc_request.clone(),
data_connector,
)
.await;
NonEmpty::new(Box::new(types::Step::ModelSelect(types::ModelSelectIR { NonEmpty::new(Box::new(types::Step::ModelSelect(types::ModelSelectIR {
model_name: alias.to_string(), model_name: alias.to_string(),
ndc_request, ndc_request,
@ -221,8 +212,7 @@ async fn get_execution_steps<'s>(
}))) })))
} }
}; };
if let Some(join_steps) = get_join_steps(alias.to_string(), join_locations, http_context).await if let Some(join_steps) = get_join_steps(join_locations, http_context).await {
{
sequence_steps.push(Box::new(types::Step::Sequence(join_steps))); sequence_steps.push(Box::new(types::Step::Sequence(join_steps)));
sequence_steps.push(Box::new(types::Step::HashJoin)); sequence_steps.push(Box::new(types::Step::HashJoin));
}; };
@ -235,7 +225,6 @@ async fn get_execution_steps<'s>(
/// TODO: Currently the steps are sequential, we should make them parallel once the executor supports it. /// TODO: Currently the steps are sequential, we should make them parallel once the executor supports it.
#[async_recursion] #[async_recursion]
async fn get_join_steps( async fn get_join_steps(
_root_field_name: String,
join_locations: JoinLocations<(RemoteJoin<'async_recursion, 'async_recursion>, JoinId)>, join_locations: JoinLocations<(RemoteJoin<'async_recursion, 'async_recursion>, JoinId)>,
http_context: &HttpContext, http_context: &HttpContext,
) -> Option<NonEmpty<Box<types::Step>>> { ) -> Option<NonEmpty<Box<types::Step>>> {
@ -248,7 +237,7 @@ async fn get_join_steps(
let ndc_request = types::NDCRequest::Query(query_request); let ndc_request = types::NDCRequest::Query(query_request);
let data_connector_explain = fetch_explain_from_data_connector( let data_connector_explain = fetch_explain_from_data_connector(
http_context, http_context,
ndc_request.clone(), &ndc_request,
remote_join.target_data_connector, remote_join.target_data_connector,
) )
.await; .await;
@ -272,7 +261,7 @@ async fn get_join_steps(
}, },
))) )))
}; };
if let Some(rest_join_steps) = get_join_steps(alias, location.rest, http_context).await { if let Some(rest_join_steps) = get_join_steps(location.rest, http_context).await {
sequence_steps.push(Box::new(types::Step::Sequence(rest_join_steps))); sequence_steps.push(Box::new(types::Step::Sequence(rest_join_steps)));
sequence_steps.push(Box::new(types::Step::HashJoin)); sequence_steps.push(Box::new(types::Step::HashJoin));
}; };
@ -314,7 +303,7 @@ fn simplify_step(step: Box<types::Step>) -> Box<types::Step> {
async fn fetch_explain_from_data_connector( async fn fetch_explain_from_data_connector(
http_context: &HttpContext, http_context: &HttpContext,
ndc_request: types::NDCRequest, ndc_request: &types::NDCRequest,
data_connector: &resolved::data_connector::DataConnectorLink, data_connector: &resolved::data_connector::DataConnectorLink,
) -> types::NDCExplainResponse { ) -> types::NDCExplainResponse {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
@ -333,39 +322,28 @@ async fn fetch_explain_from_data_connector(
headers: data_connector.headers.0.clone(), headers: data_connector.headers.0.clone(),
response_size_limit: http_context.ndc_response_size_limit, response_size_limit: http_context.ndc_response_size_limit,
}; };
{ // TODO: use capabilities from the data connector context
// TODO: use capabilities from the data connector context let capabilities = ndc_client::capabilities_get(&ndc_config).await?;
let capabilities = ndc_client::capabilities_get(&ndc_config).await?; match ndc_request {
match ndc_request { types::NDCRequest::Query(query_request) => {
types::NDCRequest::Query(query_request) => capabilities if capabilities.capabilities.query.explain.is_some() {
.capabilities ndc_client::explain_query_post(&ndc_config, query_request)
.query .await
.explain .map(Some)
.async_map(|_| { .map_err(error::Error::from)
Box::pin(async move { } else {
ndc_client::explain_query_post(&ndc_config, query_request) Ok(None)
.await }
.map_err(error::Error::from) }
}) types::NDCRequest::Mutation(mutation_request) => {
}) if capabilities.capabilities.mutation.explain.is_some() {
.await ndc_client::explain_mutation_post(&ndc_config, mutation_request)
.transpose(), .await
types::NDCRequest::Mutation(mutation_request) => capabilities .map(Some)
.capabilities .map_err(error::Error::from)
.mutation } else {
.explain Ok(None)
.async_map(|_| { }
Box::pin(async move {
ndc_client::explain_mutation_post(
&ndc_config,
mutation_request,
)
.await
.map_err(error::Error::from)
})
})
.await
.transpose(),
} }
} }
}) })

View File

@ -112,7 +112,7 @@ pub(crate) enum NDCExplainResponse {
Error(GraphQLError), Error(GraphQLError),
} }
#[derive(Serialize, Debug, PartialEq, Clone)] #[derive(Serialize, Debug, PartialEq)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(tag = "type", content = "value")] #[serde(tag = "type", content = "value")]
pub(crate) enum NDCRequest { pub(crate) enum NDCRequest {

View File

@ -83,7 +83,7 @@ pub(crate) fn generate_command_info<'n, 's>(
field: &'n normalized_ast::Field<'s, GDS>, field: &'n normalized_ast::Field<'s, GDS>,
field_call: &'n normalized_ast::FieldCall<'s, GDS>, field_call: &'n normalized_ast::FieldCall<'s, GDS>,
result_type: &QualifiedTypeReference, result_type: &QualifiedTypeReference,
result_base_type_kind: &TypeKind, result_base_type_kind: TypeKind,
command_source: &'s CommandSourceDetail, command_source: &'s CommandSourceDetail,
session_variables: &SessionVariables, session_variables: &SessionVariables,
) -> Result<CommandInfo<'s>, error::Error> { ) -> Result<CommandInfo<'s>, error::Error> {
@ -118,7 +118,7 @@ pub(crate) fn generate_command_info<'n, 's>(
// Add the name of the root command // Add the name of the root command
let mut usage_counts = UsagesCounts::new(); let mut usage_counts = UsagesCounts::new();
count_command(command_name.clone(), &mut usage_counts); count_command(command_name, &mut usage_counts);
let selection = selection_set::generate_nested_selection( let selection = selection_set::generate_nested_selection(
result_type, result_type,
@ -148,7 +148,7 @@ pub(crate) fn generate_function_based_command<'n, 's>(
field: &'n normalized_ast::Field<'s, GDS>, field: &'n normalized_ast::Field<'s, GDS>,
field_call: &'n normalized_ast::FieldCall<'s, GDS>, field_call: &'n normalized_ast::FieldCall<'s, GDS>,
result_type: &QualifiedTypeReference, result_type: &QualifiedTypeReference,
result_base_type_kind: &TypeKind, result_base_type_kind: TypeKind,
command_source: &'s CommandSourceDetail, command_source: &'s CommandSourceDetail,
session_variables: &SessionVariables, session_variables: &SessionVariables,
) -> Result<FunctionBasedCommand<'s>, error::Error> { ) -> Result<FunctionBasedCommand<'s>, error::Error> {
@ -176,7 +176,7 @@ pub(crate) fn generate_procedure_based_command<'n, 's>(
field: &'n normalized_ast::Field<'s, GDS>, field: &'n normalized_ast::Field<'s, GDS>,
field_call: &'n normalized_ast::FieldCall<'s, GDS>, field_call: &'n normalized_ast::FieldCall<'s, GDS>,
result_type: &QualifiedTypeReference, result_type: &QualifiedTypeReference,
result_base_type_kind: &TypeKind, result_base_type_kind: TypeKind,
command_source: &'s CommandSourceDetail, command_source: &'s CommandSourceDetail,
session_variables: &SessionVariables, session_variables: &SessionVariables,
) -> Result<ProcedureBasedCommand<'s>, error::Error> { ) -> Result<ProcedureBasedCommand<'s>, error::Error> {

View File

@ -175,7 +175,7 @@ pub(crate) fn build_filter_expression<'s>(
}, },
)) => { )) => {
// Add the target model being used in the usage counts // Add the target model being used in the usage counts
count_model(target_model_name.clone(), usage_counts); count_model(target_model_name, usage_counts);
let ndc_relationship_name = NDCRelationshipName::new(source_type, relationship_name)?; let ndc_relationship_name = NDCRelationshipName::new(source_type, relationship_name)?;
relationships.insert( relationships.insert(

View File

@ -67,7 +67,7 @@ pub fn generate_ir<'n, 's>(
field, field,
field_call, field_call,
result_type, result_type,
result_base_type_kind, *result_base_type_kind,
source, source,
session_variables, session_variables,
)?, )?,

View File

@ -213,7 +213,7 @@ pub(crate) fn build_ndc_order_by_element<'s>(
); );
// Add the target model being used in the usage counts // Add the target model being used in the usage counts
count_model(target_model_name.clone(), usage_counts); count_model(target_model_name, usage_counts);
// This map contains the relationships or the columns of the relationship that needs to be used for ordering. // This map contains the relationships or the columns of the relationship that needs to be used for ordering.
let argument_value_map = argument.value.as_object()?; let argument_value_map = argument.value.as_object()?;

View File

@ -88,7 +88,7 @@ pub(crate) fn process_model_predicate<'s>(
operator, operator,
} => Ok(make_permission_unary_boolean_expression( } => Ok(make_permission_unary_boolean_expression(
ndc_column.clone(), ndc_column.clone(),
operator, *operator,
&relationship_paths, &relationship_paths,
)?), )?),
resolved::model::ModelPredicate::BinaryFieldComparison { resolved::model::ModelPredicate::BinaryFieldComparison {
@ -172,7 +172,7 @@ pub(crate) fn process_model_predicate<'s>(
); );
// Add the target model being used in the usage counts // Add the target model being used in the usage counts
count_model(relationship_info.target_model_name.clone(), usage_counts); count_model(&relationship_info.target_model_name, usage_counts);
process_model_predicate( process_model_predicate(
predicate, predicate,
@ -210,7 +210,7 @@ fn make_permission_binary_boolean_expression(
fn make_permission_unary_boolean_expression( fn make_permission_unary_boolean_expression(
ndc_column: String, ndc_column: String,
operator: &ndc_models::UnaryComparisonOperator, operator: ndc_models::UnaryComparisonOperator,
relationship_paths: &Vec<NDCRelationshipName>, relationship_paths: &Vec<NDCRelationshipName>,
) -> Result<ndc_models::Expression, Error> { ) -> Result<ndc_models::Expression, Error> {
let path_elements = super::filter::build_path_elements(relationship_paths); let path_elements = super::filter::build_path_elements(relationship_paths);
@ -219,7 +219,7 @@ fn make_permission_unary_boolean_expression(
name: ndc_column, name: ndc_column,
path: path_elements, path: path_elements,
}, },
operator: *operator, operator,
}) })
} }

View File

@ -245,7 +245,7 @@ fn generate_command_rootfield_ir<'n, 's>(
field, field,
field_call, field_call,
result_type, result_type,
result_base_type_kind, *result_base_type_kind,
source, source,
session_variables, session_variables,
)?, )?,

View File

@ -60,7 +60,7 @@ pub(crate) fn select_many_generate_ir<'n, 's>(
// Add the name of the root model // Add the name of the root model
let mut usage_counts = UsagesCounts::new(); let mut usage_counts = UsagesCounts::new();
count_model(model_name.clone(), &mut usage_counts); count_model(model_name, &mut usage_counts);
for argument in field_call.arguments.values() { for argument in field_call.arguments.values() {
match argument.info.generic { match argument.info.generic {

View File

@ -112,7 +112,7 @@ pub(crate) fn select_one_generate_ir<'n, 's>(
// Add the name of the root model // Add the name of the root model
let mut usage_counts = UsagesCounts::new(); let mut usage_counts = UsagesCounts::new();
count_model(model_name.clone(), &mut usage_counts); count_model(model_name, &mut usage_counts);
let filter_clause = ResolvedFilterExpression { let filter_clause = ResolvedFilterExpression {
expression: Some(ndc_models::Expression::And { expression: Some(ndc_models::Expression::And {

View File

@ -221,7 +221,7 @@ pub(crate) fn generate_model_relationship_ir<'s>(
usage_counts: &mut UsagesCounts, usage_counts: &mut UsagesCounts,
) -> Result<FieldSelection<'s>, error::Error> { ) -> Result<FieldSelection<'s>, error::Error> {
// Add the target model being used in the usage counts // Add the target model being used in the usage counts
count_model(annotation.model_name.clone(), usage_counts); count_model(&annotation.model_name, usage_counts);
let field_call = field.field_call()?; let field_call = field.field_call()?;
let mut limit = None; let mut limit = None;
@ -335,7 +335,7 @@ pub(crate) fn generate_command_relationship_ir<'s>(
session_variables: &SessionVariables, session_variables: &SessionVariables,
usage_counts: &mut UsagesCounts, usage_counts: &mut UsagesCounts,
) -> Result<FieldSelection<'s>, error::Error> { ) -> Result<FieldSelection<'s>, error::Error> {
count_command(annotation.command_name.clone(), usage_counts); count_command(&annotation.command_name, usage_counts);
let field_call = field.field_call()?; let field_call = field.field_call()?;
let target_source = let target_source =
@ -439,7 +439,7 @@ pub(crate) fn build_local_command_relationship<'s>(
field, field,
field_call, field_call,
&annotation.target_type, &annotation.target_type,
&annotation.target_base_type_kind, annotation.target_base_type_kind,
&target_source.details, &target_source.details,
session_variables, session_variables,
)?; )?;
@ -581,7 +581,7 @@ pub(crate) fn build_remote_command_relationship<'n, 's>(
field, field,
field_call, field_call,
&annotation.target_type, &annotation.target_type,
&annotation.target_base_type_kind, annotation.target_base_type_kind,
&target_source.details, &target_source.details,
session_variables, session_variables,
)?; )?;

View File

@ -153,7 +153,7 @@ fn build_global_id_fields(
pub(crate) fn generate_nested_selection<'s>( pub(crate) fn generate_nested_selection<'s>(
qualified_type_reference: &QualifiedTypeReference, qualified_type_reference: &QualifiedTypeReference,
field_base_type_kind: &TypeKind, field_base_type_kind: TypeKind,
field: &normalized_ast::Field<'s, GDS>, field: &normalized_ast::Field<'s, GDS>,
data_connector: &'s resolved::data_connector::DataConnectorLink, data_connector: &'s resolved::data_connector::DataConnectorLink,
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>, type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
@ -232,7 +232,7 @@ pub(crate) fn generate_selection_set_ir<'s>(
})?; })?;
let nested_selection = generate_nested_selection( let nested_selection = generate_nested_selection(
field_type, field_type,
field_base_type_kind, *field_base_type_kind,
field, field,
data_connector, data_connector,
type_mappings, type_mappings,

View File

@ -131,11 +131,11 @@ fn extend_usage_count(usage_counts: UsagesCounts, all_usage_counts: &mut UsagesC
} }
} }
pub fn count_model(model: Qualified<ModelName>, all_usage_counts: &mut UsagesCounts) { pub fn count_model(model: &Qualified<ModelName>, all_usage_counts: &mut UsagesCounts) {
match all_usage_counts match all_usage_counts
.models_used .models_used
.iter_mut() .iter_mut()
.find(|element| element.model == model) .find(|element| element.model == *model)
{ {
None => { None => {
let model_count = ModelCount { let model_count = ModelCount {
@ -150,11 +150,11 @@ pub fn count_model(model: Qualified<ModelName>, all_usage_counts: &mut UsagesCou
} }
} }
pub fn count_command(command: Qualified<CommandName>, all_usage_counts: &mut UsagesCounts) { pub fn count_command(command: &Qualified<CommandName>, all_usage_counts: &mut UsagesCounts) {
match all_usage_counts match all_usage_counts
.commands_used .commands_used
.iter_mut() .iter_mut()
.find(|element| element.command == command) .find(|element| element.command == *command)
{ {
None => { None => {
let command_count = CommandCount { let command_count = CommandCount {
@ -261,7 +261,7 @@ mod tests {
fn test_counter_functions() { fn test_counter_functions() {
let mut aggregator = UsagesCounts::new(); let mut aggregator = UsagesCounts::new();
count_command( count_command(
Qualified::new("subgraph".to_string(), CommandName(identifier!("command1"))), &Qualified::new("subgraph".to_string(), CommandName(identifier!("command1"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(
@ -278,7 +278,7 @@ mod tests {
} }
); );
count_command( count_command(
Qualified::new("subgraph".to_string(), CommandName(identifier!("command1"))), &Qualified::new("subgraph".to_string(), CommandName(identifier!("command1"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(
@ -295,7 +295,7 @@ mod tests {
} }
); );
count_model( count_model(
Qualified::new("subgraph".to_string(), ModelName(identifier!("model1"))), &Qualified::new("subgraph".to_string(), ModelName(identifier!("model1"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(
@ -315,7 +315,7 @@ mod tests {
} }
); );
count_model( count_model(
Qualified::new("subgraph".to_string(), ModelName(identifier!("model1"))), &Qualified::new("subgraph".to_string(), ModelName(identifier!("model1"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(
@ -335,7 +335,7 @@ mod tests {
} }
); );
count_model( count_model(
Qualified::new("subgraph".to_string(), ModelName(identifier!("model2"))), &Qualified::new("subgraph".to_string(), ModelName(identifier!("model2"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(
@ -367,7 +367,7 @@ mod tests {
} }
); );
count_command( count_command(
Qualified::new("subgraph".to_string(), CommandName(identifier!("command2"))), &Qualified::new("subgraph".to_string(), CommandName(identifier!("command2"))),
&mut aggregator, &mut aggregator,
); );
assert_eq!( assert_eq!(

View File

@ -22,7 +22,7 @@ pub const FUNCTION_IR_VALUE_COLUMN_NAME: &str = "__value";
/// Executes a NDC operation /// Executes a NDC operation
pub async fn execute_ndc_query<'n, 's>( pub async fn execute_ndc_query<'n, 's>(
http_context: &HttpContext, http_context: &HttpContext,
query: ndc_models::QueryRequest, query: &ndc_models::QueryRequest,
data_connector: &resolved::data_connector::DataConnectorLink, data_connector: &resolved::data_connector::DataConnectorLink,
execution_span_attribute: String, execution_span_attribute: String,
field_span_attribute: String, field_span_attribute: String,
@ -61,7 +61,7 @@ pub async fn execute_ndc_query<'n, 's>(
pub(crate) async fn fetch_from_data_connector<'s>( pub(crate) async fn fetch_from_data_connector<'s>(
http_context: &HttpContext, http_context: &HttpContext,
query_request: ndc_models::QueryRequest, query_request: &ndc_models::QueryRequest,
data_connector: &resolved::data_connector::DataConnectorLink, data_connector: &resolved::data_connector::DataConnectorLink,
project_id: Option<ProjectId>, project_id: Option<ProjectId>,
) -> Result<ndc_models::QueryResponse, error::Error> { ) -> Result<ndc_models::QueryResponse, error::Error> {
@ -113,7 +113,7 @@ pub fn append_project_id_to_headers(
/// Executes a NDC mutation /// Executes a NDC mutation
pub(crate) async fn execute_ndc_mutation<'n, 's, 'ir>( pub(crate) async fn execute_ndc_mutation<'n, 's, 'ir>(
http_context: &HttpContext, http_context: &HttpContext,
query: ndc_models::MutationRequest, query: &ndc_models::MutationRequest,
data_connector: &resolved::data_connector::DataConnectorLink, data_connector: &resolved::data_connector::DataConnectorLink,
selection_set: &'n normalized_ast::SelectionSet<'s, GDS>, selection_set: &'n normalized_ast::SelectionSet<'s, GDS>,
execution_span_attribute: String, execution_span_attribute: String,
@ -192,7 +192,7 @@ pub(crate) async fn execute_ndc_mutation<'n, 's, 'ir>(
pub(crate) async fn fetch_from_data_connector_mutation<'s>( pub(crate) async fn fetch_from_data_connector_mutation<'s>(
http_context: &HttpContext, http_context: &HttpContext,
query_request: ndc_models::MutationRequest, query_request: &ndc_models::MutationRequest,
data_connector: &resolved::data_connector::DataConnectorLink, data_connector: &resolved::data_connector::DataConnectorLink,
project_id: Option<ProjectId>, project_id: Option<ProjectId>,
) -> Result<ndc_models::MutationResponse, error::Error> { ) -> Result<ndc_models::MutationResponse, error::Error> {

View File

@ -96,7 +96,7 @@ pub async fn capabilities_get(
/// https://hasura.github.io/ndc-spec/specification/explain.html?highlight=%2Fexplain#request /// https://hasura.github.io/ndc-spec/specification/explain.html?highlight=%2Fexplain#request
pub async fn explain_query_post( pub async fn explain_query_post(
configuration: &Configuration, configuration: &Configuration,
query_request: ndc_models::QueryRequest, query_request: &ndc_models::QueryRequest,
) -> Result<ndc_models::ExplainResponse, Error> { ) -> Result<ndc_models::ExplainResponse, Error> {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
tracer tracer
@ -112,7 +112,7 @@ pub async fn explain_query_post(
.map_err(|_| Error::InvalidBaseURL)?; .map_err(|_| Error::InvalidBaseURL)?;
let req_builder = client.request(reqwest::Method::POST, uri); let req_builder = client.request(reqwest::Method::POST, uri);
execute_request(configuration, req_builder.json(&query_request)).await execute_request(configuration, req_builder.json(query_request)).await
}) })
}, },
) )
@ -124,7 +124,7 @@ pub async fn explain_query_post(
/// https://hasura.github.io/ndc-spec/specification/explain.html?highlight=%2Fexplain#request-1 /// https://hasura.github.io/ndc-spec/specification/explain.html?highlight=%2Fexplain#request-1
pub async fn explain_mutation_post( pub async fn explain_mutation_post(
configuration: &Configuration, configuration: &Configuration,
mutation_request: ndc_models::MutationRequest, mutation_request: &ndc_models::MutationRequest,
) -> Result<ndc_models::ExplainResponse, Error> { ) -> Result<ndc_models::ExplainResponse, Error> {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
tracer tracer
@ -140,7 +140,7 @@ pub async fn explain_mutation_post(
.map_err(|_| Error::InvalidBaseURL)?; .map_err(|_| Error::InvalidBaseURL)?;
let req_builder = client.request(reqwest::Method::POST, uri); let req_builder = client.request(reqwest::Method::POST, uri);
execute_request(configuration, req_builder.json(&mutation_request)).await execute_request(configuration, req_builder.json(mutation_request)).await
}) })
}, },
) )
@ -152,7 +152,7 @@ pub async fn explain_mutation_post(
/// https://hasura.github.io/ndc-spec/specification/mutations/index.html /// https://hasura.github.io/ndc-spec/specification/mutations/index.html
pub async fn mutation_post( pub async fn mutation_post(
configuration: &Configuration, configuration: &Configuration,
mutation_request: ndc_models::MutationRequest, mutation_request: &ndc_models::MutationRequest,
) -> Result<ndc_models::MutationResponse, Error> { ) -> Result<ndc_models::MutationResponse, Error> {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
tracer tracer
@ -168,7 +168,7 @@ pub async fn mutation_post(
.map_err(|_| Error::InvalidBaseURL)?; .map_err(|_| Error::InvalidBaseURL)?;
let req_builder = client.request(reqwest::Method::POST, uri); let req_builder = client.request(reqwest::Method::POST, uri);
execute_request(configuration, req_builder.json(&mutation_request)).await execute_request(configuration, req_builder.json(mutation_request)).await
}) })
}, },
) )
@ -180,7 +180,7 @@ pub async fn mutation_post(
/// https://hasura.github.io/ndc-spec/specification/queries/index.html /// https://hasura.github.io/ndc-spec/specification/queries/index.html
pub async fn query_post( pub async fn query_post(
configuration: &Configuration, configuration: &Configuration,
query_request: ndc_models::QueryRequest, query_request: &ndc_models::QueryRequest,
) -> Result<ndc_models::QueryResponse, Error> { ) -> Result<ndc_models::QueryResponse, Error> {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
tracer tracer
@ -196,7 +196,7 @@ pub async fn query_post(
.map_err(|_| Error::InvalidBaseURL)?; .map_err(|_| Error::InvalidBaseURL)?;
let req_builder = client.request(reqwest::Method::POST, uri); let req_builder = client.request(reqwest::Method::POST, uri);
execute_request(configuration, req_builder.json(&query_request)).await execute_request(configuration, req_builder.json(query_request)).await
}) })
}, },
) )

View File

@ -119,7 +119,7 @@ pub struct ExecutionNode<'s> {
pub data_connector: &'s resolved::data_connector::DataConnectorLink, pub data_connector: &'s resolved::data_connector::DataConnectorLink,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum ProcessResponseAs<'ir> { pub enum ProcessResponseAs<'ir> {
Object { Object {
is_nullable: bool, is_nullable: bool,
@ -606,7 +606,7 @@ async fn execute_query_field_plan<'n, 's, 'ir>(
} }
NodeQueryPlan::NDCQueryExecution(ndc_query) => RootFieldResult::new( NodeQueryPlan::NDCQueryExecution(ndc_query) => RootFieldResult::new(
&ndc_query.process_response_as.is_nullable(), &ndc_query.process_response_as.is_nullable(),
resolve_ndc_query_execution(http_context, ndc_query, project_id).await, resolve_ndc_query_execution(http_context, &ndc_query, project_id).await,
), ),
NodeQueryPlan::RelayNodeSelect(optional_query) => RootFieldResult::new( NodeQueryPlan::RelayNodeSelect(optional_query) => RootFieldResult::new(
&optional_query.as_ref().map_or(true, |ndc_query| { &optional_query.as_ref().map_or(true, |ndc_query| {
@ -827,7 +827,7 @@ fn resolve_schema_field(
async fn resolve_ndc_query_execution( async fn resolve_ndc_query_execution(
http_context: &HttpContext, http_context: &HttpContext,
ndc_query: NDCQueryExecution<'_, '_>, ndc_query: &NDCQueryExecution<'_, '_>,
project_id: Option<ProjectId>, project_id: Option<ProjectId>,
) -> Result<json::Value, error::Error> { ) -> Result<json::Value, error::Error> {
let NDCQueryExecution { let NDCQueryExecution {
@ -839,7 +839,7 @@ async fn resolve_ndc_query_execution(
} = ndc_query; } = ndc_query;
let mut response = ndc::execute_ndc_query( let mut response = ndc::execute_ndc_query(
http_context, http_context,
execution_tree.root_node.query, &execution_tree.root_node.query,
execution_tree.root_node.data_connector, execution_tree.root_node.data_connector,
execution_span_attribute.clone(), execution_span_attribute.clone(),
field_span_attribute.clone(), field_span_attribute.clone(),
@ -851,10 +851,9 @@ async fn resolve_ndc_query_execution(
execute_join_locations( execute_join_locations(
http_context, http_context,
execution_span_attribute, execution_span_attribute,
field_span_attribute,
&mut response, &mut response,
&process_response_as, process_response_as,
execution_tree.remote_executions, &execution_tree.remote_executions,
project_id, project_id,
) )
.await?; .await?;
@ -879,7 +878,7 @@ async fn resolve_ndc_mutation_execution(
} = ndc_query; } = ndc_query;
let response = ndc::execute_ndc_mutation( let response = ndc::execute_ndc_mutation(
http_context, http_context,
query, &query,
data_connector, data_connector,
selection_set, selection_set,
execution_span_attribute, execution_span_attribute,
@ -898,6 +897,6 @@ async fn resolve_optional_ndc_select(
) -> Result<json::Value, error::Error> { ) -> Result<json::Value, error::Error> {
match optional_query { match optional_query {
None => Ok(json::Value::Null), None => Ok(json::Value::Null),
Some(ndc_query) => resolve_ndc_query_execution(http_context, ndc_query, project_id).await, Some(ndc_query) => resolve_ndc_query_execution(http_context, &ndc_query, project_id).await,
} }
} }

View File

@ -400,7 +400,7 @@ fn process_command_field_value(
pub fn process_response( pub fn process_response(
selection_set: &normalized_ast::SelectionSet<'_, GDS>, selection_set: &normalized_ast::SelectionSet<'_, GDS>,
rows_sets: Vec<ndc_models::RowSet>, rows_sets: Vec<ndc_models::RowSet>,
process_response_as: ProcessResponseAs, process_response_as: &ProcessResponseAs,
) -> Result<json::Value, error::Error> { ) -> Result<json::Value, error::Error> {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
// Post process the response to add the `__typename` fields // Post process the response to add the `__typename` fields

View File

@ -98,25 +98,24 @@ pub(crate) mod types;
#[async_recursion] #[async_recursion]
pub(crate) async fn execute_join_locations<'ir>( pub(crate) async fn execute_join_locations<'ir>(
http_context: &HttpContext, http_context: &HttpContext,
execution_span_attribute: String, execution_span_attribute: &str,
field_span_attribute: String,
lhs_response: &mut Vec<ndc_models::RowSet>, lhs_response: &mut Vec<ndc_models::RowSet>,
lhs_response_type: &ProcessResponseAs, lhs_response_type: &ProcessResponseAs,
join_locations: JoinLocations<(RemoteJoin<'async_recursion, 'ir>, JoinId)>, join_locations: &JoinLocations<(RemoteJoin<'async_recursion, 'ir>, JoinId)>,
project_id: Option<ProjectId>, project_id: Option<ProjectId>,
) -> Result<(), error::Error> ) -> Result<(), error::Error>
where where
'ir: 'async_recursion, 'ir: 'async_recursion,
{ {
let tracer = tracing_util::global_tracer(); let tracer = tracing_util::global_tracer();
for (key, location) in join_locations.locations { for (key, location) in &join_locations.locations {
// collect the join column arguments from the LHS response, also get // collect the join column arguments from the LHS response, also get
// the replacement tokens // the replacement tokens
let collect_arg_res = tracer.in_span( let collect_arg_res = tracer.in_span(
"collect_arguments", "collect_arguments",
"Collect arguments for join".into(), "Collect arguments for join".into(),
SpanVisibility::Internal, SpanVisibility::Internal,
|| collect::collect_arguments(lhs_response, lhs_response_type, &key, &location), || collect::collect_arguments(lhs_response, lhs_response_type, key, location),
)?; )?;
if let Some(CollectArgumentResult { if let Some(CollectArgumentResult {
arguments, arguments,
@ -142,9 +141,9 @@ where
|| { || {
Box::pin(execute_ndc_query( Box::pin(execute_ndc_query(
http_context, http_context,
join_node.target_ndc_ir, &join_node.target_ndc_ir,
join_node.target_data_connector, join_node.target_data_connector,
execution_span_attribute.clone(), execution_span_attribute.to_string(),
remote_alias.clone(), remote_alias.clone(),
project_id.clone(), project_id.clone(),
)) ))
@ -157,12 +156,10 @@ where
if !location.rest.locations.is_empty() { if !location.rest.locations.is_empty() {
execute_join_locations( execute_join_locations(
http_context, http_context,
execution_span_attribute.clone(), execution_span_attribute,
// TODO: is this field span correct?
field_span_attribute.clone(),
&mut target_response, &mut target_response,
&join_node.process_response_as, &join_node.process_response_as,
sub_tree, &sub_tree,
project_id.clone(), project_id.clone(),
) )
.await?; .await?;
@ -177,7 +174,7 @@ where
let rhs_response: HashMap<Argument, ndc_models::RowSet> = let rhs_response: HashMap<Argument, ndc_models::RowSet> =
join_variables_.into_iter().zip(target_response).collect(); join_variables_.into_iter().zip(target_response).collect();
join::join_responses(&key, &remote_alias, &location, lhs_response, rhs_response) join::join_responses(key, &remote_alias, location, lhs_response, &rhs_response)
}, },
)?; )?;
} }

View File

@ -137,7 +137,7 @@ fn collect_argument_from_row<'s, 'ir>(
.to_string(), .to_string(),
})?; })?;
let rows = rows_from_row_field_value(location_kind, nested_val)?; let rows = rows_from_row_field_value(*location_kind, nested_val)?;
if let Some(mut rows) = rows { if let Some(mut rows) = rows {
for (sub_key, sub_location) in &location.rest.locations { for (sub_key, sub_location) in &location.rest.locations {
for row in rows.iter_mut() { for row in rows.iter_mut() {
@ -186,7 +186,7 @@ pub(crate) fn create_argument(
} }
fn rows_from_row_field_value( fn rows_from_row_field_value(
location_kind: &LocationKind, location_kind: LocationKind,
nested_val: &ndc_models::RowFieldValue, nested_val: &ndc_models::RowFieldValue,
) -> Result<Option<Vec<IndexMap<String, ndc_models::RowFieldValue>>>, error::Error> { ) -> Result<Option<Vec<IndexMap<String, ndc_models::RowFieldValue>>>, error::Error> {
let rows: Option<Vec<IndexMap<String, ndc_models::RowFieldValue>>> = match location_kind { let rows: Option<Vec<IndexMap<String, ndc_models::RowFieldValue>>> = match location_kind {

View File

@ -21,7 +21,7 @@ pub(crate) fn join_responses(
remote_alias: &str, remote_alias: &str,
location: &Location<(RemoteJoin<'_, '_>, JoinId)>, location: &Location<(RemoteJoin<'_, '_>, JoinId)>,
lhs_response: &mut [ndc_models::RowSet], lhs_response: &mut [ndc_models::RowSet],
rhs_response: HashMap<BTreeMap<String, ValueExt>, ndc_models::RowSet>, rhs_response: &HashMap<BTreeMap<String, ValueExt>, ndc_models::RowSet>,
) -> Result<(), error::Error> { ) -> Result<(), error::Error> {
for row_set in lhs_response.iter_mut() { for row_set in lhs_response.iter_mut() {
if let Some(rows) = row_set.rows.as_mut() { if let Some(rows) = row_set.rows.as_mut() {
@ -44,8 +44,8 @@ pub(crate) fn join_responses(
location, location,
&mut command_row_parsed, &mut command_row_parsed,
remote_alias.to_owned(), remote_alias.to_owned(),
alias.to_owned(), alias,
&rhs_response, rhs_response,
)?; )?;
*command_row = json::to_value(command_row_parsed)?; *command_row = json::to_value(command_row_parsed)?;
} }
@ -59,8 +59,8 @@ pub(crate) fn join_responses(
location, location,
&mut command_row, &mut command_row,
remote_alias.to_owned(), remote_alias.to_owned(),
alias.to_owned(), alias,
&rhs_response, rhs_response,
)?; )?;
*x = ndc_models::RowFieldValue(json::to_value(command_row)?); *x = ndc_models::RowFieldValue(json::to_value(command_row)?);
} }
@ -80,8 +80,8 @@ pub(crate) fn join_responses(
location, location,
row, row,
remote_alias.to_owned(), remote_alias.to_owned(),
alias.to_owned(), alias,
&rhs_response, rhs_response,
)?; )?;
} }
}; };
@ -97,7 +97,7 @@ fn follow_location_and_insert_value(
location: &Location<(RemoteJoin<'_, '_>, JoinId)>, location: &Location<(RemoteJoin<'_, '_>, JoinId)>,
row: &mut IndexMap<String, ndc_models::RowFieldValue>, row: &mut IndexMap<String, ndc_models::RowFieldValue>,
remote_alias: String, remote_alias: String,
key: String, key: &str,
rhs_response: &HashMap<Argument, ndc_models::RowSet>, rhs_response: &HashMap<Argument, ndc_models::RowSet>,
) -> Result<(), error::Error> { ) -> Result<(), error::Error> {
match &location.join_node { match &location.join_node {
@ -109,7 +109,7 @@ fn follow_location_and_insert_value(
} }
JoinNode::Local(location_kind) => { JoinNode::Local(location_kind) => {
let row_field_val = let row_field_val =
row.get_mut(&key) row.get_mut(key)
.ok_or(error::InternalEngineError::InternalGeneric { .ok_or(error::InternalEngineError::InternalGeneric {
description: "unexpected: could not find {key} in row".into(), description: "unexpected: could not find {key} in row".into(),
})?; })?;
@ -130,7 +130,7 @@ fn follow_location_and_insert_value(
sub_location, sub_location,
inner_row, inner_row,
remote_alias.to_string(), remote_alias.to_string(),
sub_key.to_string(), sub_key,
rhs_response, rhs_response,
)?; )?;
} }
@ -152,7 +152,7 @@ fn follow_location_and_insert_value(
sub_location, sub_location,
inner_row, inner_row,
remote_alias.to_string(), remote_alias.to_string(),
sub_key.to_string(), sub_key,
rhs_response, rhs_response,
)? )?
} }
@ -171,7 +171,7 @@ fn follow_location_and_insert_value(
sub_location, sub_location,
&mut inner_row, &mut inner_row,
remote_alias.to_string(), remote_alias.to_string(),
sub_key.to_string(), sub_key,
rhs_response, rhs_response,
)? )?
} }

View File

@ -32,7 +32,7 @@ pub(crate) fn generate_select_many_arguments(
// insert limit argument // insert limit argument
if let Some(limit_field) = &model.graphql_api.limit_field { if let Some(limit_field) = &model.graphql_api.limit_field {
let limit_argument = generate_int_input_argument( let limit_argument = generate_int_input_argument(
limit_field.field_name.to_string(), limit_field.field_name.as_str(),
Annotation::Input(types::InputAnnotation::Model( Annotation::Input(types::InputAnnotation::Model(
ModelInputAnnotation::ModelLimitArgument, ModelInputAnnotation::ModelLimitArgument,
)), )),
@ -46,7 +46,7 @@ pub(crate) fn generate_select_many_arguments(
// insert offset argument // insert offset argument
if let Some(offset_field) = &model.graphql_api.offset_field { if let Some(offset_field) = &model.graphql_api.offset_field {
let offset_argument = generate_int_input_argument( let offset_argument = generate_int_input_argument(
offset_field.field_name.to_string(), offset_field.field_name.as_str(),
Annotation::Input(types::InputAnnotation::Model( Annotation::Input(types::InputAnnotation::Model(
ModelInputAnnotation::ModelOffsetArgument, ModelInputAnnotation::ModelOffsetArgument,
)), )),
@ -153,10 +153,10 @@ pub(crate) fn select_many_field(
/// Generates the input field for the arguments which are of type int. /// Generates the input field for the arguments which are of type int.
pub(crate) fn generate_int_input_argument( pub(crate) fn generate_int_input_argument(
name: String, name: &str,
annotation: Annotation, annotation: Annotation,
) -> Result<gql_schema::InputField<GDS>, crate::schema::Error> { ) -> Result<gql_schema::InputField<GDS>, crate::schema::Error> {
let input_field_name = resolved::types::mk_name(&name)?; let input_field_name = resolved::types::mk_name(name)?;
Ok(gql_schema::InputField::new( Ok(gql_schema::InputField::new(
input_field_name, input_field_name,
None, None,

View File

@ -151,7 +151,7 @@ pub enum ApolloFederationRootFields {
Service, Service,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Display, Copy)] #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Display)]
pub enum TypeKind { pub enum TypeKind {
Scalar, Scalar,
Object, Object,

View File

@ -1,5 +1,5 @@
pub mod async_map;
pub mod json_ext; pub mod json_ext;
use serde::{de::DeserializeOwned, ser::SerializeMap, Deserialize, Serialize}; use serde::{de::DeserializeOwned, ser::SerializeMap, Deserialize, Serialize};
use std::{collections::HashMap, hash::Hash}; use std::{collections::HashMap, hash::Hash};

View File

@ -1,31 +0,0 @@
use axum::async_trait;
use futures::Future;
use std::pin::Pin;
#[async_trait]
pub trait AsyncMap<T, U, F>
where
F: FnOnce(T) -> Pin<Box<dyn Future<Output = U> + Send>> + Send,
{
type Output;
async fn async_map(self, map: F) -> Self::Output;
}
#[async_trait]
impl<T, U, F> AsyncMap<T, U, F> for std::option::Option<T>
where
T: Send,
U: Send,
F: 'static + FnOnce(T) -> Pin<Box<dyn Future<Output = U> + Send>> + Send,
{
type Output = std::option::Option<U>;
async fn async_map(self, map: F) -> Self::Output {
match self {
Some(t) => {
let u = map(t).await;
Some(u)
}
None => None,
}
}
}

View File

@ -427,13 +427,13 @@ fn in_curly_braces(strings: Vec<String>) -> String {
"{{\n{}\n}}", "{{\n{}\n}}",
strings strings
.into_iter() .into_iter()
.map(with_indent) .map(|s| with_indent(&s))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n") .join("\n")
) )
} }
fn with_indent(sdl: String) -> String { fn with_indent(sdl: &str) -> String {
sdl.lines() sdl.lines()
.map(|l| format!(" {}", l)) .map(|l| format!(" {}", l))
.collect::<Vec<String>>() .collect::<Vec<String>>()

View File

@ -596,18 +596,13 @@ fn collect_accessible_types<S: schema::SchemaContext>(
// insert query root always to accessible types // insert query root always to accessible types
// then collect other accessible types // then collect other accessible types
accessible_types.insert(schema.query_type.clone()); accessible_types.insert(schema.query_type.clone());
collect_accessible_types_( collect_accessible_types_(namespace, schema, &schema.query_type, accessible_types);
namespace,
schema,
schema.query_type.clone(),
accessible_types,
);
// insert mutation root always to accessible types if it exists in schema // insert mutation root always to accessible types if it exists in schema
// and collect related accessible types // and collect related accessible types
if let Some(mutation_type) = &schema.mutation_type { if let Some(mutation_type) = &schema.mutation_type {
accessible_types.insert(mutation_type.clone()); accessible_types.insert(mutation_type.clone());
collect_accessible_types_(namespace, schema, mutation_type.clone(), accessible_types); collect_accessible_types_(namespace, schema, mutation_type, accessible_types);
} }
} }
@ -615,10 +610,10 @@ fn collect_accessible_types<S: schema::SchemaContext>(
fn collect_accessible_types_<S: schema::SchemaContext>( fn collect_accessible_types_<S: schema::SchemaContext>(
namespace: &S::Namespace, namespace: &S::Namespace,
schema: &schema::Schema<S>, schema: &schema::Schema<S>,
current_type_name: ast::TypeName, current_type_name: &ast::TypeName,
accessible_types: &mut HashSet<TypeName>, accessible_types: &mut HashSet<TypeName>,
) { ) {
let current_type = schema.types.get(&current_type_name); let current_type = schema.types.get(current_type_name);
match current_type { match current_type {
Some(schema::TypeInfo::Object(object)) => { Some(schema::TypeInfo::Object(object)) => {
for namespaced_fields in object.fields.values() { for namespaced_fields in object.fields.values() {
@ -631,7 +626,7 @@ fn collect_accessible_types_<S: schema::SchemaContext>(
collect_accessible_types_( collect_accessible_types_(
namespace, namespace,
schema, schema,
input_field_type_name.clone(), input_field_type_name,
accessible_types, accessible_types,
) )
} }
@ -643,7 +638,7 @@ fn collect_accessible_types_<S: schema::SchemaContext>(
collect_accessible_types_( collect_accessible_types_(
namespace, namespace,
schema, schema,
field_type_name.clone(), field_type_name,
accessible_types, accessible_types,
); );
} }
@ -659,7 +654,7 @@ fn collect_accessible_types_<S: schema::SchemaContext>(
collect_accessible_types_( collect_accessible_types_(
namespace, namespace,
schema, schema,
input_field_type_name.clone(), input_field_type_name,
accessible_types, accessible_types,
) )
} }

View File

@ -23,7 +23,7 @@ pub mod string;
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// ]; // ];
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum Punctuation { pub enum Punctuation {
// ! // !
Bang, Bang,

View File

@ -1,4 +1,3 @@
use core::slice::Iter;
use std::cmp::min; use std::cmp::min;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use thiserror::Error; use thiserror::Error;
@ -75,8 +74,8 @@ fn num_bytes_in_char(first_byte: u8) -> usize {
} }
} }
fn is_whitespace(b: &u8) -> bool { fn is_whitespace(b: u8) -> bool {
*b == b' ' || *b == b'\t' b == b' ' || b == b'\t'
} }
struct Line { struct Line {
@ -94,8 +93,8 @@ impl Line {
self.start = min(self.start + count, self.end); self.start = min(self.start + count, self.end);
} }
fn iter<'a>(&self, bytes: &'a [u8]) -> Iter<'a, u8> { fn iter<'bytes>(&self, bytes: &'bytes [u8]) -> impl Iterator<Item = u8> + 'bytes {
bytes[self.start..self.end].iter() bytes[self.start..self.end].iter().copied()
} }
fn append_to(&self, bytes: &[u8], s: &mut String) { fn append_to(&self, bytes: &[u8], s: &mut String) {
@ -179,7 +178,7 @@ fn parse_block_string(bytes: &[u8]) -> Result<(String, Consumed, usize), (Error,
.skip(1) .skip(1)
// Don't consider whitespace only lines // Don't consider whitespace only lines
.filter_map(|line| { .filter_map(|line| {
let indent = line.iter(bytes).take_while(|b| is_whitespace(b)).count(); let indent = line.iter(bytes).take_while(|b| is_whitespace(*b)).count();
(indent < line.len()).then_some(indent) (indent < line.len()).then_some(indent)
}) })
// The minimum of all indents would be the common indent // The minimum of all indents would be the common indent

View File

@ -427,7 +427,7 @@ impl<'a> Parser<'a> {
{ {
let start = self.parse_punctuation(start_token)?; let start = self.parse_punctuation(start_token)?;
let mut items = vec![]; let mut items = vec![];
let end_token_ = &lexer::Token::Punctuation(end_token.clone()); let end_token_ = &lexer::Token::Punctuation(end_token);
while !self.is_next_token(end_token_) { while !self.is_next_token(end_token_) {
items.push(parse(self)?); items.push(parse(self)?);
} }
@ -451,7 +451,7 @@ impl<'a> Parser<'a> {
where where
F: Fn(&mut Self) -> Result<T>, F: Fn(&mut Self) -> Result<T>,
{ {
if self.is_next_token(&lexer::Token::Punctuation(start_token.clone())) { if self.is_next_token(&lexer::Token::Punctuation(start_token)) {
Ok(Some(self.parse_delimited_list_helper( Ok(Some(self.parse_delimited_list_helper(
start_token, start_token,
end_token, end_token,

View File

@ -105,7 +105,7 @@ pub fn check_fragment_cycles<'q>(
executable::Selection::FragmentSpread(spread) => { executable::Selection::FragmentSpread(spread) => {
let fragment_name = &spread.fragment_name.item; let fragment_name = &spread.fragment_name.item;
if fragment_path.contains(fragment_name) { if fragment_path.contains(fragment_name) {
let mut path = fragment_path.iter().cloned().cloned().collect::<Vec<_>>(); let mut path = fragment_path.iter().copied().cloned().collect::<Vec<_>>();
path.push(fragment_name.clone()); path.push(fragment_name.clone());
return Err(Error::CycleDetected(path)); return Err(Error::CycleDetected(path));
} }

View File

@ -230,7 +230,7 @@ where
directives, directives,
}; };
if cannonical_field.reachable { if cannonical_field.reachable {
field_calls.insert(reachability.iter().cloned().cloned().collect(), field_call); field_calls.insert(reachability.iter().copied().cloned().collect(), field_call);
} }
alias_selection_sets.push((reachability, selection_sets)); alias_selection_sets.push((reachability, selection_sets));
} }

View File

@ -10,8 +10,8 @@ use std::{
use expect_test::expect_file; use expect_test::expect_file;
#[cfg(test)] #[cfg(test)]
fn test_parser_for_schema(schema_path: PathBuf) -> Result<(), io::Error> { fn test_parser_for_schema(schema_path: &Path) -> Result<(), io::Error> {
let schema = fs::read_to_string(schema_path.as_path())?; let schema = fs::read_to_string(schema_path)?;
let expected_ast_path = schema_path.with_extension("ast.txt"); let expected_ast_path = schema_path.with_extension("ast.txt");
match fs::read_to_string(expected_ast_path.as_path()) { match fs::read_to_string(expected_ast_path.as_path()) {
Err(io_error) => { Err(io_error) => {
@ -62,7 +62,7 @@ fn test_schema_parser() -> Result<(), io::Error> {
dir_entry.path().extension().map(|e| e.to_str()), dir_entry.path().extension().map(|e| e.to_str()),
Some(Some("graphql")) Some(Some("graphql"))
) { ) {
test_parser_for_schema(dir_entry.path())?; test_parser_for_schema(&dir_entry.path())?;
} }
} }
Ok(()) Ok(())

View File

@ -33,19 +33,19 @@ impl EnumTagType {
} }
} }
pub fn impl_opendd_enum(impl_style: EnumImplStyle, variants: Vec<EnumVariant<'_>>) -> TraitImpls { pub fn impl_opendd_enum(impl_style: EnumImplStyle, variants: &[EnumVariant<'_>]) -> TraitImpls {
let (tag, deserialize_exp, json_schema_expr) = match impl_style { let (tag, deserialize_exp, json_schema_expr) = match impl_style {
EnumImplStyle::UntaggedWithKind => ( EnumImplStyle::UntaggedWithKind => (
"kind".to_string(), "kind".to_string(),
impl_deserialize_as_untagged(&variants), impl_deserialize_as_untagged(variants),
impl_json_schema_untagged(&variants), impl_json_schema_untagged(variants),
), ),
EnumImplStyle::Tagged(tag_kind) => { EnumImplStyle::Tagged(tag_kind) => {
let tag_type = EnumTagType::new(&tag_kind); let tag_type = EnumTagType::new(&tag_kind);
( (
tag_type.generate_tag(), tag_type.generate_tag(),
impl_deserialize_as_tagged(&variants, &tag_type), impl_deserialize_as_tagged(variants, &tag_type),
impl_json_schema_tagged(&variants, &tag_type), impl_json_schema_tagged(variants, &tag_type),
) )
} }
}; };
@ -228,8 +228,8 @@ fn impl_json_schema_untagged(variants: &[EnumVariant<'_>]) -> proc_macro2::Token
open_dds::traits::gen_subschema_for::<#ty>(gen) open_dds::traits::gen_subschema_for::<#ty>(gen)
} }
}) })
.collect(); .collect::<Vec<_>>();
helpers::variant_subschemas(false, schemas) helpers::variant_subschemas(false, &schemas)
} }
fn impl_json_schema_tagged( fn impl_json_schema_tagged(
@ -303,9 +303,9 @@ fn impl_json_schema_tagged(
}} }}
}) })
.collect(); .collect::<Vec<_>>();
helpers::variant_subschemas(unique_names.len() == count, variant_schemas) helpers::variant_subschemas(unique_names.len() == count, &variant_schemas)
} }
EnumTagType::Adjacent { tag, content } => { EnumTagType::Adjacent { tag, content } => {
let mut unique_names = std::collections::HashSet::new(); let mut unique_names = std::collections::HashSet::new();
@ -317,7 +317,7 @@ fn impl_json_schema_tagged(
count += 1; count += 1;
let name = &variant.renamed_variant; let name = &variant.renamed_variant;
let schema = helpers::schema_object(quote! { let schema = helpers::schema_object(&quote! {
instance_type: Some(schemars::schema::InstanceType::String.into()), instance_type: Some(schemars::schema::InstanceType::String.into()),
enum_values: Some(vec![#name.into()]), enum_values: Some(vec![#name.into()]),
}); });
@ -325,7 +325,7 @@ fn impl_json_schema_tagged(
let content_schema = quote! { let content_schema = quote! {
open_dds::traits::gen_subschema_for::<#ty>(gen) open_dds::traits::gen_subschema_for::<#ty>(gen)
}; };
helpers::schema_object(quote! { helpers::schema_object(&quote! {
instance_type: Some(schemars::schema::InstanceType::Object.into()), instance_type: Some(schemars::schema::InstanceType::Object.into()),
object: Some(Box::new(schemars::schema::ObjectValidation { object: Some(Box::new(schemars::schema::ObjectValidation {
properties: { properties: {
@ -345,9 +345,9 @@ fn impl_json_schema_tagged(
})), })),
}) })
}) })
.collect(); .collect::<Vec<_>>();
helpers::variant_subschemas(unique_names.len() == count, variant_schemas) helpers::variant_subschemas(unique_names.len() == count, &variant_schemas)
} }
} }
} }

View File

@ -84,7 +84,7 @@ fn none_if_empty(s: String) -> Option<String> {
} }
pub fn apply_schema_metadata( pub fn apply_schema_metadata(
schema_expr: proc_macro2::TokenStream, schema_expr: &proc_macro2::TokenStream,
json_schema_metadata: JsonSchemaMetadata, json_schema_metadata: JsonSchemaMetadata,
) -> proc_macro2::TokenStream { ) -> proc_macro2::TokenStream {
let title = json_schema_metadata.title; let title = json_schema_metadata.title;
@ -117,7 +117,7 @@ pub fn apply_schema_metadata(
} }
} }
pub fn schema_object(properties: proc_macro2::TokenStream) -> proc_macro2::TokenStream { pub fn schema_object(properties: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
quote! { quote! {
schemars::schema::Schema::Object( schemars::schema::Schema::Object(
schemars::schema::SchemaObject { schemars::schema::SchemaObject {
@ -131,17 +131,17 @@ pub fn schema_object(properties: proc_macro2::TokenStream) -> proc_macro2::Token
/// be done for most tagging regimes by checking that all tag names are unique. /// be done for most tagging regimes by checking that all tag names are unique.
pub fn variant_subschemas( pub fn variant_subschemas(
unique: bool, unique: bool,
schemas: Vec<proc_macro2::TokenStream>, schemas: &[proc_macro2::TokenStream],
) -> proc_macro2::TokenStream { ) -> proc_macro2::TokenStream {
if unique { if unique {
schema_object(quote! { schema_object(&quote! {
subschemas: Some(Box::new(schemars::schema::SubschemaValidation { subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
one_of: Some(vec![#(#schemas),*]), one_of: Some(vec![#(#schemas),*]),
..Default::default() ..Default::default()
})), })),
}) })
} else { } else {
schema_object(quote! { schema_object(&quote! {
subschemas: Some(Box::new(schemars::schema::SubschemaValidation { subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
any_of: Some(vec![#(#schemas),*]), any_of: Some(vec![#(#schemas),*]),
..Default::default() ..Default::default()

View File

@ -12,14 +12,14 @@ use crate::container::*;
#[proc_macro_derive(OpenDd, attributes(opendd))] #[proc_macro_derive(OpenDd, attributes(opendd))]
pub fn derive(input_tok: TokenStream) -> TokenStream { pub fn derive(input_tok: TokenStream) -> TokenStream {
let input = parse_macro_input!(input_tok as DeriveInput); let input = parse_macro_input!(input_tok as DeriveInput);
impl_opendd(input) impl_opendd(&input)
.unwrap_or_else(syn::Error::into_compile_error) .unwrap_or_else(syn::Error::into_compile_error)
.into() .into()
} }
fn impl_opendd(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> { fn impl_opendd(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
let name = &input.ident; let name = &input.ident;
let cont = Container::from_derive_input(&input)?; let cont = Container::from_derive_input(input)?;
let TraitImpls { let TraitImpls {
deserialize: impl_deserialize, deserialize: impl_deserialize,
json_schema, json_schema,
@ -30,13 +30,13 @@ fn impl_opendd(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
}) })
} }
Data::Enum(EnumData::Impl(impl_style, enum_variants)) => { Data::Enum(EnumData::Impl(impl_style, enum_variants)) => {
enum_derive::impl_opendd_enum(impl_style, enum_variants) enum_derive::impl_opendd_enum(impl_style, &enum_variants)
} }
Data::Struct(struct_data) => struct_derive::impl_opendd_struct(name, struct_data), Data::Struct(struct_data) => struct_derive::impl_opendd_struct(name, &struct_data),
}; };
let json_schema_metadata = cont.json_schema_metadata; let json_schema_metadata = cont.json_schema_metadata;
let schema_name = &json_schema_metadata.schema_name.to_string(); let schema_name = &json_schema_metadata.schema_name.to_string();
let impl_json_schema = helpers::apply_schema_metadata(json_schema, json_schema_metadata); let impl_json_schema = helpers::apply_schema_metadata(&json_schema, json_schema_metadata);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
Ok(quote! { Ok(quote! {
impl #impl_generics open_dds::traits::OpenDd for #name #ty_generics #where_clause { impl #impl_generics open_dds::traits::OpenDd for #name #ty_generics #where_clause {

View File

@ -3,7 +3,7 @@ use quote::quote;
use crate::container::*; use crate::container::*;
use crate::helpers; use crate::helpers;
pub fn impl_opendd_struct(name: &syn::Ident, data: StructData<'_>) -> TraitImpls { pub fn impl_opendd_struct(name: &syn::Ident, data: &StructData<'_>) -> TraitImpls {
let (impl_deserialize, json_schema_expr) = match &data { let (impl_deserialize, json_schema_expr) = match &data {
StructData::Newtype(field) => ( StructData::Newtype(field) => (
quote! { quote! {
@ -185,7 +185,7 @@ fn impl_json_schema_named_fields(fields: &[NamedField<'_>]) -> proc_macro2::Toke
let mut required = schemars::Set::new(); let mut required = schemars::Set::new();
}; };
let schema_object = helpers::schema_object(quote! { let schema_object = helpers::schema_object(&quote! {
instance_type: Some(schemars::schema::InstanceType::Object.into()), instance_type: Some(schemars::schema::InstanceType::Object.into()),
object: Some(Box::new(schemars::schema::ObjectValidation{ object: Some(Box::new(schemars::schema::ObjectValidation{
properties, properties,

View File

@ -1,15 +1,19 @@
use crate::traceable::{ErrorVisibility, Traceable, TraceableError};
use http::HeaderMap;
use opentelemetry::{
global::{self, BoxedTracer},
trace::{get_active_span, FutureExt, SpanRef, TraceContextExt, Tracer as OtelTracer},
Context, Key,
};
use opentelemetry_http::HeaderExtractor;
use std::borrow::Cow; use std::borrow::Cow;
use std::{collections::HashMap, future::Future, pin::Pin}; use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
#[derive(derive_more::Display)] use http::HeaderMap;
use opentelemetry::global::{self, BoxedTracer};
use opentelemetry::trace::{
get_active_span, FutureExt, SpanRef, TraceContextExt, Tracer as OtelTracer,
};
use opentelemetry::{Context, Key};
use opentelemetry_http::HeaderExtractor;
use crate::traceable::{ErrorVisibility, Traceable, TraceableError};
#[derive(Clone, Copy, derive_more::Display)]
pub enum SpanVisibility { pub enum SpanVisibility {
#[display(fmt = "internal")] #[display(fmt = "internal")]
Internal, Internal,
@ -17,6 +21,7 @@ pub enum SpanVisibility {
User, User,
} }
#[derive(Clone, Copy)]
pub enum AttributeVisibility { pub enum AttributeVisibility {
Default, Default,
Internal, Internal,