From 55fc2e7f19cf1a7c78ba3903c20af730980f037a Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 22 May 2023 22:05:09 +0200 Subject: [PATCH] Add --no-crud option to skip generating CRUD functions In certain cases it might be not desireable to write CRUD functions by hand. To avoid conflict this change adds the option to skip generating those functions. This for example is a workaround for MySQL which currently is not supported by the generated functions or to support unsigned integers in id fields. Related: https://github.com/Wulf/dsync/issues/46 Related: https://github.com/Wulf/dsync/issues/47 --- README.md | 1 + src/bin/main.rs | 11 +++++- src/code.rs | 37 +++++++++++++++---- src/lib.rs | 18 +++++++-- test/simple_table_no_crud/models/mod.rs | 1 + .../models/todos/generated.rs | 35 ++++++++++++++++++ test/simple_table_no_crud/models/todos/mod.rs | 2 + test/simple_table_no_crud/schema.rs | 10 +++++ test/simple_table_no_crud/test.sh | 7 ++++ 9 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 test/simple_table_no_crud/models/mod.rs create mode 100644 test/simple_table_no_crud/models/todos/generated.rs create mode 100644 test/simple_table_no_crud/models/todos/mod.rs create mode 100644 test/simple_table_no_crud/schema.rs create mode 100755 test/simple_table_no_crud/test.sh diff --git a/README.md b/README.md index 3b299de1..4392a079 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ cargo install dsync * `--model-path`: (optional) set a custom model import path, default `crate::models::` * `--schema-path`: (optional) set a custom schema import path, default `crate::schema::` * `--no-serde`: (optional) if set, does not output any serde related code +* `--no-crud`: (optional) Do not generate the CRUD functions for generated models * note: the CLI has fail-safes to prevent accidental file overwriting ```sh diff --git a/src/bin/main.rs b/src/bin/main.rs index 0e3c7b67..04809f99 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -72,6 +72,11 @@ struct Args { help = "Optional; Disable generating serde implementations" )] no_serde: bool, + #[structopt( + long = "no-crud", + help = "Optional; Do not generate the CRUD functions for generated models" + )] + no_crud: bool, } fn main() { @@ -89,7 +94,7 @@ fn main() { ); } else { eprintln!("{}", backtrace); - } + } } #[cfg(not(feature = "backtrace"))] { @@ -120,6 +125,10 @@ fn actual_main() -> dsync::Result<()> { default_table_options = default_table_options.disable_serde(); } + if args.no_crud { + default_table_options = default_table_options.disable_fns(); + } + dsync::generate_files( args.input, args.output, diff --git a/src/code.rs b/src/code.rs index 1b33f7e3..6d972c57 100644 --- a/src/code.rs +++ b/src/code.rs @@ -481,25 +481,42 @@ fn build_imports(table: &ParsedTableMacro, config: &GenerationConfig) -> String "" }; + let fns_imports = if table_options.get_fns() { + "\nuse diesel::QueryResult;" + } else { + "" + }; + + let connection_type_alias = if table_options.get_fns() { + format!( + "\ntype Connection = {connection_type};", + connection_type = config.connection_type, + ) + } else { + "".to_string() + }; + format!( indoc! {" use crate::diesel::*; - use {schema_path}; - use diesel::QueryResult; + use {schema_path};{fns_imports} {serde_imports}{async_imports} {belongs_imports} - - type Connection = {connection_type}; + {connection_type_alias} "}, - connection_type = config.connection_type, belongs_imports = belongs_imports, async_imports = async_imports, schema_path = schema_path, - serde_imports = serde_imports + serde_imports = serde_imports, + fns_imports = fns_imports, + connection_type_alias = connection_type_alias, ) + .trim_end() + .to_string() } pub fn generate_for_table(table: ParsedTableMacro, config: &GenerationConfig) -> String { + let table_options = config.table(&table.name.to_string()); // first, we generate struct code let read_struct = Struct::new(StructType::Read, &table, config); let update_struct = Struct::new(StructType::Update, &table, config); @@ -512,8 +529,12 @@ pub fn generate_for_table(table: ParsedTableMacro, config: &GenerationConfig) -> structs.push('\n'); structs.push_str(update_struct.code()); - let functions = build_table_fns(&table, config, create_struct, update_struct); + let functions = if table_options.get_fns() { + build_table_fns(&table, config, create_struct, update_struct) + } else { + "".to_string() + }; let imports = build_imports(&table, config); - format!("{FILE_SIGNATURE}\n\n{imports}\n{structs}\n{functions}") + format!("{FILE_SIGNATURE}\n\n{imports}\n\n{structs}\n{functions}") } diff --git a/src/lib.rs b/src/lib.rs index d12f22c4..c1bda207 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ mod code; +pub mod error; mod file; mod parser; -pub mod error; use error::IOErrorToError; pub use error::{Error, Result}; @@ -27,6 +27,9 @@ pub struct TableOptions<'a> { /// Generates serde::Serialize and serde::Deserialize derive implementations use_serde: bool, + + /// Generates the CRUD functions for generated models + fns: bool, } impl<'a> TableOptions<'a> { @@ -48,6 +51,10 @@ impl<'a> TableOptions<'a> { self.use_serde } + pub fn get_fns(&self) -> bool { + self.fns + } + pub fn get_autogenerated_columns(&self) -> &[&'_ str] { self.autogenerated_columns.as_deref().unwrap_or_default() } @@ -82,6 +89,10 @@ impl<'a> TableOptions<'a> { } } + pub fn disable_fns(self) -> Self { + Self { fns: false, ..self } + } + pub fn autogenerated_columns(self, cols: Vec<&'a str>) -> Self { Self { autogenerated_columns: Some(cols.clone()), @@ -103,6 +114,7 @@ impl<'a> TableOptions<'a> { .or_else(|| other.autogenerated_columns.clone()), use_serde: self.use_serde || other.use_serde, + fns: self.fns || other.fns, } } } @@ -117,6 +129,7 @@ impl<'a> Default for TableOptions<'a> { #[cfg(feature = "async")] use_async: Default::default(), use_serde: true, + fns: true, } } } @@ -200,8 +213,7 @@ pub fn generate_files( } // pass 2: delete code for removed tables - for item in std::fs::read_dir(&output_dir).attach_path_err(&output_dir)? - { + for item in std::fs::read_dir(&output_dir).attach_path_err(&output_dir)? { let item = item.attach_path_err(&output_dir)?; // check if item is a directory diff --git a/test/simple_table_no_crud/models/mod.rs b/test/simple_table_no_crud/models/mod.rs new file mode 100644 index 00000000..015a6a2b --- /dev/null +++ b/test/simple_table_no_crud/models/mod.rs @@ -0,0 +1 @@ +pub mod todos; diff --git a/test/simple_table_no_crud/models/todos/generated.rs b/test/simple_table_no_crud/models/todos/generated.rs new file mode 100644 index 00000000..c5dca1ac --- /dev/null +++ b/test/simple_table_no_crud/models/todos/generated.rs @@ -0,0 +1,35 @@ +/* This file is generated and managed by dsync */ + +use crate::diesel::*; +use crate::schema::*; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone, Queryable, Insertable, AsChangeset, Selectable)] +#[diesel(table_name=todos, primary_key(id))] +pub struct Todo { + pub id: i32, + pub unsigned: u32, + pub text: String, + pub completed: bool, + pub created_at: chrono::DateTime, + pub updated_at: chrono::DateTime, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Queryable, Insertable, AsChangeset)] +#[diesel(table_name=todos)] +pub struct CreateTodo { + pub unsigned: u32, + pub text: String, + pub completed: bool, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Queryable, Insertable, AsChangeset)] +#[diesel(table_name=todos)] +pub struct UpdateTodo { + pub unsigned: Option, + pub text: Option, + pub completed: Option, + pub created_at: Option>, + pub updated_at: Option>, +} + diff --git a/test/simple_table_no_crud/models/todos/mod.rs b/test/simple_table_no_crud/models/todos/mod.rs new file mode 100644 index 00000000..a5bb9b90 --- /dev/null +++ b/test/simple_table_no_crud/models/todos/mod.rs @@ -0,0 +1,2 @@ +pub use generated::*; +pub mod generated; diff --git a/test/simple_table_no_crud/schema.rs b/test/simple_table_no_crud/schema.rs new file mode 100644 index 00000000..37cf5cec --- /dev/null +++ b/test/simple_table_no_crud/schema.rs @@ -0,0 +1,10 @@ +diesel::table! { + todos (id) { + id -> Int4, + unsigned -> Unsigned, + text -> Text, + completed -> Bool, + created_at -> Timestamptz, + updated_at -> Timestamptz, + } +} diff --git a/test/simple_table_no_crud/test.sh b/test/simple_table_no_crud/test.sh new file mode 100755 index 00000000..cdfdf0e7 --- /dev/null +++ b/test/simple_table_no_crud/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +cd $SCRIPT_DIR + +cargo run -- -i schema.rs -o models -g id -g created_at -g updated_at -c "diesel::r2d2::PooledConnection>" --no-crud