Compare commits
4 commits
e3ce642226
...
2da8721778
| Author | SHA1 | Date | |
|---|---|---|---|
| 2da8721778 | |||
| 5e0ffe67c3 | |||
| cbe60d1bd2 | |||
| dc77c71f68 |
6 changed files with 49 additions and 55 deletions
|
|
@ -186,7 +186,7 @@ file or class name and description of purpose be included on the
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2020 LaunchBadge, LLC
|
Copyright 2025 Matthieu Bessat
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2020 LaunchBadge, LLC
|
Copyright (c) 2025 Matthieu Bessat
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
Permission is hereby granted, free of charge, to any
|
||||||
person obtaining a copy of this software and associated
|
person obtaining a copy of this software and associated
|
||||||
|
|
|
||||||
2
TODO.md
2
TODO.md
|
|
@ -14,7 +14,7 @@
|
||||||
- insert
|
- insert
|
||||||
- update
|
- update
|
||||||
- delete_by_id
|
- delete_by_id
|
||||||
- custom queries
|
- [ ] delete_many
|
||||||
|
|
||||||
- [ ] Config file for project
|
- [ ] Config file for project
|
||||||
- configure models path
|
- configure models path
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use quote::{format_ident, quote};
|
||||||
use syn::File;
|
use syn::File;
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
|
|
||||||
use crate::{generators::repositories::relations::{gen_get_many_by_related_entities_method, gen_get_many_by_related_entity_method}, models::{Field, FieldForeignMode, Model}};
|
use crate::{generators::repositories::relations::gen_get_many_of_related_entity_method, models::{Field, FieldForeignMode, Model}};
|
||||||
use crate::generators::{SourceNode, SourceNodeContainer};
|
use crate::generators::{SourceNode, SourceNodeContainer};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -242,6 +242,42 @@ fn gen_delete_by_id_method(model: &Model) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gen_delete_many_by_id_method(model: &Model) -> TokenStream {
|
||||||
|
let primary_key = &model.fields.iter()
|
||||||
|
.find(|f| f.is_primary)
|
||||||
|
.expect("A model must have at least one primary key")
|
||||||
|
.name;
|
||||||
|
|
||||||
|
let func_name_ident = format_ident!("delete_many_by_{}", primary_key);
|
||||||
|
let delete_query_tmpl = format!(
|
||||||
|
"DELETE FROM {} WHERE {} IN ({{}})",
|
||||||
|
model.table_name,
|
||||||
|
primary_key
|
||||||
|
);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
pub async fn #func_name_ident(&self, ids: &[&str]) -> Result<(), sqlx::Error> {
|
||||||
|
if ids.is_empty() {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
let placeholder_params: String = (1..=(ids.len()))
|
||||||
|
.map(|i| format!("${}", i))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(",");
|
||||||
|
let query_sql = format!(#delete_query_tmpl, placeholder_params);
|
||||||
|
let mut query = sqlx::query(&query_sql);
|
||||||
|
for item_id in ids {
|
||||||
|
query = query.bind(item_id)
|
||||||
|
}
|
||||||
|
query
|
||||||
|
.execute(&self.db.0)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn generate_repository_file(all_models: &[Model], model: &Model) -> Result<SourceNodeContainer> {
|
pub fn generate_repository_file(all_models: &[Model], model: &Model) -> Result<SourceNodeContainer> {
|
||||||
let resource_name = model.name.clone();
|
let resource_name = model.name.clone();
|
||||||
|
|
@ -268,6 +304,7 @@ pub fn generate_repository_file(all_models: &[Model], model: &Model) -> Result<S
|
||||||
let insert_many_method_code = gen_insert_many_method(model);
|
let insert_many_method_code = gen_insert_many_method(model);
|
||||||
let update_by_id_method_code = gen_update_by_id_method(model);
|
let update_by_id_method_code = gen_update_by_id_method(model);
|
||||||
let delete_by_id_method_code = gen_delete_by_id_method(model);
|
let delete_by_id_method_code = gen_delete_by_id_method(model);
|
||||||
|
let delete_many_by_id_method_code = gen_delete_many_by_id_method(model);
|
||||||
|
|
||||||
|
|
||||||
let query_by_field_methods: Vec<TokenStream> =
|
let query_by_field_methods: Vec<TokenStream> =
|
||||||
|
|
@ -295,10 +332,7 @@ pub fn generate_repository_file(all_models: &[Model], model: &Model) -> Result<S
|
||||||
match f.foreign_mode { FieldForeignMode::ForeignRef(_) => true, FieldForeignMode::NotRef => false }
|
match f.foreign_mode { FieldForeignMode::ForeignRef(_) => true, FieldForeignMode::NotRef => false }
|
||||||
).collect();
|
).collect();
|
||||||
let related_entity_methods_codes: Vec<TokenStream> = fields_with_foreign_refs.iter().map(|field|
|
let related_entity_methods_codes: Vec<TokenStream> = fields_with_foreign_refs.iter().map(|field|
|
||||||
gen_get_many_by_related_entity_method(model, &field)
|
gen_get_many_of_related_entity_method(model, &field)
|
||||||
).collect();
|
|
||||||
let related_entities_methods_codes: Vec<TokenStream> = fields_with_foreign_refs.iter().map(|field|
|
|
||||||
gen_get_many_by_related_entities_method(all_models, model, &field)
|
|
||||||
).collect();
|
).collect();
|
||||||
|
|
||||||
// TODO: add import line
|
// TODO: add import line
|
||||||
|
|
@ -331,13 +365,13 @@ pub fn generate_repository_file(all_models: &[Model], model: &Model) -> Result<S
|
||||||
|
|
||||||
#delete_by_id_method_code
|
#delete_by_id_method_code
|
||||||
|
|
||||||
|
#delete_many_by_id_method_code
|
||||||
|
|
||||||
#(#query_by_field_methods)*
|
#(#query_by_field_methods)*
|
||||||
|
|
||||||
#(#query_many_by_field_methods)*
|
#(#query_many_by_field_methods)*
|
||||||
|
|
||||||
#(#related_entity_methods_codes)*
|
#(#related_entity_methods_codes)*
|
||||||
|
|
||||||
#(#related_entities_methods_codes)*
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// convert TokenStream into rust code as string
|
// convert TokenStream into rust code as string
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ use quote::{format_ident, quote};
|
||||||
|
|
||||||
use crate::models::{Field, FieldForeignMode, Model};
|
use crate::models::{Field, FieldForeignMode, Model};
|
||||||
|
|
||||||
pub fn gen_get_many_by_related_entity_method(model: &Model, foreign_key_field: &Field) -> TokenStream {
|
/// method that can be used to retreive a list of entities of type X that are the children of a parent type Y
|
||||||
|
/// ex: get all comments of a post
|
||||||
|
pub fn gen_get_many_of_related_entity_method(model: &Model, foreign_key_field: &Field) -> TokenStream {
|
||||||
let resource_ident = format_ident!("{}", &model.name);
|
let resource_ident = format_ident!("{}", &model.name);
|
||||||
|
|
||||||
let foreign_ref_params = match &foreign_key_field.foreign_mode {
|
let foreign_ref_params = match &foreign_key_field.foreign_mode {
|
||||||
|
|
@ -15,7 +17,7 @@ pub fn gen_get_many_by_related_entity_method(model: &Model, foreign_key_field: &
|
||||||
|
|
||||||
let select_query = format!("SELECT * FROM {} WHERE {} = $1", model.table_name, foreign_key_field.name);
|
let select_query = format!("SELECT * FROM {} WHERE {} = $1", model.table_name, foreign_key_field.name);
|
||||||
|
|
||||||
let func_name_ident = format_ident!("get_many_{}_by_{}", foreign_ref_params.reverse_relation_name, foreign_ref_params.target_resource_name);
|
let func_name_ident = format_ident!("get_many_of_{}", foreign_ref_params.target_resource_name);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub async fn #func_name_ident(&self, item_id: &str) -> Result<Vec<#resource_ident>, sqlx::Error> {
|
pub async fn #func_name_ident(&self, item_id: &str) -> Result<Vec<#resource_ident>, sqlx::Error> {
|
||||||
|
|
@ -27,45 +29,3 @@ pub fn gen_get_many_by_related_entity_method(model: &Model, foreign_key_field: &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_get_many_by_related_entities_method(all_models: &[Model], model: &Model, foreign_key_field: &Field) -> TokenStream {
|
|
||||||
let resource_ident = format_ident!("{}", &model.name);
|
|
||||||
|
|
||||||
let foreign_ref_params = match &foreign_key_field.foreign_mode {
|
|
||||||
FieldForeignMode::ForeignRef(params) => params,
|
|
||||||
FieldForeignMode::NotRef => {
|
|
||||||
panic!("Expected foreign key");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let select_query = format!("SELECT * FROM {} WHERE {} IN ({{}})", model.table_name, foreign_key_field.name);
|
|
||||||
|
|
||||||
let target_resource = all_models.iter()
|
|
||||||
.find(|m| m.name.to_lowercase() == foreign_ref_params.target_resource_name.to_lowercase())
|
|
||||||
.expect("Could not find foreign ref target type associated resource");
|
|
||||||
|
|
||||||
let func_name_ident = format_ident!("get_many_{}_by_{}", foreign_ref_params.reverse_relation_name, target_resource.table_name);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
pub async fn #func_name_ident(&self, items_ids: Vec<String>) -> Result<Vec<#resource_ident>, sqlx::Error> {
|
|
||||||
if items_ids.is_empty() {
|
|
||||||
return Ok(vec![])
|
|
||||||
}
|
|
||||||
let placeholder_params: String = (1..=(items_ids.len()))
|
|
||||||
.map(|i| format!("${i}"))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(",");
|
|
||||||
let query_tmpl = format!(
|
|
||||||
#select_query,
|
|
||||||
placeholder_params
|
|
||||||
);
|
|
||||||
let mut query = sqlx::query_as::<_, #resource_ident>(&query_tmpl);
|
|
||||||
for id in items_ids {
|
|
||||||
query = query.bind(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
query
|
|
||||||
.fetch_all(&self.db.0)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ pub fn parse_models(source_code_path: &Path) -> Result<Vec<Model>> {
|
||||||
output_field.foreign_mode = FieldForeignMode::ForeignRef(
|
output_field.foreign_mode = FieldForeignMode::ForeignRef(
|
||||||
ForeignRefParams {
|
ForeignRefParams {
|
||||||
reverse_relation_name: rrn,
|
reverse_relation_name: rrn,
|
||||||
target_resource_name: target_type_name.to_lowercase()
|
target_resource_name: target_type_name.to_case(Case::Snake)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue