diff --git a/CHANGELOG.md b/CHANGELOG.md index 13b653e9..69114def 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ This changelog documents the changes between release versions. - Add root `configuration.json` or `configuration.yaml` file to allow editing cli options. ([#68](https://github.com/hasura/ndc-mongodb/pull/68)) - Update default sample size to 100. ([#68](https://github.com/hasura/ndc-mongodb/pull/68)) - Add `all_schema_nullable` option defaulted to true. ([#68](https://github.com/hasura/ndc-mongodb/pull/68)) +- Change `native_procedure` to `native_mutation` along with code renaming ([#70](https://github.com/hasura/ndc-mongodb/pull/70)) + - Note: `native_procedures` folder in configuration is not deprecated. It will continue to work for a few releases, but renaming your folder is all that is needed. ## [0.0.5] - 2024-04-26 - Fix incorrect order of results for query requests with more than 10 variable sets (#37) diff --git a/crates/configuration/src/configuration.rs b/crates/configuration/src/configuration.rs index b5a78bc3..04eecab6 100644 --- a/crates/configuration/src/configuration.rs +++ b/crates/configuration/src/configuration.rs @@ -7,7 +7,7 @@ use ndc_models as ndc; use serde::{Deserialize, Serialize}; use crate::{ - native_procedure::NativeProcedure, + native_mutation::NativeMutation, native_query::{NativeQuery, NativeQueryRepresentation}, read_directory, schema, serialized, }; @@ -28,22 +28,22 @@ pub struct Configuration { /// response. pub functions: BTreeMap, - /// Procedures are based on native procedures. - pub procedures: BTreeMap, + /// Mutations are based on native mutations. + pub mutations: BTreeMap, - /// Native procedures allow arbitrary MongoDB commands where types of results are + /// Native murations allow arbitrary MongoDB commands where types of results are /// specified via user configuration. - pub native_procedures: BTreeMap, + pub native_mutations: BTreeMap, /// Native queries allow arbitrary aggregation pipelines that can be included in a query plan. pub native_queries: BTreeMap, /// Object types defined for this connector include types of documents in each collection, - /// types for objects inside collection documents, types for native query and native procedure + /// types for objects inside collection documents, types for native query and native mutation /// arguments and results. /// /// The object types here combine object type defined in files in the `schema/`, - /// `native_queries/`, and `native_procedures/` subdirectories in the connector configuration + /// `native_queries/`, and `native_mutations/` subdirectories in the connector configuration /// directory. pub object_types: BTreeMap, @@ -53,11 +53,11 @@ pub struct Configuration { impl Configuration { pub fn validate( schema: serialized::Schema, - native_procedures: BTreeMap, + native_mutations: BTreeMap, native_queries: BTreeMap, options: ConfigurationOptions ) -> anyhow::Result { - let object_types_iter = || merge_object_types(&schema, &native_procedures, &native_queries); + let object_types_iter = || merge_object_types(&schema, &native_mutations, &native_queries); let object_type_errors = { let duplicate_type_names: Vec<&str> = object_types_iter() .map(|(name, _)| name.as_ref()) @@ -81,7 +81,7 @@ impl Configuration { .map(|(name, nq)| (name, nq.into())) .collect(); - let internal_native_procedures: BTreeMap<_, _> = native_procedures + let internal_native_mutations: BTreeMap<_, _> = native_mutations .into_iter() .map(|(name, np)| (name, np.into())) .collect(); @@ -129,12 +129,12 @@ impl Configuration { }) .partition_result(); - let procedures = internal_native_procedures + let mutations = internal_native_mutations .iter() - .map(|(name, native_procedure)| { + .map(|(name, native_mutation)| { ( name.to_owned(), - native_procedure_to_procedure_info(name, native_procedure), + native_mutation_to_mutation_info(name, native_mutation), ) }) .collect(); @@ -153,8 +153,8 @@ impl Configuration { Ok(Configuration { collections, functions, - procedures, - native_procedures: internal_native_procedures, + mutations, + native_mutations: internal_native_mutations, native_queries: internal_native_queries, object_types, options @@ -204,18 +204,18 @@ impl Default for ConfigurationIntrospectionOptions { fn merge_object_types<'a>( schema: &'a serialized::Schema, - native_procedures: &'a BTreeMap, + native_mutations: &'a BTreeMap, native_queries: &'a BTreeMap, ) -> impl Iterator { let object_types_from_schema = schema.object_types.iter(); - let object_types_from_native_procedures = native_procedures + let object_types_from_native_mutations = native_mutations .values() - .flat_map(|native_procedure| &native_procedure.object_types); + .flat_map(|native_mutation| &native_mutation.object_types); let object_types_from_native_queries = native_queries .values() .flat_map(|native_query| &native_query.object_types); object_types_from_schema - .chain(object_types_from_native_procedures) + .chain(object_types_from_native_mutations) .chain(object_types_from_native_queries) } @@ -305,15 +305,15 @@ fn function_result_type( Ok(value_field.r#type.clone().into()) } -fn native_procedure_to_procedure_info( - procedure_name: &str, - procedure: &NativeProcedure, +fn native_mutation_to_mutation_info( + mutation_name: &str, + mutation: &NativeMutation, ) -> ndc::ProcedureInfo { ndc::ProcedureInfo { - name: procedure_name.to_owned(), - description: procedure.description.clone(), - arguments: arguments_to_ndc_arguments(procedure.arguments.clone()), - result_type: procedure.result_type.clone().into(), + name: mutation_name.to_owned(), + description: mutation.description.clone(), + arguments: arguments_to_ndc_arguments(mutation.arguments.clone()), + result_type: mutation.result_type.clone().into(), } } @@ -364,9 +364,9 @@ mod tests { .into_iter() .collect(), }; - let native_procedures = [( + let native_mutations = [( "hello".to_owned(), - serialized::NativeProcedure { + serialized::NativeMutation { object_types: [( "Album".to_owned(), schema::ObjectType { @@ -385,7 +385,7 @@ mod tests { )] .into_iter() .collect(); - let result = Configuration::validate(schema, native_procedures, Default::default(), Default::default()); + let result = Configuration::validate(schema, native_mutations, Default::default(), Default::default()); let error_msg = result.unwrap_err().to_string(); assert!(error_msg.contains("multiple definitions")); assert!(error_msg.contains("Album")); diff --git a/crates/configuration/src/directory.rs b/crates/configuration/src/directory.rs index b66eee8d..75f5e30b 100644 --- a/crates/configuration/src/directory.rs +++ b/crates/configuration/src/directory.rs @@ -11,11 +11,16 @@ use tokio_stream::wrappers::ReadDirStream; use crate::{configuration::ConfigurationOptions, serialized::Schema, with_name::WithName, Configuration}; pub const SCHEMA_DIRNAME: &str = "schema"; -pub const NATIVE_PROCEDURES_DIRNAME: &str = "native_procedures"; +pub const NATIVE_MUTATIONS_DIRNAME: &str = "native_mutations"; pub const NATIVE_QUERIES_DIRNAME: &str = "native_queries"; pub const CONFIGURATION_OPTIONS_BASENAME: &str = "configuration"; pub const CONFIGURATION_OPTIONS_METADATA: &str = ".configuration_metadata"; +// Deprecated: Discussion came out that we standardize names and the decision +// was to use `native_mutations`. We should leave this in for a few releases +// with some CHANGELOG/Docs messaging around deprecation +pub const NATIVE_PROCEDURES_DIRNAME: &str = "native_procedures"; + pub const CONFIGURATION_EXTENSIONS: [(&str, FileFormat); 3] = [("json", JSON), ("yaml", YAML), ("yml", YAML)]; pub const DEFAULT_EXTENSION: &str = "json"; @@ -40,10 +45,16 @@ pub async fn read_directory( .unwrap_or_default(); let schema = schemas.into_values().fold(Schema::default(), Schema::merge); + // Deprecated see message above at NATIVE_PROCEDURES_DIRNAME let native_procedures = read_subdir_configs(&dir.join(NATIVE_PROCEDURES_DIRNAME)) .await? .unwrap_or_default(); + // TODO: Once we fully remove `native_procedures` after a deprecation period we can remove `mut` + let mut native_mutations = read_subdir_configs(&dir.join(NATIVE_MUTATIONS_DIRNAME)) + .await? + .unwrap_or_default(); + let native_queries = read_subdir_configs(&dir.join(NATIVE_QUERIES_DIRNAME)) .await? .unwrap_or_default(); @@ -51,12 +62,14 @@ pub async fn read_directory( let options = parse_configuration_options_file(dir) .await; - Configuration::validate(schema, native_procedures, native_queries, options) + native_mutations.extend(native_procedures.into_iter()); + + Configuration::validate(schema, native_mutations, native_queries, options) } /// Parse all files in a directory with one of the allowed configuration extensions according to -/// the given type argument. For example if `T` is `NativeProcedure` this function assumes that all -/// json and yaml files in the given directory should be parsed as native procedure configurations. +/// the given type argument. For example if `T` is `NativeMutation` this function assumes that all +/// json and yaml files in the given directory should be parsed as native mutation configurations. /// /// Assumes that every configuration file has a `name` field. async fn read_subdir_configs(subdir: &Path) -> anyhow::Result>> diff --git a/crates/configuration/src/lib.rs b/crates/configuration/src/lib.rs index 9a99aa3d..d7ce160f 100644 --- a/crates/configuration/src/lib.rs +++ b/crates/configuration/src/lib.rs @@ -1,6 +1,6 @@ mod configuration; mod directory; -pub mod native_procedure; +pub mod native_mutation; pub mod native_query; pub mod schema; mod serialized; diff --git a/crates/configuration/src/native_procedure.rs b/crates/configuration/src/native_mutation.rs similarity index 76% rename from crates/configuration/src/native_procedure.rs rename to crates/configuration/src/native_mutation.rs index 8062fb75..74efeb0e 100644 --- a/crates/configuration/src/native_procedure.rs +++ b/crates/configuration/src/native_mutation.rs @@ -7,14 +7,14 @@ use crate::{ serialized::{self}, }; -/// Internal representation of Native Procedures. For doc comments see -/// [crate::serialized::NativeProcedure] +/// Internal representation of Native Mutations. For doc comments see +/// [crate::serialized::NativeMutation] /// /// Note: this type excludes `name` and `object_types` from the serialized type. Object types are /// intended to be merged into one big map so should not be accessed through values of this type. /// Native query values are stored in maps so names should be taken from map keys. #[derive(Clone, Debug)] -pub struct NativeProcedure { +pub struct NativeMutation { pub result_type: Type, pub arguments: BTreeMap, pub command: bson::Document, @@ -22,9 +22,9 @@ pub struct NativeProcedure { pub description: Option, } -impl From for NativeProcedure { - fn from(value: serialized::NativeProcedure) -> Self { - NativeProcedure { +impl From for NativeMutation { + fn from(value: serialized::NativeMutation) -> Self { + NativeMutation { result_type: value.result_type, arguments: value.arguments, command: value.command, diff --git a/crates/configuration/src/serialized/mod.rs b/crates/configuration/src/serialized/mod.rs index 87ade19f..b8d91602 100644 --- a/crates/configuration/src/serialized/mod.rs +++ b/crates/configuration/src/serialized/mod.rs @@ -1,5 +1,5 @@ -mod native_procedure; +mod native_mutation; mod native_query; mod schema; -pub use self::{native_procedure::NativeProcedure, native_query::NativeQuery, schema::Schema}; +pub use self::{native_mutation::NativeMutation, native_query::NativeQuery, schema::Schema}; diff --git a/crates/configuration/src/serialized/native_procedure.rs b/crates/configuration/src/serialized/native_mutation.rs similarity index 86% rename from crates/configuration/src/serialized/native_procedure.rs rename to crates/configuration/src/serialized/native_mutation.rs index 74dfa9fe..4f0cec31 100644 --- a/crates/configuration/src/serialized/native_procedure.rs +++ b/crates/configuration/src/serialized/native_mutation.rs @@ -9,22 +9,22 @@ use crate::schema::{ObjectField, ObjectType, Type}; /// An arbitrary database command using MongoDB's runCommand API. /// See https://www.mongodb.com/docs/manual/reference/method/db.runCommand/ /// -/// Native Procedures appear as "procedures" in your data graph. +/// Native Mutations appear as "mutations" in your data graph. #[derive(Clone, Debug, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] -pub struct NativeProcedure { +pub struct NativeMutation { /// You may define object types here to reference in `result_type`. Any types defined here will /// be merged with the definitions in `schema.json`. This allows you to maintain hand-written - /// types for native procedures without having to edit a generated `schema.json` file. + /// types for native mutations without having to edit a generated `schema.json` file. #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] pub object_types: BTreeMap, - /// Type of data returned by the procedure. You may reference object types defined in the + /// Type of data returned by the mutation. You may reference object types defined in the /// `object_types` list in this definition, or you may reference object types from /// `schema.json`. pub result_type: Type, - /// Arguments to be supplied for each procedure invocation. These will be substituted into the + /// Arguments to be supplied for each mutation invocation. These will be substituted into the /// given `command`. /// /// Argument values are standard JSON mapped from GraphQL input types, not Extended JSON. @@ -40,7 +40,7 @@ pub struct NativeProcedure { /// See https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/ /// /// Keys and values in the command may contain placeholders of the form `{{variableName}}` - /// which will be substituted when the native procedure is executed according to the given + /// which will be substituted when the native mutation is executed according to the given /// arguments. /// /// Placeholders must be inside quotes so that the command can be stored in JSON format. If the diff --git a/crates/configuration/src/serialized/native_query.rs b/crates/configuration/src/serialized/native_query.rs index 2147f030..d2042384 100644 --- a/crates/configuration/src/serialized/native_query.rs +++ b/crates/configuration/src/serialized/native_query.rs @@ -66,7 +66,7 @@ pub struct NativeQuery { /// The pipeline may include Extended JSON. /// /// Keys and values in the pipeline may contain placeholders of the form `{{variableName}}` - /// which will be substituted when the native procedure is executed according to the given + /// which will be substituted when the native query is executed according to the given /// arguments. /// /// Placeholders must be inside quotes so that the pipeline can be stored in JSON format. If diff --git a/crates/integration-tests/src/tests/mod.rs b/crates/integration-tests/src/tests/mod.rs index d3b88c96..74271150 100644 --- a/crates/integration-tests/src/tests/mod.rs +++ b/crates/integration-tests/src/tests/mod.rs @@ -9,6 +9,6 @@ mod basic; mod local_relationship; -mod native_procedure; +mod native_mutation; mod native_query; mod remote_relationship; diff --git a/crates/integration-tests/src/tests/native_procedure.rs b/crates/integration-tests/src/tests/native_mutation.rs similarity index 95% rename from crates/integration-tests/src/tests/native_procedure.rs rename to crates/integration-tests/src/tests/native_mutation.rs index c17a1da5..6a7574b4 100644 --- a/crates/integration-tests/src/tests/native_procedure.rs +++ b/crates/integration-tests/src/tests/native_mutation.rs @@ -3,7 +3,7 @@ use insta::assert_yaml_snapshot; use serde_json::json; #[tokio::test] -async fn updates_with_native_procedure() -> anyhow::Result<()> { +async fn updates_with_native_mutation() -> anyhow::Result<()> { let id_1 = 5471; let id_2 = 5472; let mutation = r#" diff --git a/crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_procedure__updates_with_native_procedure.snap b/crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_mutation__updates_with_native_mutation.snap similarity index 89% rename from crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_procedure__updates_with_native_procedure.snap rename to crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_mutation__updates_with_native_mutation.snap index 87a41d4c..1a1a408b 100644 --- a/crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_procedure__updates_with_native_procedure.snap +++ b/crates/integration-tests/src/tests/snapshots/integration_tests__tests__native_mutation__updates_with_native_mutation.snap @@ -1,5 +1,5 @@ --- -source: crates/integration-tests/src/tests/native_procedure.rs +source: crates/integration-tests/src/tests/native_mutation.rs expression: "query(r#\"\n query {\n artist1: artist(where: { artistId: { _eq: 5471 } }, limit: 1) {\n artistId\n name\n }\n artist2: artist(where: { artistId: { _eq: 5472 } }, limit: 1) {\n artistId\n name\n }\n }\n \"#).run().await?" --- data: diff --git a/crates/mongodb-agent-common/src/interface_types/mongo_agent_error.rs b/crates/mongodb-agent-common/src/interface_types/mongo_agent_error.rs index 3f80e2d6..376fbfac 100644 --- a/crates/mongodb-agent-common/src/interface_types/mongo_agent_error.rs +++ b/crates/mongodb-agent-common/src/interface_types/mongo_agent_error.rs @@ -6,7 +6,7 @@ use http::StatusCode; use mongodb::bson; use thiserror::Error; -use crate::procedure::ProcedureError; +use crate::mutation::MutationError; /// A superset of the DC-API `AgentError` type. This enum adds error cases specific to the MongoDB /// agent. @@ -21,7 +21,7 @@ pub enum MongoAgentError { MongoDBSerialization(#[from] mongodb::bson::ser::Error), MongoDBSupport(#[from] mongodb_support::error::Error), NotImplemented(&'static str), - ProcedureError(#[from] ProcedureError), + MutationError(#[from] MutationError), Serialization(serde_json::Error), UnknownAggregationFunction(String), UnspecifiedRelation(String), @@ -76,7 +76,7 @@ impl MongoAgentError { } MongoDBSupport(err) => (StatusCode::BAD_REQUEST, ErrorResponse::new(&err)), NotImplemented(missing_feature) => (StatusCode::BAD_REQUEST, ErrorResponse::new(&format!("The MongoDB agent does not yet support {missing_feature}"))), - ProcedureError(err) => (StatusCode::BAD_REQUEST, ErrorResponse::new(err)), + MutationError(err) => (StatusCode::BAD_REQUEST, ErrorResponse::new(err)), Serialization(err) => (StatusCode::INTERNAL_SERVER_ERROR, ErrorResponse::new(&err)), UnknownAggregationFunction(function) => ( StatusCode::BAD_REQUEST, diff --git a/crates/mongodb-agent-common/src/lib.rs b/crates/mongodb-agent-common/src/lib.rs index 664c2795..a57214ca 100644 --- a/crates/mongodb-agent-common/src/lib.rs +++ b/crates/mongodb-agent-common/src/lib.rs @@ -5,7 +5,7 @@ pub mod health; pub mod interface_types; pub mod mongodb; pub mod mongodb_connection; -pub mod procedure; +pub mod mutation; pub mod query; pub mod scalar_types_capabilities; pub mod schema; diff --git a/crates/mongodb-agent-common/src/procedure/error.rs b/crates/mongodb-agent-common/src/mutation/error.rs similarity index 96% rename from crates/mongodb-agent-common/src/procedure/error.rs rename to crates/mongodb-agent-common/src/mutation/error.rs index 45a5ba56..e2e363bf 100644 --- a/crates/mongodb-agent-common/src/procedure/error.rs +++ b/crates/mongodb-agent-common/src/mutation/error.rs @@ -4,7 +4,7 @@ use thiserror::Error; use crate::query::arguments::ArgumentError; #[derive(Debug, Error)] -pub enum ProcedureError { +pub enum MutationError { #[error("error executing mongodb command: {0}")] ExecutionError(#[from] mongodb::error::Error), diff --git a/crates/mongodb-agent-common/src/procedure/interpolated_command.rs b/crates/mongodb-agent-common/src/mutation/interpolated_command.rs similarity index 82% rename from crates/mongodb-agent-common/src/procedure/interpolated_command.rs rename to crates/mongodb-agent-common/src/mutation/interpolated_command.rs index d644480d..e90c9c89 100644 --- a/crates/mongodb-agent-common/src/procedure/interpolated_command.rs +++ b/crates/mongodb-agent-common/src/mutation/interpolated_command.rs @@ -3,11 +3,11 @@ use std::collections::BTreeMap; use itertools::Itertools as _; use mongodb::bson::{self, Bson}; -use super::ProcedureError; +use super::MutationError; -type Result = std::result::Result; +type Result = std::result::Result; -/// Parse native procedure commands, and interpolate arguments. +/// Parse native mutation commands, and interpolate arguments. pub fn interpolated_command( command: &bson::Document, arguments: &BTreeMap, @@ -48,7 +48,7 @@ fn interpolate_document( let interpolated_key = interpolate_string(&key, arguments)?; match interpolated_key { Bson::String(string_key) => Ok((string_key, interpolated_value)), - _ => Err(ProcedureError::NonStringKey(interpolated_key)), + _ => Err(MutationError::NonStringKey(interpolated_key)), } }) .try_collect() @@ -69,23 +69,23 @@ fn interpolate_document( /// /// if the type of the variable `recordId` is `int`. fn interpolate_string(string: &str, arguments: &BTreeMap) -> Result { - let parts = parse_native_procedure(string); + let parts = parse_native_mutation(string); if parts.len() == 1 { let mut parts = parts; match parts.remove(0) { - NativeProcedurePart::Text(string) => Ok(Bson::String(string)), - NativeProcedurePart::Parameter(param) => resolve_argument(¶m, arguments), + NativeMutationPart::Text(string) => Ok(Bson::String(string)), + NativeMutationPart::Parameter(param) => resolve_argument(¶m, arguments), } } else { let interpolated_parts: Vec = parts .into_iter() .map(|part| match part { - NativeProcedurePart::Text(string) => Ok(string), - NativeProcedurePart::Parameter(param) => { + NativeMutationPart::Text(string) => Ok(string), + NativeMutationPart::Parameter(param) => { let argument_value = resolve_argument(¶m, arguments)?; match argument_value { Bson::String(string) => Ok(string), - _ => Err(ProcedureError::NonStringInStringContext(param)), + _ => Err(MutationError::NonStringInStringContext(param)), } } }) @@ -97,34 +97,34 @@ fn interpolate_string(string: &str, arguments: &BTreeMap) -> Resul fn resolve_argument(argument_name: &str, arguments: &BTreeMap) -> Result { let argument = arguments .get(argument_name) - .ok_or_else(|| ProcedureError::MissingArgument(argument_name.to_owned()))?; + .ok_or_else(|| MutationError::MissingArgument(argument_name.to_owned()))?; Ok(argument.clone()) } -/// A part of a Native Procedure command text, either raw text or a parameter. +/// A part of a Native Mutation command text, either raw text or a parameter. #[derive(Debug, Clone, PartialEq, Eq)] -enum NativeProcedurePart { +enum NativeMutationPart { /// A raw text part Text(String), /// A parameter Parameter(String), } -/// Parse a string or key in a native procedure into parts where variables have the syntax +/// Parse a string or key in a native mutation into parts where variables have the syntax /// `{{}}`. -fn parse_native_procedure(string: &str) -> Vec { - let vec: Vec> = string +fn parse_native_mutation(string: &str) -> Vec { + let vec: Vec> = string .split("{{") .filter(|part| !part.is_empty()) .map(|part| match part.split_once("}}") { - None => vec![NativeProcedurePart::Text(part.to_string())], + None => vec![NativeMutationPart::Text(part.to_string())], Some((var, text)) => { if text.is_empty() { - vec![NativeProcedurePart::Parameter(var.trim().to_owned())] + vec![NativeMutationPart::Parameter(var.trim().to_owned())] } else { vec![ - NativeProcedurePart::Parameter(var.trim().to_owned()), - NativeProcedurePart::Text(text.to_string()), + NativeMutationPart::Parameter(var.trim().to_owned()), + NativeMutationPart::Text(text.to_string()), ] } } @@ -136,7 +136,7 @@ fn parse_native_procedure(string: &str) -> Vec { #[cfg(test)] mod tests { use configuration::{ - native_procedure::NativeProcedure, + native_mutation::NativeMutation, schema::{ObjectField, ObjectType, Type}, }; use mongodb::bson::doc; @@ -153,7 +153,7 @@ mod tests { #[test] fn interpolates_non_string_type() -> anyhow::Result<()> { - let native_procedure = NativeProcedure { + let native_mutation = NativeMutation { result_type: Type::Object("InsertArtist".to_owned()), arguments: [ ( @@ -192,10 +192,10 @@ mod tests { let arguments = resolve_arguments( &Default::default(), - &native_procedure.arguments, + &native_mutation.arguments, input_arguments, )?; - let command = interpolated_command(&native_procedure.command, &arguments)?; + let command = interpolated_command(&native_mutation.command, &arguments)?; assert_eq!( command, @@ -212,7 +212,7 @@ mod tests { #[test] fn interpolates_array_argument() -> anyhow::Result<()> { - let native_procedure = NativeProcedure { + let native_mutation = NativeMutation { result_type: Type::Object("InsertArtist".to_owned()), arguments: [( "documents".to_owned(), @@ -266,8 +266,8 @@ mod tests { .collect(); let arguments = - resolve_arguments(&object_types, &native_procedure.arguments, input_arguments)?; - let command = interpolated_command(&native_procedure.command, &arguments)?; + resolve_arguments(&object_types, &native_mutation.arguments, input_arguments)?; + let command = interpolated_command(&native_mutation.command, &arguments)?; assert_eq!( command, @@ -290,7 +290,7 @@ mod tests { #[test] fn interpolates_arguments_within_string() -> anyhow::Result<()> { - let native_procedure = NativeProcedure { + let native_mutation = NativeMutation { result_type: Type::Object("Insert".to_owned()), arguments: [ ( @@ -326,10 +326,10 @@ mod tests { let arguments = resolve_arguments( &Default::default(), - &native_procedure.arguments, + &native_mutation.arguments, input_arguments, )?; - let command = interpolated_command(&native_procedure.command, &arguments)?; + let command = interpolated_command(&native_mutation.command, &arguments)?; assert_eq!( command, diff --git a/crates/mongodb-agent-common/src/procedure/mod.rs b/crates/mongodb-agent-common/src/mutation/mod.rs similarity index 72% rename from crates/mongodb-agent-common/src/procedure/mod.rs rename to crates/mongodb-agent-common/src/mutation/mod.rs index 9e6ff281..512e716e 100644 --- a/crates/mongodb-agent-common/src/procedure/mod.rs +++ b/crates/mongodb-agent-common/src/mutation/mod.rs @@ -4,19 +4,19 @@ mod interpolated_command; use std::borrow::Cow; use std::collections::BTreeMap; -use configuration::native_procedure::NativeProcedure; +use configuration::native_mutation::NativeMutation; use configuration::schema::{ObjectField, ObjectType, Type}; use mongodb::options::SelectionCriteria; use mongodb::{bson, Database}; use crate::query::arguments::resolve_arguments; -pub use self::error::ProcedureError; +pub use self::error::MutationError; pub use self::interpolated_command::interpolated_command; /// Encapsulates running arbitrary mongodb commands with interpolated arguments #[derive(Clone, Debug)] -pub struct Procedure<'a> { +pub struct Mutation<'a> { arguments: BTreeMap, command: Cow<'a, bson::Document>, parameters: Cow<'a, BTreeMap>, @@ -24,17 +24,17 @@ pub struct Procedure<'a> { selection_criteria: Option>, } -impl<'a> Procedure<'a> { - pub fn from_native_procedure( - native_procedure: &'a NativeProcedure, +impl<'a> Mutation<'a> { + pub fn from_native_mutation( + native_mutation: &'a NativeMutation, arguments: BTreeMap, ) -> Self { - Procedure { + Mutation { arguments, - command: Cow::Borrowed(&native_procedure.command), - parameters: Cow::Borrowed(&native_procedure.arguments), - result_type: native_procedure.result_type.clone(), - selection_criteria: native_procedure.selection_criteria.as_ref().map(Cow::Borrowed), + command: Cow::Borrowed(&native_mutation.command), + parameters: Cow::Borrowed(&native_mutation.arguments), + result_type: native_mutation.result_type.clone(), + selection_criteria: native_mutation.selection_criteria.as_ref().map(Cow::Borrowed), } } @@ -42,7 +42,7 @@ impl<'a> Procedure<'a> { self, object_types: &BTreeMap, database: Database, - ) -> Result<(bson::Document, Type), ProcedureError> { + ) -> Result<(bson::Document, Type), MutationError> { let selection_criteria = self.selection_criteria.map(Cow::into_owned); let command = interpolate( object_types, @@ -57,7 +57,7 @@ impl<'a> Procedure<'a> { pub fn interpolated_command( self, object_types: &BTreeMap, - ) -> Result { + ) -> Result { interpolate( object_types, &self.parameters, @@ -72,7 +72,7 @@ fn interpolate( parameters: &BTreeMap, arguments: BTreeMap, command: &bson::Document, -) -> Result { +) -> Result { let bson_arguments = resolve_arguments(object_types, parameters, arguments)?; interpolated_command(command, &bson_arguments) } diff --git a/crates/mongodb-agent-common/src/query/native_query.rs b/crates/mongodb-agent-common/src/query/native_query.rs index abdc51bd..85f70d95 100644 --- a/crates/mongodb-agent-common/src/query/native_query.rs +++ b/crates/mongodb-agent-common/src/query/native_query.rs @@ -7,7 +7,7 @@ use itertools::Itertools as _; use crate::{ interface_types::MongoAgentError, mongodb::{Pipeline, Stage}, - procedure::{interpolated_command, ProcedureError}, + mutation::{interpolated_command, MutationError}, }; use super::{arguments::resolve_arguments, query_target::QueryTarget}; @@ -47,7 +47,7 @@ fn make_pipeline( let bson_arguments = resolve_arguments(&config.object_types, &native_query.arguments, expressions) - .map_err(ProcedureError::UnresolvableArguments)?; + .map_err(MutationError::UnresolvableArguments)?; // Replace argument placeholders with resolved expressions, convert document list to // a `Pipeline` value @@ -191,8 +191,8 @@ mod tests { object_types, collections: Default::default(), functions: Default::default(), - procedures: Default::default(), - native_procedures: Default::default(), + mutations: Default::default(), + native_mutations: Default::default(), options: Default::default(), }; diff --git a/crates/mongodb-connector/src/mutation.rs b/crates/mongodb-connector/src/mutation.rs index c98e812f..e6ea2590 100644 --- a/crates/mongodb-connector/src/mutation.rs +++ b/crates/mongodb-connector/src/mutation.rs @@ -8,7 +8,7 @@ use mongodb::{ Database, }; use mongodb_agent_common::{ - procedure::Procedure, query::serialization::bson_to_json, state::ConnectorState, + mutation::Mutation, query::serialization::bson_to_json, state::ConnectorState, }; use ndc_sdk::{ connector::MutationError, @@ -32,13 +32,13 @@ pub async fn handle_mutation_request( ) -> Result, MutationError> { tracing::debug!(?config, mutation_request = %serde_json::to_string(&mutation_request).unwrap(), "executing mutation"); let database = state.database(); - let jobs = look_up_procedures(config, &mutation_request)?; - let operation_results = try_join_all(jobs.into_iter().map(|(procedure, requested_fields)| { - execute_procedure( + let jobs = look_up_mutations(config, &mutation_request)?; + let operation_results = try_join_all(jobs.into_iter().map(|(mutation, requested_fields)| { + execute_mutation( &query_context, database.clone(), &mutation_request.collection_relationships, - procedure, + mutation, requested_fields, ) })) @@ -46,13 +46,13 @@ pub async fn handle_mutation_request( Ok(JsonResponse::Value(MutationResponse { operation_results })) } -/// Looks up procedures according to the names given in the mutation request, and pairs them with -/// arguments and requested fields. Returns an error if any procedures cannot be found. -fn look_up_procedures<'a, 'b>( +/// Looks up mutations according to the names given in the mutation request, and pairs them with +/// arguments and requested fields. Returns an error if any mutations cannot be found. +fn look_up_mutations<'a, 'b>( config: &'a Configuration, mutation_request: &'b MutationRequest, -) -> Result, Option<&'b NestedField>)>, MutationError> { - let (procedures, not_found): (Vec<_>, Vec) = mutation_request +) -> Result, Option<&'b NestedField>)>, MutationError> { + let (mutations, not_found): (Vec<_>, Vec) = mutation_request .operations .iter() .map(|operation| match operation { @@ -61,33 +61,33 @@ fn look_up_procedures<'a, 'b>( arguments, fields, } => { - let native_procedure = config.native_procedures.get(name); - let procedure = native_procedure.ok_or(name).map(|native_procedure| { - Procedure::from_native_procedure(native_procedure, arguments.clone()) + let native_mutation = config.native_mutations.get(name); + let mutation = native_mutation.ok_or(name).map(|native_mutation| { + Mutation::from_native_mutation(native_mutation, arguments.clone()) })?; - Ok((procedure, fields.as_ref())) + Ok((mutation, fields.as_ref())) } }) .partition_result(); if !not_found.is_empty() { return Err(MutationError::UnprocessableContent(format!( - "request includes unknown procedures: {}", + "request includes unknown mutations: {}", not_found.join(", ") ))); } - Ok(procedures) + Ok(mutations) } -async fn execute_procedure( +async fn execute_mutation( query_context: &QueryContext<'_>, database: Database, relationships: &BTreeMap, - procedure: Procedure<'_>, + mutation: Mutation<'_>, requested_fields: Option<&NestedField>, ) -> Result { - let (result, result_type) = procedure + let (result, result_type) = mutation .execute(&query_context.object_types, database.clone()) .await .map_err(|err| MutationError::UnprocessableContent(err.to_string()))?; diff --git a/crates/mongodb-connector/src/schema.rs b/crates/mongodb-connector/src/schema.rs index c843b352..727fd807 100644 --- a/crates/mongodb-connector/src/schema.rs +++ b/crates/mongodb-connector/src/schema.rs @@ -14,7 +14,7 @@ pub async fn get_schema(config: &Configuration) -> Result