From 0c89a4b241a98630774d0e706b91572ab6e38b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Tue, 19 May 2026 11:08:01 +0400 Subject: [PATCH] Drop RowsAffected check from Delete methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deletes are idempotent — zero affected rows is not an error. Signed-off-by: Émile Ré --- contrib/claude/coredata.md | 10 +++++++++- pkg/coredata/common_third_party.go | 6 +----- pkg/coredata/common_third_party_domain.go | 6 +----- pkg/coredata/common_tracker_pattern.go | 6 +----- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/contrib/claude/coredata.md b/contrib/claude/coredata.md index 7e5b28184..9ad1d0755 100644 --- a/contrib/claude/coredata.md +++ b/contrib/claude/coredata.md @@ -113,6 +113,8 @@ This ensures the compiler catches renamed or removed enum values instead of sile Use `conn.Query` + `pgx.Collect*` only for `SELECT` and `INSERT … RETURNING` statements that return rows. For `UPDATE` and `DELETE`, use `conn.Exec` — there is no need for `RETURNING` since the caller already owns all the field values. +**Delete must not check `RowsAffected()`.** A DELETE that affects zero rows is not an error — the resource may have already been deleted (idempotent deletes). Only `Update` checks `RowsAffected() == 0` to return `ErrResourceNotFound`. + ```go // Single row (SELECT / INSERT … RETURNING) rows, err := conn.Query(ctx, q, args) @@ -127,7 +129,7 @@ rows, err := conn.Query(ctx, q, args) assets, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Asset]) *a = assets -// Update / Delete — no RETURNING +// Update — no RETURNING, check RowsAffected result, err := conn.Exec(ctx, q, args) if err != nil { return err @@ -135,6 +137,12 @@ if err != nil { if result.RowsAffected() == 0 { return ErrResourceNotFound } + +// Delete — no RETURNING, do NOT check RowsAffected +_, err := conn.Exec(ctx, q, args) +if err != nil { + return err +} ``` ## Sentinel errors diff --git a/pkg/coredata/common_third_party.go b/pkg/coredata/common_third_party.go index 41f66857d..34cb75d03 100644 --- a/pkg/coredata/common_third_party.go +++ b/pkg/coredata/common_third_party.go @@ -429,15 +429,11 @@ func (t CommonThirdParty) Delete( args := pgx.StrictNamedArgs{"id": id} - result, err := conn.Exec(ctx, q, args) + _, err := conn.Exec(ctx, q, args) if err != nil { return fmt.Errorf("cannot delete common third party: %w", err) } - if result.RowsAffected() == 0 { - return ErrResourceNotFound - } - return nil } diff --git a/pkg/coredata/common_third_party_domain.go b/pkg/coredata/common_third_party_domain.go index 207027591..f028b0f26 100644 --- a/pkg/coredata/common_third_party_domain.go +++ b/pkg/coredata/common_third_party_domain.go @@ -172,15 +172,11 @@ func (d CommonThirdPartyDomain) Delete( args := pgx.StrictNamedArgs{"id": d.ID} - result, err := conn.Exec(ctx, q, args) + _, err := conn.Exec(ctx, q, args) if err != nil { return fmt.Errorf("cannot delete common third party domain: %w", err) } - if result.RowsAffected() == 0 { - return ErrResourceNotFound - } - return nil } diff --git a/pkg/coredata/common_tracker_pattern.go b/pkg/coredata/common_tracker_pattern.go index ca9e82bdd..27dcaa16c 100644 --- a/pkg/coredata/common_tracker_pattern.go +++ b/pkg/coredata/common_tracker_pattern.go @@ -274,15 +274,11 @@ func (p CommonTrackerPattern) Delete( args := pgx.StrictNamedArgs{"id": id} - result, err := conn.Exec(ctx, q, args) + _, err := conn.Exec(ctx, q, args) if err != nil { return fmt.Errorf("cannot delete common tracker pattern: %w", err) } - if result.RowsAffected() == 0 { - return ErrResourceNotFound - } - return nil }