diff --git a/lib/sqlx_tools_generator_cli/src/gen_repositories.rs b/lib/sqlx_tools_generator_cli/src/gen_repositories.rs index 7e989dd..41100e3 100644 --- a/lib/sqlx_tools_generator_cli/src/gen_repositories.rs +++ b/lib/sqlx_tools_generator_cli/src/gen_repositories.rs @@ -80,6 +80,56 @@ fn gen_insert_method(model: &Model) -> TokenStream { } } +fn gen_insert_many_method(model: &Model) -> TokenStream { + let resource_ident = format_ident!("{}", &model.name); + let error_msg = format!("Failed to insert many entities of resource {:?}", model.name.clone()); + let sql_columns = model.fields.iter() + .map(|f| f.name.clone()) + .collect::<Vec<String>>() + .join(", "); + let base_insert_query = format!( + "INSERT INTO {} ({}) VALUES {{}} ON CONFLICT DO NOTHING", + model.table_name, + sql_columns + ); + let field_names: Vec<proc_macro2::Ident> = model.fields.iter() + .map(|f| format_ident!("{}", &f.name)) + .collect(); + let fields_count: usize = model.fields.len(); + + quote! { + pub async fn insert_many(&self, entities: &Vec<#resource_ident>) -> Result<()> { + let values_templates: String = (1..(#fields_count*entities.len()+1)) + .collect::<Vec<usize>>() + .chunks(#fields_count) + .map(|c| c.to_vec()) + .map(|x| format!( + "({})", + x.iter() + .map(|i| format!("${}", i)) + .collect::<Vec<String>>() + .join(", ") + )) + .collect::<Vec<String>>() + .join(", "); + let query_sql = format!(#base_insert_query, values_templates); + + let mut query = sqlx::query(&query_sql); + for entity in entities { + query = query + #( .bind( &entity.#field_names ) )*; + } + query + .execute(&self.db.0) + .await + .context(#error_msg)?; + + Ok(()) + } + } +} + + fn generate_repository_file(model: &Model) -> Result<SourceNodeContainer> { let resource_name = model.name.clone(); @@ -91,6 +141,7 @@ fn generate_repository_file(model: &Model) -> Result<SourceNodeContainer> { let get_all_method_code = gen_get_all_method(&model); let get_by_id_method_code = gen_get_by_id_method(&model); let insert_method_code = gen_insert_method(&model); + let insert_many_method_code = gen_insert_many_method(&model); // TODO: add import line @@ -115,6 +166,8 @@ fn generate_repository_file(model: &Model) -> Result<SourceNodeContainer> { #get_by_id_method_code #insert_method_code + + #insert_many_method_code } }; // convert TokenStream into rust code as string