From 77c66760029efd99278b58dc528afed0a89bf6f2 Mon Sep 17 00:00:00 2001 From: Dominic Petrick <dompetrick@gmail.com> Date: Thu, 31 Dec 2020 14:01:31 +0100 Subject: [PATCH] `findOne` deprecation (#1487) * Add deprecation mechanism to DMMF fields. * Deprecate `findOne`. * Deprecate with 2.15 --- query-engine/core/src/schema/input_types.rs | 16 +++++++++++ query-engine/core/src/schema/mod.rs | 7 +++++ query-engine/core/src/schema/output_types.rs | 15 ++++++++++ query-engine/core/src/schema/query_schema.rs | 2 ++ .../schema_builder/output_types/query_type.rs | 28 +++++++++++++++++-- query-engine/core/src/schema_builder/utils.rs | 2 ++ .../query-engine/src/dmmf/schema/ast.rs | 27 ++++++++++++++++++ .../src/dmmf/schema/field_renderer.rs | 2 ++ 8 files changed, 97 insertions(+), 2 deletions(-) diff --git a/query-engine/core/src/schema/input_types.rs b/query-engine/core/src/schema/input_types.rs index f6ac7d21887e..1f147fa1c387 100644 --- a/query-engine/core/src/schema/input_types.rs +++ b/query-engine/core/src/schema/input_types.rs @@ -81,6 +81,7 @@ impl InputObjectType { pub struct InputField { pub name: String, pub default_value: Option<dml::DefaultValue>, + pub deprecation: Option<Deprecation>, /// Possible field types, represented as a union of input types, but only one can be provided at any time. pub field_types: Vec<InputType>, @@ -125,6 +126,21 @@ impl InputField { self.field_types.push(typ); self } + + pub fn deprecate<T, S, U>(mut self, reason: T, since_version: S, planned_removal_version: Option<U>) -> Self + where + T: Into<String>, + S: Into<String>, + U: Into<String>, + { + self.deprecation = Some(Deprecation { + reason: reason.into(), + since_version: since_version.into(), + planned_removal_version: planned_removal_version.map(Into::into), + }); + + self + } } #[derive(Clone)] diff --git a/query-engine/core/src/schema/mod.rs b/query-engine/core/src/schema/mod.rs index 875447d99df9..121c49d29b9c 100644 --- a/query-engine/core/src/schema/mod.rs +++ b/query-engine/core/src/schema/mod.rs @@ -40,3 +40,10 @@ impl<T> IntoArc<T> for Weak<T> { self.upgrade().expect("Expected weak reference to be valid.") } } + +#[derive(Debug, PartialEq)] +pub struct Deprecation { + pub since_version: String, + pub planned_removal_version: Option<String>, + pub reason: String, +} diff --git a/query-engine/core/src/schema/output_types.rs b/query-engine/core/src/schema/output_types.rs index cee7b0c0b13d..dda8d616f5c5 100644 --- a/query-engine/core/src/schema/output_types.rs +++ b/query-engine/core/src/schema/output_types.rs @@ -142,6 +142,7 @@ impl ObjectType { pub struct OutputField { pub name: String, pub field_type: OutputTypeRef, + pub deprecation: Option<Deprecation>, /// Arguments are input fields, but positioned in context of an output field /// instead of being attached to an input object. @@ -168,4 +169,18 @@ impl OutputField { self } } + + pub fn deprecate<T, S>(mut self, reason: T, since_version: S, planned_removal_version: Option<String>) -> Self + where + T: Into<String>, + S: Into<String>, + { + self.deprecation = Some(Deprecation { + reason: reason.into(), + since_version: since_version.into(), + planned_removal_version, + }); + + self + } } diff --git a/query-engine/core/src/schema/query_schema.rs b/query-engine/core/src/schema/query_schema.rs index dcb55efa615c..a67034329460 100644 --- a/query-engine/core/src/schema/query_schema.rs +++ b/query-engine/core/src/schema/query_schema.rs @@ -89,6 +89,7 @@ pub struct QueryInfo { #[derive(Debug, Clone, PartialEq)] pub enum QueryTag { FindOne, + FindUnique, FindFirst, FindMany, CreateOne, @@ -107,6 +108,7 @@ impl fmt::Display for QueryTag { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match self { Self::FindOne => "findOne", + Self::FindUnique => "findUnique", Self::FindFirst => "findFirst", Self::FindMany => "findMany", Self::CreateOne => "createOne", diff --git a/query-engine/core/src/schema_builder/output_types/query_type.rs b/query-engine/core/src/schema_builder/output_types/query_type.rs index 8dae05c17685..e6a71e50a780 100644 --- a/query-engine/core/src/schema_builder/output_types/query_type.rs +++ b/query-engine/core/src/schema_builder/output_types/query_type.rs @@ -17,6 +17,7 @@ pub(crate) fn build(ctx: &mut BuilderContext) -> (OutputType, ObjectTypeStrongRe } append_opt(&mut vec, find_one_field(ctx, &model)); + append_opt(&mut vec, find_unique_field(ctx, &model)); vec }) .flatten() @@ -28,8 +29,7 @@ pub(crate) fn build(ctx: &mut BuilderContext) -> (OutputType, ObjectTypeStrongRe (OutputType::Object(Arc::downgrade(&strong_ref)), strong_ref) } -/// Builds a "single" query arity item field (e.g. "user", "post" ...) for given model. -/// Find one unique semantics. +/// Deprecated field. Semantics are identical to `findUnique`. fn find_one_field(ctx: &mut BuilderContext, model: &ModelRef) -> Option<OutputField> { arguments::where_unique_argument(ctx, model).map(|arg| { let field_name = ctx.pluralize_internal(camel_case(&model.name), format!("findOne{}", model.name)); @@ -44,6 +44,30 @@ fn find_one_field(ctx: &mut BuilderContext, model: &ModelRef) -> Option<OutputFi }), ) .optional() + .deprecate( + "The `findOne` query has been deprecated and replaced with `findUnique`.", + "2.14", + Some("2.15".to_owned()), + ) + }) +} + +/// Builds a "single" query arity item field (e.g. "user", "post" ...) for given model. +/// Find one unique semantics. +fn find_unique_field(ctx: &mut BuilderContext, model: &ModelRef) -> Option<OutputField> { + arguments::where_unique_argument(ctx, model).map(|arg| { + let field_name = ctx.pluralize_internal(camel_case(&model.name), format!("findUnique{}", model.name)); + + field( + field_name, + vec![arg], + OutputType::object(output_objects::map_model_object_type(ctx, &model)), + Some(QueryInfo { + model: Some(Arc::clone(&model)), + tag: QueryTag::FindUnique, + }), + ) + .optional() }) } diff --git a/query-engine/core/src/schema_builder/utils.rs b/query-engine/core/src/schema_builder/utils.rs index c44db87324b1..089bf62fe109 100644 --- a/query-engine/core/src/schema_builder/utils.rs +++ b/query-engine/core/src/schema_builder/utils.rs @@ -57,6 +57,7 @@ where field_type: Arc::new(field_type), query_info, is_required: true, + deprecation: None, } } @@ -71,6 +72,7 @@ where field_types: field_types.into(), default_value, is_required: true, + deprecation: None, } } diff --git a/query-engine/query-engine/src/dmmf/schema/ast.rs b/query-engine/query-engine/src/dmmf/schema/ast.rs index f92635e86f88..5b1837b3740d 100644 --- a/query-engine/query-engine/src/dmmf/schema/ast.rs +++ b/query-engine/query-engine/src/dmmf/schema/ast.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use query_core::Deprecation; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Default)] @@ -18,6 +19,9 @@ pub struct DmmfOutputField { pub is_required: bool, pub is_nullable: bool, pub output_type: DmmfTypeReference, + + #[serde(skip_serializing_if = "Option::is_none")] + pub deprecation: Option<DmmfDeprecation>, } #[derive(Debug, Serialize, Deserialize)] @@ -49,6 +53,9 @@ pub struct DmmfInputField { pub is_required: bool, pub is_nullable: bool, pub input_types: Vec<DmmfTypeReference>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub deprecation: Option<DmmfDeprecation>, } #[derive(Debug, Serialize, Deserialize)] @@ -78,3 +85,23 @@ pub struct DmmfEnum { pub name: String, pub values: Vec<String>, } + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DmmfDeprecation { + pub since_version: String, + pub reason: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub planned_removal_version: Option<String>, +} + +impl From<&Deprecation> for DmmfDeprecation { + fn from(deprecation: &Deprecation) -> Self { + Self { + since_version: deprecation.since_version.clone(), + planned_removal_version: deprecation.planned_removal_version.clone(), + reason: deprecation.reason.clone(), + } + } +} diff --git a/query-engine/query-engine/src/dmmf/schema/field_renderer.rs b/query-engine/query-engine/src/dmmf/schema/field_renderer.rs index 25c088766aa8..f97b126be222 100644 --- a/query-engine/query-engine/src/dmmf/schema/field_renderer.rs +++ b/query-engine/query-engine/src/dmmf/schema/field_renderer.rs @@ -16,6 +16,7 @@ pub(super) fn render_input_field(input_field: &InputFieldRef, ctx: &mut RenderCo input_types: type_references, is_required: input_field.is_required, is_nullable: nullable, + deprecation: input_field.deprecation.as_ref().map(Into::into), }; field @@ -31,6 +32,7 @@ pub(super) fn render_output_field(field: &OutputFieldRef, ctx: &mut RenderContex output_type, is_required: field.is_required, is_nullable: !field.is_required, + deprecation: field.deprecation.as_ref().map(Into::into), }; ctx.add_mapping(field.name.clone(), field.query_info.as_ref());