mirror of
https://github.com/Phundrak/georm.git
synced 2025-08-30 14:15:35 +00:00
feat: deprecate create_or_update
in favour of upsert
The `create_or_update` method has been deprecated and replaced by `upsert` for clarity and consistency with common database terminology. This commit also removes the file `src/entity.rs` which has been forgotten in earlier commits and was no longer part of Georm.
This commit is contained in:
parent
49c7d86102
commit
5d8a1b1917
@ -557,7 +557,7 @@ Post::find(executor, &post_id).await?;
|
||||
// Mutation operations
|
||||
post.create(executor).await?;
|
||||
post.update(executor).await?;
|
||||
post.create_or_update(executor).await?;
|
||||
post.upsert(executor).await?;
|
||||
post.delete(executor).await?;
|
||||
Post::delete_by_id(executor, &post_id).await?;
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl Profile {
|
||||
&mut self,
|
||||
display_name: Option<String>,
|
||||
bio: Option<String>,
|
||||
executor: E
|
||||
executor: E,
|
||||
) -> Result<Self>
|
||||
where
|
||||
E: sqlx::Executor<'e, Database = sqlx::Postgres>,
|
||||
|
@ -69,7 +69,7 @@ impl User {
|
||||
pub async fn get_user_by_id_or_select<'e, E>(
|
||||
id: Option<i32>,
|
||||
prompt: &str,
|
||||
executor: E
|
||||
executor: E,
|
||||
) -> Result<Self>
|
||||
where
|
||||
E: sqlx::Executor<'e, Database = sqlx::Postgres>,
|
||||
@ -128,8 +128,7 @@ impl User {
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
pub async fn update_profile(id: Option<i32>, pool: &sqlx::PgPool) -> Result<(User, Profile)>
|
||||
{
|
||||
pub async fn update_profile(id: Option<i32>, pool: &sqlx::PgPool) -> Result<(User, Profile)> {
|
||||
let prompt = "Select the user whose profile you want to update";
|
||||
let user = Self::get_user_by_id_or_select(id, prompt, pool).await?;
|
||||
let profile = match user.get_profile(pool).await? {
|
||||
|
@ -44,7 +44,7 @@ pub fn generate_upsert_query(
|
||||
let field_idents: Vec<syn::Ident> = fields.iter().map(|f| f.ident.clone()).collect();
|
||||
|
||||
quote! {
|
||||
async fn create_or_update<'e, E>(&self, mut executor: E) -> ::sqlx::Result<Self>
|
||||
async fn upsert<'e, E>(&self, mut executor: E) -> ::sqlx::Result<Self>
|
||||
where
|
||||
E: ::sqlx::Executor<'e, Database = ::sqlx::Postgres>
|
||||
{
|
||||
|
@ -1,83 +0,0 @@
|
||||
pub trait Georm<Id> {
|
||||
/// Find all the entities in the database.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn find_all(
|
||||
pool: &sqlx::PgPool,
|
||||
) -> impl ::std::future::Future<Output = ::sqlx::Result<Vec<Self>>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Find the entiy in the database based on its identifier.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn find(
|
||||
pool: &sqlx::PgPool,
|
||||
id: &Id,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<Option<Self>>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Create the entity in the database.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn create(
|
||||
&self,
|
||||
pool: &sqlx::PgPool,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Update an entity with a matching identifier in the database.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn update(
|
||||
&self,
|
||||
pool: &sqlx::PgPool,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Update an entity with a matching identifier in the database if
|
||||
/// it exists, create it otherwise.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn create_or_update(
|
||||
&self,
|
||||
pool: &sqlx::PgPool,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Delete the entity from the database if it exists.
|
||||
///
|
||||
/// # Returns
|
||||
/// Returns the amount of rows affected by the deletion.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn delete(
|
||||
&self,
|
||||
pool: &sqlx::PgPool,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
|
||||
|
||||
/// Delete any entity with the identifier `id`.
|
||||
///
|
||||
/// # Returns
|
||||
/// Returns the amount of rows affected by the deletion.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns any error Postgres may have encountered
|
||||
fn delete_by_id(
|
||||
pool: &sqlx::PgPool,
|
||||
id: &Id,
|
||||
) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
|
||||
|
||||
/// Returns the identifier of the entity.
|
||||
fn get_id(&self) -> &Id;
|
||||
}
|
17
src/georm.rs
17
src/georm.rs
@ -26,7 +26,7 @@ use sqlx::{Executor, Postgres};
|
||||
/// ### Instance Methods (Mutation Operations)
|
||||
/// - [`create`] - Insert a new entity into the database
|
||||
/// - [`update`] - Update an existing entity in the database
|
||||
/// - [`create_or_update`] - Upsert (insert or update) an entity
|
||||
/// - [`upsert`] - Upsert (insert or update) an entity
|
||||
/// - [`delete`] - Delete this entity from the database
|
||||
/// - [`get_id`] - Get the primary key of this entity
|
||||
///
|
||||
@ -92,7 +92,7 @@ use sqlx::{Executor, Postgres};
|
||||
/// [`find`]: Georm::find
|
||||
/// [`create`]: Georm::create
|
||||
/// [`update`]: Georm::update
|
||||
/// [`create_or_update`]: Georm::create_or_update
|
||||
/// [`upsert`]: Georm::upsert
|
||||
/// [`delete`]: Georm::delete
|
||||
/// [`delete_by_id`]: Georm::delete_by_id
|
||||
/// [`get_id`]: Georm::get_id
|
||||
@ -264,7 +264,7 @@ pub trait Georm<Id> {
|
||||
/// # Examples
|
||||
/// ```ignore
|
||||
/// let user = User { id: 1, username: "alice".into(), email: "alice@example.com".into() };
|
||||
/// let final_user = user.create_or_update(&pool).await?;
|
||||
/// let final_user = user.upsert(&pool).await?;
|
||||
/// // Will insert if ID 1 doesn't exist, update if it does
|
||||
/// ```
|
||||
///
|
||||
@ -273,13 +273,22 @@ pub trait Georm<Id> {
|
||||
/// - Non-primary-key constraint violations
|
||||
/// - Database connection issues
|
||||
/// - Permission problems
|
||||
fn upsert<'e, E>(&self, executor: E) -> impl ::std::future::Future<Output = sqlx::Result<Self>>
|
||||
where
|
||||
Self: Sized,
|
||||
E: Executor<'e, Database = Postgres>;
|
||||
|
||||
#[deprecated(since = "0.3.0", note = "Please use `upsert` instead")]
|
||||
fn create_or_update<'e, E>(
|
||||
&self,
|
||||
executor: E,
|
||||
) -> impl ::std::future::Future<Output = sqlx::Result<Self>>
|
||||
where
|
||||
Self: Sized,
|
||||
E: Executor<'e, Database = Postgres>;
|
||||
E: Executor<'e, Database = Postgres>,
|
||||
{
|
||||
self.upsert(executor)
|
||||
}
|
||||
|
||||
/// Delete this entity from the database.
|
||||
///
|
||||
|
@ -33,7 +33,7 @@
|
||||
//! ### Instance Methods (called on entity objects)
|
||||
//! - `entity.create(pool)` - Insert new record, returns created entity with database-generated values
|
||||
//! - `entity.update(pool)` - Update existing record, returns updated entity with fresh database state
|
||||
//! - `entity.create_or_update(pool)` - True PostgreSQL upsert using `ON CONFLICT`, returns final entity
|
||||
//! - `entity.upsert(pool)` - True PostgreSQL upsert using `ON CONFLICT`, returns final entity
|
||||
//! - `entity.delete(pool)` - Delete this record, returns affected row count
|
||||
//! - `entity.get_id()` - Get reference to the entity's ID (`&Id` for simple keys, owned for composite)
|
||||
//!
|
||||
@ -55,7 +55,7 @@
|
||||
//! Georm leverages PostgreSQL-specific features for performance and reliability:
|
||||
//!
|
||||
//! - **RETURNING clause**: All `INSERT` and `UPDATE` operations use `RETURNING *` to capture database-generated values (sequences, defaults, triggers)
|
||||
//! - **True upserts**: `create_or_update()` uses `INSERT ... ON CONFLICT ... DO UPDATE` for atomic upsert operations
|
||||
//! - **True upserts**: `upsert()` uses `INSERT ... ON CONFLICT ... DO UPDATE` for atomic upsert operations
|
||||
//! - **Prepared statements**: All queries use parameter binding for security and performance
|
||||
//! - **Compile-time verification**: SQLx macros verify all generated SQL against your database schema at compile time
|
||||
//!
|
||||
|
@ -36,7 +36,7 @@ fn composite_key_get_id() {
|
||||
}
|
||||
|
||||
#[sqlx::test(fixtures("composite_key"))]
|
||||
async fn composite_key_create_or_update(pool: sqlx::PgPool) -> sqlx::Result<()> {
|
||||
async fn composite_key_upsert(pool: sqlx::PgPool) -> sqlx::Result<()> {
|
||||
let new_user_role = UserRole {
|
||||
user_id: 5,
|
||||
role_id: 2,
|
||||
@ -44,7 +44,7 @@ async fn composite_key_create_or_update(pool: sqlx::PgPool) -> sqlx::Result<()>
|
||||
};
|
||||
|
||||
// This will test the upsert query generation bug
|
||||
let result = new_user_role.create_or_update(&pool).await?;
|
||||
let result = new_user_role.upsert(&pool).await?;
|
||||
assert_eq!(5, result.user_id);
|
||||
assert_eq!(2, result.role_id);
|
||||
|
||||
|
@ -52,7 +52,7 @@ async fn upsert_handles_generated_fields(pool: sqlx::PgPool) -> sqlx::Result<()>
|
||||
let mut modified_product = product.clone();
|
||||
modified_product.price = BigDecimal::from(1200);
|
||||
|
||||
let upserted = modified_product.create_or_update(&pool).await?;
|
||||
let upserted = modified_product.upsert(&pool).await?;
|
||||
|
||||
// price is updated
|
||||
assert_eq!(upserted.price, BigDecimal::from(1200));
|
||||
|
@ -115,7 +115,7 @@ async fn should_create_if_does_not_exist(pool: sqlx::PgPool) -> sqlx::Result<()>
|
||||
name: "Miura Kentaro".into(),
|
||||
..Default::default()
|
||||
};
|
||||
author.create_or_update(&pool).await?;
|
||||
author.upsert(&pool).await?;
|
||||
let all_authors = Author::find_all(&pool).await?;
|
||||
assert_eq!(1, all_authors.len());
|
||||
Ok(())
|
||||
@ -130,7 +130,7 @@ async fn should_update_if_exist(pool: sqlx::PgPool) -> sqlx::Result<()> {
|
||||
name: "Miura Kentaro".into(),
|
||||
..Default::default()
|
||||
};
|
||||
author.create_or_update(&pool).await?;
|
||||
author.upsert(&pool).await?;
|
||||
let mut all_authors = Author::find_all(&pool).await?;
|
||||
all_authors.sort();
|
||||
assert_eq!(3, all_authors.len());
|
||||
|
Loading…
x
Reference in New Issue
Block a user