Repository: Brendonovich/prisma-client-rust (language: rust)

Issue:
Unchecked action and SetParam variants
`create_unchecked`, `update_unchecked`, `UncheckedSetParam`, etc... would solve #32



Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index ad7a87df..b90d450b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@ exclude = ["examples", "integration-tests"]
 members = [
   "examples/*",
   "integration-tests",
+  # "tests/*",
   "sdk",
   "sdk/example/*",
   "cli",
diff --git a/cli/src/generator/models/actions.rs b/cli/src/generator/models/actions.rs
index f6d387a2..bbd4359f 100644
--- a/cli/src/generator/models/actions.rs
+++ b/cli/src/generator/models/actions.rs
@@ -3,37 +3,42 @@ use prisma_client_rust_sdk::GenerateArgs;
 
 use super::required_fields;
 
-pub fn create_args_params_pushes(model: &dml::Model) -> Vec<TokenStream> {
-    let required_fields = required_fields(model);
+pub fn create_fn(model: &dml::Model) -> TokenStream {
+    let (names, (types, push_wrappers)): (Vec<_>, (Vec<_>, Vec<_>)) = required_fields(model)
+        .into_iter()
+        .map(|field| (snake_ident(field.name()), (field.typ, field.push_wrapper)))
+        .unzip();
 
-    required_fields
-        .iter()
-        .map(|field| {
-            let field_name_snake = snake_ident(field.name());
-            let push_wrapper = &field.push_wrapper;
+    quote! {
+        pub fn create(self, #(#names: #types,)* mut _params: Vec<SetParam>) -> Create<'a> {
+            _params.extend([
+                #(#push_wrappers(#names)),*
+            ]);
 
-            quote!(_params.push(#push_wrapper(#field_name_snake)))
-        })
-        .collect()
+            Create::new(
+                self.client,
+                _params
+            )
+        }
+    }
 }
 
-pub fn create_fn(model: &dml::Model) -> TokenStream {
-    let required_fields = required_fields(model);
-
-    let required_field_names = required_fields
+pub fn create_unchecked_fn(model: &dml::Model) -> TokenStream {
+    let (names, types): (Vec<_>, Vec<_>) = model
+        .required_scalar_fields()
         .iter()
-        .map(|field| snake_ident(field.name()));
-    let required_field_types = required_fields.iter().map(|field| &field.typ);
-
-    let create_args_params_pushes = create_args_params_pushes(model);
+        .map(|f| (snake_ident(f.name()), f.type_tokens(quote!())))
+        .unzip();
 
     quote! {
-        pub fn create(self, #(#required_field_names: #required_field_types,)* mut _params: Vec<SetParam>) -> Create<'a> {
-            #(#create_args_params_pushes;)*
+        pub fn create_unchecked(self, #(#names: #types,)* mut _params: Vec<UncheckedSetParam>) -> Create<'a> {
+            _params.extend([
+                #(#names::set(#names)),*
+            ]);
 
             Create::new(
                 self.client,
-                _params
+                _params.into_iter().map(Into::into).collect()
             )
         }
     }
@@ -54,9 +59,11 @@ pub fn create_many_fn(model: &dml::Model) -> TokenStream {
         .collect::<Vec<_>>();
 
     quote! {
-        pub fn create_many(self, data: Vec<(#(#scalar_field_types,)* Vec<SetParam>)>) -> CreateMany<'a> {
+        pub fn create_many(self, data: Vec<(#(#scalar_field_types,)* Vec<UncheckedSetParam>)>) -> CreateMany<'a> {
             let data = data.into_iter().map(|(#(#scalar_field_names2,)* mut _params)| {
-                #(_params.push(#scalar_field_names::set(#scalar_field_names));)*
+                _params.extend([
+                    #(#scalar_field_names::set(#scalar_field_names)),*
+                ]);
 
                 _params
             }).collect();
@@ -70,17 +77,21 @@ pub fn create_many_fn(model: &dml::Model) -> TokenStream {
 }
 
 pub fn upsert_fn(model: &dml::Model) -> TokenStream {
-    let required_fields = required_fields(model);
-
-    let create_args_names_snake = required_fields
-        .iter()
-        .map(|field| snake_ident(field.name()));
-    let create_args_typs = required_fields.iter().map(|field| &field.typ);
-    let create_args_params_pushes = create_args_params_pushes(model);
+    let (names, (types, push_wrappers)): (Vec<_>, (Vec<_>, Vec<_>)) = required_fields(model)
+        .into_iter()
+        .map(|field| (snake_ident(field.name()), (field.typ, field.push_wrapper)))
+        .unzip();
 
     quote! {
-        pub fn upsert(self, _where: UniqueWhereParam, (#(#create_args_names_snake,)* mut _params): (#(#create_args_typs,)* Vec<SetParam>), _update: Vec<SetParam>) -> Upsert<'a> {
-            #(#create_args_params_pushes;)*
+        pub fn upsert(
+            self,
+             _where: UniqueWhereParam,
+              (#(#names,)* mut _params): (#(#types,)* Vec<SetParam>),
+               _update: Vec<SetParam>
+        ) -> Upsert<'a> {
+            _params.extend([
+                #(#push_wrappers(#names)),*
+            ]);
 
             Upsert::new(
                 self.client,
@@ -96,6 +107,7 @@ pub fn struct_definition(model: &dml::Model, args: &GenerateArgs) -> TokenStream
     let pcr = quote!(::prisma_client_rust);
 
     let create_fn = create_fn(model);
+    let create_unchecked_fn = create_unchecked_fn(model);
     let upsert_fn = upsert_fn(model);
 
     let create_many_fn = (args
@@ -133,6 +145,7 @@ pub fn struct_definition(model: &dml::Model, args: &GenerateArgs) -> TokenStream
             }
 
             #create_fn
+            #create_unchecked_fn
 
             #create_many_fn
 
@@ -145,7 +158,16 @@ pub fn struct_definition(model: &dml::Model, args: &GenerateArgs) -> TokenStream
                 )
             }
 
-            pub fn update_many(self, _where: Vec<WhereParam>, _params: Vec<SetParam>) -> UpdateMany<'a> {
+            pub fn update_unchecked(self, _where: UniqueWhereParam, _params: Vec<UncheckedSetParam>) -> Update<'a> {
+                Update::new(
+                    self.client,
+                    _where.into(),
+                    _params.into_iter().map(Into::into).collect(),
+                    vec![]
+                )
+            }
+
+            pub fn update_many(self, _where: Vec<WhereParam>, _params: Vec<UncheckedSetParam>) -> UpdateMany<'a> {
                 UpdateMany::new(
                     self.client,
                     _where,
diff --git a/cli/src/generator/models/create.rs b/cli/src/generator/models/create.rs
index c58f1b41..4c907fd4 100644
--- a/cli/src/generator/models/create.rs
+++ b/cli/src/generator/models/create.rs
@@ -10,8 +10,8 @@ fn create_unchecked(model: &dml::Model) -> TokenStream {
         .unzip();
 
     quote! {
-        pub fn create_unchecked(#(#scalar_field_names: #scalar_field_types,)* _params: Vec<SetParam>)
-            -> (#(#scalar_field_types,)* Vec<SetParam>) {
+        pub fn create_unchecked(#(#scalar_field_names: #scalar_field_types,)* _params: Vec<UncheckedSetParam>)
+            -> (#(#scalar_field_types,)* Vec<UncheckedSetParam>) {
             (#(#scalar_field_names,)* _params)
         }
     }
diff --git a/cli/src/generator/models/field.rs b/cli/src/generator/models/field.rs
index 6701cec6..a9334343 100644
--- a/cli/src/generator/models/field.rs
+++ b/cli/src/generator/models/field.rs
@@ -209,17 +209,17 @@ pub fn module(
 
                     let typ = method.type_tokens(quote!());
 
-                    Some(quote! {
-                        pub fn #method_name_snake(value: #typ) -> WhereParam {
-                            WhereParam::#field_name_pascal(_prisma::read_filters::#filter_enum::#method_name_pascal(value))
-                        }
-                    })
+                    Some(quote!(fn #method_name_snake(_: #typ) -> #method_name_pascal;))
                 });
 
                 quote! {
                     #equals
 
-                    #(#read_methods)*
+                    #pcr::scalar_where_param_fns!(
+                        _prisma::read_filters::#filter_enum,
+                        #field_name_pascal,
+                        { #(#read_methods)* }
+                    );
                 }
             });
 
@@ -246,12 +246,19 @@ pub fn module(
 
             quote! {
                 pub struct Set(pub #field_type);
+
                 impl From<Set> for SetParam {
                     fn from(value: Set) -> Self {
                         Self::#set_variant(value.0)
                     }
                 }
 
+                impl From<Set> for UncheckedSetParam {
+                    fn from(value: Set) -> Self {
+                        Self::#field_name_pascal(value.0)
+                    }
+                }
+
                 pub fn set<T: From<Set>>(value: #field_type) -> T {
                     Set(value).into()
                 }
@@ -275,7 +282,7 @@ pub fn module(
         quote! {
             pub mod #field_name_snake {
                 use super::super::*;
-                use super::{WhereParam, UniqueWhereParam, OrderByParam, WithParam, SetParam};
+                use super::{WhereParam, UniqueWhereParam, OrderByParam, WithParam, SetParam, UncheckedSetParam};
                 use super::_prisma::*;
 
                 pub const NAME: &str = #field_name;
diff --git a/cli/src/generator/models/mod.rs b/cli/src/generator/models/mod.rs
index d8b20965..8562e4c3 100644
--- a/cli/src/generator/models/mod.rs
+++ b/cli/src/generator/models/mod.rs
@@ -160,7 +160,7 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
         where_params_entries.extend(OPERATORS.iter().map(|op| {
             let variant_name = pascal_ident(&op.name);
             let op_action = &op.action;
-            
+
             let value = match op.list {
                 true => quote! {
                     #pcr::SerializedWhereValue::List(
@@ -202,25 +202,25 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
                 let field = fields[0];
 
                 let read_filter = args.read_filter(field.as_scalar_field().unwrap()).unwrap();
-                
+
                 where_params_entries.push(Variant::unique(field, read_filter));
 
                 None
             } else {
                 let variant_name_string = fields.iter().map(|f| pascal_ident(f.name()).to_string()).collect::<String>();
                 let variant_name = format_ident!("{}Equals", &variant_name_string);
-                
+
                 let variant_data_names = fields.iter().map(|f| snake_ident(f.name())).collect::<Vec<_>>();
-            
-                let ((field_defs, field_types), (prisma_values, field_names_snake)): 
+
+                let ((field_defs, field_types), (prisma_values, field_names_snake)):
                     ((Vec<_>, Vec<_>), (Vec<_>, Vec<_>)) = fields.into_iter().map(|field| {
                     let field_type = match field.arity() {
                         dml::FieldArity::List | dml::FieldArity::Required => field.type_tokens(quote!()),
                         dml::FieldArity::Optional => field.field_type().to_tokens(quote!(), &dml::FieldArity::Required)
                     };
-                    
+
                     let field_name_snake = snake_ident(field.name());
-                    
+
                     (
                         (quote!(#field_name_snake: #field_type), field_type),
                         (field.field_type().to_prisma_value(&field_name_snake, &dml::FieldArity::Required), field_name_snake)
@@ -263,7 +263,7 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
             .unzip();
 
         where_params_entries.extend(field_where_param_entries.into_iter().flatten());
-        
+
         let where_params_enums = where_params::collate_entries(where_params_entries);
         let data_struct = data::struct_definition(&model);
         let with_params_enum = with_params::enum_definition(&model);
@@ -283,13 +283,13 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
                 use super::_prisma::*;
 
                 pub const NAME: &str = #model_name;
-                
+
                 #(#field_modules)*
 
                 #compound_field_accessors
 
                 #create_fn
-                
+
                 #select_macro
                 #select_params_enum
 
@@ -312,7 +312,7 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
 
                 pub type UniqueArgs = ::prisma_client_rust::UniqueArgs<Types>;
                 pub type ManyArgs = ::prisma_client_rust::ManyArgs<Types>;
-                
+
                 pub type Count<'a> = ::prisma_client_rust::Count<'a, Types>;
                 pub type Create<'a> = ::prisma_client_rust::Create<'a, Types>;
                 pub type CreateMany<'a> = ::prisma_client_rust::CreateMany<'a, Types>;
@@ -324,7 +324,7 @@ pub fn generate(args: &GenerateArgs, module_path: TokenStream) -> Vec<TokenStrea
                 pub type Upsert<'a> = ::prisma_client_rust::Upsert<'a, Types>;
                 pub type Delete<'a> = ::prisma_client_rust::Delete<'a, Types>;
                 pub type DeleteMany<'a> = ::prisma_client_rust::DeleteMany<'a, Types>;
-              
+
                 #actions_struct
             }
         }
diff --git a/cli/src/generator/models/set_params.rs b/cli/src/generator/models/set_params.rs
index b876fdf6..e8c58065 100644
--- a/cli/src/generator/models/set_params.rs
+++ b/cli/src/generator/models/set_params.rs
@@ -75,11 +75,11 @@ fn field_set_params(field: &dml::Field, args: &GenerateArgs) -> Vec<SetParam> {
             if let Some(write_type) = args.write_filter(&scalar_field) {
                 for method in &write_type.methods {
                     let typ = method.type_tokens(quote!());
-                    
+
                     let prisma_value_converter = method.base_type.to_prisma_value(&format_ident!("value"), &method.arity());
 
                     let variant_name = format_ident!("{}{}", pascal_ident(&method.name), field_name_pascal);
-                    
+
                     let action = &method.action;
                     params.push(SetParam {
                         variant: quote!(#variant_name(#typ)),
@@ -176,31 +176,64 @@ fn field_set_params(field: &dml::Field, args: &GenerateArgs) -> Vec<SetParam> {
 }
 
 pub fn enum_definition(model: &dml::Model, args: &GenerateArgs) -> TokenStream {
-    let set_params = model
+    let (variants, into_pv_arms): (Vec<_>, Vec<_>) = model
         .fields()
-        .map(|f| field_set_params(f, args))
-        .flatten()
-        .collect::<Vec<_>>();
-
-    let (variants, into_pv_arms): (Vec<_>, Vec<_>) = set_params
-        .iter()
-        .map(|p| (&p.variant, &p.into_pv_arm))
+        .flat_map(|f| field_set_params(f, args))
+        .map(|p| (p.variant, p.into_pv_arm))
         .unzip();
 
     let pcr = quote!(::prisma_client_rust);
 
+    let unchecked_enum = {
+        let (variants, into_pv_arms): (Vec<_>, Vec<_>) = model
+            .fields()
+            .filter(|f| f.is_scalar_field())
+            .map(|field| {
+                let field_name_pascal = pascal_ident(field.name());
+
+                let set_variant = format_ident!("Set{}", field_name_pascal);
+
+                let field_type = field.type_tokens(quote!());
+
+                (
+                    quote!(#field_name_pascal(#field_type)),
+                    quote! {
+                        UncheckedSetParam::#field_name_pascal(value) => Self::#set_variant(value)
+                    },
+                )
+            })
+            .unzip();
+
+        quote! {
+            #[derive(Clone)]
+            pub enum UncheckedSetParam {
+                  #(#variants),*
+            }
+
+            impl From<UncheckedSetParam> for SetParam {
+                fn from(param: UncheckedSetParam) -> Self {
+                    match param {
+                         #(#into_pv_arms),*
+                     }
+                }
+            }
+        }
+    };
+
     quote! {
         #[derive(Clone)]
         pub enum SetParam {
             #(#variants),*
         }
 
-        impl Into<(String, #pcr::PrismaValue)> for SetParam {
-            fn into(self) -> (String, #pcr::PrismaValue) {
-                match self {
+        impl From<SetParam> for (String, #pcr::PrismaValue) {
+            fn from(param: SetParam) -> Self {
+                match param {
                     #(#into_pv_arms),*
                 }
             }
         }
+
+        #unchecked_enum
     }
 }
diff --git a/cli/src/generator/models/types.rs b/cli/src/generator/models/types.rs
index bcb64cd7..fa725c6a 100644
--- a/cli/src/generator/models/types.rs
+++ b/cli/src/generator/models/types.rs
@@ -25,6 +25,7 @@ pub fn struct_definition(model: &dml::Model) -> TokenStream {
         impl #pcr::ModelTypes for Types {
             type Data = Data;
             type Where = WhereParam;
+            type UncheckedSet = UncheckedSetParam;
             type Set = SetParam;
             type With = WithParam;
             type OrderBy = OrderByParam;
diff --git a/sdk/src/extensions.rs b/sdk/src/extensions.rs
index d936c8ff..09f625e8 100644
--- a/sdk/src/extensions.rs
+++ b/sdk/src/extensions.rs
@@ -11,7 +11,7 @@ impl ModelExt for Model {
     fn scalar_field_has_relation(&self, scalar: &ScalarField) -> bool {
         self.fields.iter().any(|field| {
             if let FieldType::Relation(info) = field.field_type() {
-                info.fields.iter().any(|f| f == &scalar.name)
+                field.arity().is_required() && info.fields.iter().any(|f| f == &scalar.name)
             } else {
                 false
             }
diff --git a/src/gen_macros.rs b/src/gen_macros.rs
new file mode 100644
index 00000000..3e69c293
--- /dev/null
+++ b/src/gen_macros.rs
@@ -0,0 +1,12 @@
+#[macro_export]
+macro_rules! scalar_where_param_fns {
+    (
+        $filter_enum:ty,
+        $variant:ident,
+        { $(fn $name:ident(_: $typ:ty $(,)?) -> $filter_variant:ident;)+ }
+    ) => { $(
+        pub fn $name(value: $typ) -> WhereParam {
+            WhereParam::$variant(<$filter_enum>::$filter_variant(value))
+        }
+    )+}
+}
diff --git a/src/lib.rs b/src/lib.rs
index 0ac61b1e..487c18dd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,6 @@
 pub mod actions;
 mod client;
+mod gen_macros;
 #[cfg(feature = "migrations")]
 pub mod migrations;
 #[cfg(feature = "mocking")]
diff --git a/src/queries/create_many.rs b/src/queries/create_many.rs
index 0b5731f9..d93b6910 100644
--- a/src/queries/create_many.rs
+++ b/src/queries/create_many.rs
@@ -8,12 +8,15 @@ use crate::{
 
 pub struct CreateMany<'a, Actions: ModelTypes> {
     client: &'a PrismaClientInternals,
-    pub set_params: Vec<Vec<Actions::Set>>,
+    pub set_params: Vec<Vec<Actions::UncheckedSet>>,
     pub skip_duplicates: bool,
 }
 
 impl<'a, Actions: ModelTypes> CreateMany<'a, Actions> {
-    pub fn new(client: &'a PrismaClientInternals, set_params: Vec<Vec<Actions::Set>>) -> Self {
+    pub fn new(
+        client: &'a PrismaClientInternals,
+        set_params: Vec<Vec<Actions::UncheckedSet>>,
+    ) -> Self {
         Self {
             client,
             set_params,
@@ -21,39 +24,42 @@ impl<'a, Actions: ModelTypes> CreateMany<'a, Actions> {
         }
     }
 
-    #[cfg(not(any(feature = "mongodb", feature = "mssql")))]
+    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "postgresql"))]
     pub fn skip_duplicates(mut self) -> Self {
         self.skip_duplicates = true;
         self
     }
 
     fn to_selection(
-        set_params: Vec<Vec<Actions::Set>>,
+        set_params: Vec<Vec<Actions::UncheckedSet>>,
         _skip_duplicates: bool,
         nested_selections: impl IntoIterator<Item = Selection>,
     ) -> Selection {
         Self::base_selection(
             [
-                (
+                Some((
                     "data".to_string(),
                     PrismaValue::List(
                         set_params
                             .into_iter()
                             .map(|fields| {
                                 PrismaValue::Object(merge_fields(
-                                    fields.into_iter().map(Into::into).collect(),
+                                    fields.into_iter().map(Into::into).map(Into::into).collect(),
                                 ))
                             })
                             .collect(),
                     )
                     .into(),
-                ),
-                #[cfg(not(any(feature = "mongodb", feature = "mssql")))]
-                (
-                    "skipDuplicates".to_string(),
-                    PrismaValue::Boolean(_skip_duplicates).into(),
-                ),
-            ],
+                )),
+                _skip_duplicates.then(|| {
+                    (
+                        "skipDuplicates".to_string(),
+                        PrismaValue::Boolean(_skip_duplicates).into(),
+                    )
+                }),
+            ]
+            .into_iter()
+            .flatten(),
             nested_selections,
         )
     }
diff --git a/src/queries/query.rs b/src/queries/query.rs
index 6811327d..fb27087c 100644
--- a/src/queries/query.rs
+++ b/src/queries/query.rs
@@ -20,6 +20,7 @@ pub trait Query<'a>: QueryConvert {
 pub trait ModelTypes {
     type Data: Data;
     type Where: WhereInput;
+    type UncheckedSet: Into<Self::Set>;
     type Set: Into<(String, PrismaValue)>;
     type With: Into<Selection>;
     type OrderBy: Into<(String, PrismaValue)>;
@@ -125,6 +126,13 @@ pub trait PaginatedQuery<'a>: ModelQuery<'a> {
     fn set_take(&mut self, take: i64);
 }
 
+pub trait UncheckedSetQuery<'a>: ModelQuery<'a> {
+    fn add_unchecked_set(
+        &mut self,
+        param: <<Self as ModelQuery<'a>>::Types as ModelTypes>::UncheckedSet,
+    );
+}
+
 pub trait SetQuery<'a>: ModelQuery<'a> {
     fn add_set(&mut self, param: <<Self as ModelQuery<'a>>::Types as ModelTypes>::Set);
 }
diff --git a/src/queries/update_many.rs b/src/queries/update_many.rs
index 609851af..e16e39ba 100644
--- a/src/queries/update_many.rs
+++ b/src/queries/update_many.rs
@@ -3,20 +3,20 @@ use query_core::Operation;
 
 use crate::{
     merge_fields, BatchResult, ModelOperation, ModelQuery, ModelTypes, ModelWriteOperation,
-    PrismaClientInternals, Query, QueryConvert, SetQuery, WhereInput, WhereQuery,
+    PrismaClientInternals, Query, QueryConvert, UncheckedSetQuery, WhereInput, WhereQuery,
 };
 
 pub struct UpdateMany<'a, Actions: ModelTypes> {
     client: &'a PrismaClientInternals,
     pub where_params: Vec<Actions::Where>,
-    pub set_params: Vec<Actions::Set>,
+    pub set_params: Vec<Actions::UncheckedSet>,
 }
 
 impl<'a, Actions: ModelTypes> UpdateMany<'a, Actions> {
     pub fn new(
         client: &'a PrismaClientInternals,
         where_params: Vec<Actions::Where>,
-        set_params: Vec<Actions::Set>,
+        set_params: Vec<Actions::UncheckedSet>,
     ) -> Self {
         Self {
             client,
@@ -47,7 +47,11 @@ impl<'a, Actions: ModelTypes> Query<'a> for UpdateMany<'a, Actions> {
                     Some((
                         "data".to_string(),
                         PrismaValue::Object(merge_fields(
-                            self.set_params.into_iter().map(Into::into).collect(),
+                            self.set_params
+                                .into_iter()
+                                .map(Into::into)
+                                .map(Into::into)
+                                .collect(),
                         ))
                         .into(),
                     )),
@@ -86,8 +90,8 @@ impl<'a, Actions: ModelTypes> WhereQuery<'a> for UpdateMany<'a, Actions> {
     }
 }
 
-impl<'a, Actions: ModelTypes> SetQuery<'a> for UpdateMany<'a, Actions> {
-    fn add_set(&mut self, param: Actions::Set) {
+impl<'a, Actions: ModelTypes> UncheckedSetQuery<'a> for UpdateMany<'a, Actions> {
+    fn add_unchecked_set(&mut self, param: Actions::UncheckedSet) {
         self.set_params.push(param);
     }
 }


Test patch:
diff --git a/integration-tests/schema.prisma b/integration-tests/schema.prisma
index 60ebd39f..567b4a45 100644
--- a/integration-tests/schema.prisma
+++ b/integration-tests/schema.prisma
@@ -93,3 +93,28 @@ model Ref {
     id   String @id @default(uuid())
     impl Int
 }
+
+// https://github.com/Brendonovich/prisma-client-rust/issues/282
+model Child {
+    // Fields
+    name                String  @unique
+    primary_parent_name String?
+
+    // Relations
+    primary_parent Parent?  @relation("primary_child", fields: [name, primary_parent_name], references: [primary_child_name, name])
+    parents        Parent[]
+
+    @@unique([name, primary_parent_name])
+}
+
+model Parent {
+    // Fields
+    name               String @default("default")
+    primary_child_name String
+
+    // Relations
+    child             Child  @relation(fields: [primary_child_name], references: [name], onDelete: Cascade)
+    is_primary_parent Child? @relation("primary_child")
+
+    @@unique([primary_child_name, name])
+}
diff --git a/integration-tests/tests/count.rs b/integration-tests/tests/count.rs
index fc3f35a4..4f2f2f20 100644
--- a/integration-tests/tests/count.rs
+++ b/integration-tests/tests/count.rs
@@ -5,9 +5,9 @@ async fn create_posts(client: &PrismaClient) -> TestResult {
     client
         .post()
         .create_many(vec![
-            post::create("Hi from Prisma!".to_string(), true, vec![]),
-            post::create("Hi from Prisma!".to_string(), true, vec![]),
-            post::create("Hi from Prisma!".to_string(), false, vec![]),
+            post::create_unchecked("Hi from Prisma!".to_string(), true, vec![]),
+            post::create_unchecked("Hi from Prisma!".to_string(), true, vec![]),
+            post::create_unchecked("Hi from Prisma!".to_string(), false, vec![]),
         ])
         .exec()
         .await?;
diff --git a/integration-tests/tests/create.rs b/integration-tests/tests/create.rs
index c1358e30..77e48cfc 100644
--- a/integration-tests/tests/create.rs
+++ b/integration-tests/tests/create.rs
@@ -79,3 +79,25 @@ async fn set_none() -> TestResult {
 
     cleanup(client).await
 }
+
+#[tokio::test]
+async fn unchecked() -> TestResult {
+    let client = client().await;
+
+    let user = client
+        .user()
+        .create("Brendan".to_string(), vec![])
+        .exec()
+        .await?;
+
+    let file_path = client
+        .file_path()
+        .create_unchecked(0, "".to_string(), user.id, vec![])
+        .include(file_path::include!({ user }))
+        .exec()
+        .await?;
+
+    assert_eq!(&file_path.user.name, &user.name);
+
+    cleanup(client).await
+}
diff --git a/integration-tests/tests/lib.rs b/integration-tests/tests/lib.rs
index e0d881fa..d141fd51 100644
--- a/integration-tests/tests/lib.rs
+++ b/integration-tests/tests/lib.rs
@@ -8,7 +8,7 @@ mod utils;
 async fn aaaa_run_migrations() -> TestResult {
     let client = db::new_client().await.unwrap();
 
-    client._db_push().await.unwrap();
+    client._db_push().accept_data_loss().await.unwrap();
 
     client
         .user()
diff --git a/integration-tests/tests/update.rs b/integration-tests/tests/update.rs
index e49928c6..41578d8b 100644
--- a/integration-tests/tests/update.rs
+++ b/integration-tests/tests/update.rs
@@ -130,6 +130,41 @@ async fn disconnect() -> TestResult {
     cleanup(client).await
 }
 
+#[tokio::test]
+async fn unchecked() -> TestResult {
+    let client = client().await;
+
+    let user_id = create_user(&client).await?;
+
+    let user = client
+        .user()
+        .find_unique(user::id::equals(user_id.clone()))
+        .with(user::posts::fetch(vec![]))
+        .exec()
+        .await?
+        .unwrap();
+    assert_eq!(user.posts.unwrap().len(), 0);
+
+    let post = client
+        .post()
+        .create("My post".to_string(), true, vec![])
+        .exec()
+        .await?;
+
+    let updated = client
+        .post()
+        .update_unchecked(
+            post::id::equals(post.id.clone()),
+            vec![post::author_id::set(Some(user.id.clone()))],
+        )
+        .with(post::author::fetch())
+        .exec()
+        .await?;
+    assert!(updated.author().unwrap().is_some());
+
+    cleanup(client).await
+}
+
 #[tokio::test]
 async fn atomic() -> TestResult {
     let client = client().await;
diff --git a/integration-tests/tests/utils.rs b/integration-tests/tests/utils.rs
index e6e0218e..8d5528e1 100644
--- a/integration-tests/tests/utils.rs
+++ b/integration-tests/tests/utils.rs
@@ -30,6 +30,8 @@ pub async fn cleanup(client: PrismaClient) -> TestResult {
             client.profile().delete_many(vec![]),
             client.user().delete_many(vec![]),
             client.types().delete_many(vec![]),
+            client.child().delete_many(vec![]),
+            client.parent().delete_many(vec![]),
         ))
         .await
         .unwrap();