|
|
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| License.md | ||
| ReadMe.md | ||
ReadMe.md
Update Macro for SQLx
Overview
This derive macro provides a convenient way to generate update forms and related methods for database entities using SQLx. It's designed to work with MySQL databases and provides flexibility in naming conventions for tables and fields. Additionally, it now supports the use of id, code, or any custom primary key field through the primary_key attribute.
Features
- Generates an update form struct with optional fields
- Creates methods for generating SQL update statements
- Implements a builder pattern for setting update values
- Provides methods for comparing the update form with both the original model and the database record, returning JSON objects
- Allows custom table names and field names through optional attributes
- Supports specifying custom primary keys with the
primary_keyattribute - Generates a method to get the table name for use in SQL queries
- Includes an
initial_diffmethod to get a JSON representation of all fields in the model - Supports database transactions for atomic operations
- Optimized for better performance with large structs
Installation
Add the following to your Cargo.toml:
[dependencies]
entity_update_derive = { path = "path/to/entity_update_derive" }
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "mysql", "json"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }
Usage
Basic Usage with Default Primary Key (id or code)
use entity_update_derive::Update;
use sqlx::FromRow;
#[derive(Update, FromRow, Debug)]
struct User {
id: i32,
name: String,
email: Option<String>,
}
This will generate a UserUpdateForm struct and associated methods, with id as the primary key. If your struct uses code as the primary key, the macro will automatically detect and use it.
Specifying a Custom Primary Key
You can specify a custom primary key field using the primary_key attribute:
#[derive(Update, FromRow, Debug)]
struct User {
#[primary_key]
code: String,
name: String,
email: Option<String>,
}
Custom Table Name
You can specify a custom table name using the table_name attribute:
#[derive(Update, FromRow, Debug)]
#[table_name("customers")]
struct User {
id: i32,
name: String,
email: Option<String>,
}
Custom Field Names
You can specify custom field names for the database using the rename attribute:
#[derive(Update, FromRow, Debug)]
struct User {
id: i32,
#[rename("user_name")]
name: String,
#[rename("user_email")]
email: Option<String>,
}
Using the Generated Update Form with Transactions
use sqlx::mysql::MySqlPool;
use entity_update_derive::Update;
use sqlx::FromRow;
#[derive(Update, FromRow, Debug)]
struct User {
id: i32,
name: String,
email: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let pool = MySqlPool::connect("mysql://username:password@localhost/database_name").await?;
let form = User::update_form()
.with_name("new_username".to_string())
.with_email(Some("new_email@example.com".to_string()));
let user_id = 1;
let mut tx = pool.begin().await?;
form.execute_update(&user_id, &mut tx).await?;
let diff = form.transactional_db_diff(&user_id, &mut tx).await?;
println!("Diff: {:?}", diff);
tx.commit().await?;
println!("Update completed successfully");
Ok(())
}
Generated Methods
update_form()
Creates a new instance of the update form.
let form = User::update_form();
with_field_name()
Builder method for each field in the struct.
let form = User::update_form()
.with_name("New Name")
.with_email(Some("new_email@example.com"));
update_stmt()
Generates the SQL SET clause for the update statement.
let stmt = form.update_stmt();
bind_values()
Binds the update values to a SQLx query.
let query = sqlx::query("UPDATE users SET ...");
let query = form.bind_values(query);
model_diff()
Compares the update form with an instance of the original struct and returns a JSON object.
let diff: serde_json::Value = form.model_diff(&original_user);
db_diff()
Compares the update form with the current database record and returns a JSON object.
let diff: serde_json::Value = form.db_diff(&user_id, &pool).await?;
table_name()
Returns the table name as a static string.
let table_name = UserUpdateForm::table_name();
initial_diff()
Returns a JSON object containing all fields of the original model and their current values.
let user = User {
id: 1,
name: "John Doe".to_string(),
email: Some("john@example.com".to_string()),
};
let initial_diff: serde_json::Value = user.initial_diff();
Notes
- This macro now supports custom primary key fields using the
primary_keyattribute. If not specified, it defaults to checking for anidorcodefield. - The macro assumes you're using MySQL. Modifications may be needed for other database types.
- Error handling is minimal in these examples. In a production environment, you should implement proper error handling and logging.
- The
model_diff(),db_diff(), andinitial_diff()methods returnserde_json::Valueobjects, which are easy to work with when dealing with JSON data.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the Nandie Software Proprietary License. See the LICENSE file in the project root for the full license text.