From 3654383ad2b83bd70e6d34d1f8e7fe1a178a46f9 Mon Sep 17 00:00:00 2001 From: Dmitry Fedotov Date: Sat, 30 Aug 2025 10:30:53 +0300 Subject: [PATCH] v1 --- README.md | 4 +--- init_db.go | 4 ++-- repo.go | 26 ++++++-------------------- test/Makefile | 1 + test/go.mod | 2 +- test/go.sum | 4 ++-- test/go.work | 6 ++++++ test/go.work.sum | 15 +++++++++++++++ test/repo_test.go | 12 ------------ 9 files changed, 34 insertions(+), 40 deletions(-) create mode 100644 test/go.work create mode 100644 test/go.work.sum diff --git a/README.md b/README.md index 2060134..88bf360 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,8 @@ type Repo[T any] interface { Read(ctx context.Context, id string) (*T, error) // Update updates object with id. Update(ctx context.Context, id string, v *T) error - // Delete performs soft-delete (actually marks object as unavailable). + // Delete deletes object with id. Delete(ctx context.Context, id string) error - // Purge actually deletes database record with id. - Purge(ctx context.Context, id string) error } ``` diff --git a/init_db.go b/init_db.go index f808fa5..ab7af78 100644 --- a/init_db.go +++ b/init_db.go @@ -13,9 +13,9 @@ CREATE TABLE IF NOT EXISTS -- ( id text PRIMARY KEY, created_at timestamp with time zone, updated_at timestamp with time zone, - deleted_at timestamp with time zone, payload jsonb -)` +) +` func initDB(ctx context.Context, db *sql.DB, tablename string) error { if tablename == "" { diff --git a/repo.go b/repo.go index e2ec89a..c4461df 100644 --- a/repo.go +++ b/repo.go @@ -16,17 +16,15 @@ var ( ) type Repo[T any] interface { - // Create inserts object into repository table. If id already exists + // Create saves object to the repository. If id already exists // in the database it is an error. Create(ctx context.Context, id string, v *T) error // Read returns object with specified id or ErrNotFound Read(ctx context.Context, id string) (*T, error) // Update updates object with id. Update(ctx context.Context, id string, v *T) error - // Delete performs soft-delete (actually marks object as unavailable). + // Delete deletes object from the database. Delete(ctx context.Context, id string) error - // Purge actually deletes database record with id. - Purge(ctx context.Context, id string) error } // OpenOrCreate accepts *sql.DB and tablename and tries to create the named table @@ -65,7 +63,7 @@ func (r *repo[T]) Create(ctx context.Context, id string, v *T) error { } func (r *repo[T]) Read(ctx context.Context, id string) (*T, error) { - query := "SELECT payload FROM " + r.table + " WHERE id = $1 AND deleted_at is NULL" + query := "SELECT payload FROM " + r.table + " WHERE id = $1" row := r.db.QueryRowContext(ctx, query, id) @@ -94,7 +92,7 @@ func (r *repo[T]) Update(ctx context.Context, id string, v *T) error { return err } - query := "UPDATE " + r.table + " SET updated_at = $1, payload = $2 WHERE id = $3 AND deleted_at IS NULL" + query := "UPDATE " + r.table + " SET updated_at = $1, payload = $2 WHERE id = $3" if err := r.execContext(ctx, query, now, string(b), id); err != nil { return err @@ -103,21 +101,8 @@ func (r *repo[T]) Update(ctx context.Context, id string, v *T) error { return nil } -// Delete performs soft-delete. It just marks the record as deleted and it will -// no longer be available to Read and Update methods. +// Delete deletes record with cpecified id. func (r *repo[T]) Delete(ctx context.Context, id string) error { - now := time.Now() - - query := "UPDATE " + r.table + " SET deleted_at = $1 WHERE id = $2 AND deleted_at IS NULL" - - if err := r.execContext(ctx, query, now, id); err != nil { - return err - } - - return nil -} - -func (r *repo[T]) Purge(ctx context.Context, id string) error { query := "DELETE FROM " + r.table + " WHERE id = $1" if err := r.execContext(ctx, query, id); err != nil { @@ -132,6 +117,7 @@ func (r *repo[T]) execContext(ctx context.Context, query string, args ...any) er if err != nil { return errors.Join(ErrExecQuery, err) } + affected, err := res.RowsAffected() if err != nil { return errors.Join(ErrExecQuery, err) diff --git a/test/Makefile b/test/Makefile index fb5947d..15769ce 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,7 @@ test: docker run --rm -d -e POSTGRES_PASSWORD=postgres --name test-postgres -p 5432:5432 postgres:15.6-bookworm + # wait for postgres to launch sleep 10 PGX_DSN=postgres://postgres:postgres@127.0.0.1:5432 go test -v -cover docker stop test-postgres diff --git a/test/go.mod b/test/go.mod index 567be6f..175362b 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,7 +3,7 @@ module pkgtest go 1.24.2 require ( - code.uint32.ru/tiny/repo v0.0.0-20250504181319-b6dc6d3fce1a + code.uint32.ru/tiny/repo v1.0.0 github.com/jackc/pgx/v5 v5.7.4 github.com/mattn/go-sqlite3 v1.14.28 ) diff --git a/test/go.sum b/test/go.sum index 7b225dd..7324af3 100644 --- a/test/go.sum +++ b/test/go.sum @@ -1,5 +1,5 @@ -code.uint32.ru/tiny/repo v0.0.0-20250504181319-b6dc6d3fce1a h1:xlO71KbJ4fl3F05JN/I8rY3MjVF0CV3B1awa4TB6GN0= -code.uint32.ru/tiny/repo v0.0.0-20250504181319-b6dc6d3fce1a/go.mod h1:yk97QS1fB9mdT/5iRN4ufo6IwZRDYHFl1kDtBSTpuk0= +code.uint32.ru/tiny/repo v1.0.0 h1:hWLL+atKth6XwKawQcnaBkQyuiGlS7+r4pqNhvUl4XE= +code.uint32.ru/tiny/repo v1.0.0/go.mod h1:yk97QS1fB9mdT/5iRN4ufo6IwZRDYHFl1kDtBSTpuk0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/test/go.work b/test/go.work new file mode 100644 index 0000000..3b8f75f --- /dev/null +++ b/test/go.work @@ -0,0 +1,6 @@ +go 1.24.5 + +use ( + . + .. +) diff --git a/test/go.work.sum b/test/go.work.sum new file mode 100644 index 0000000..8ee5424 --- /dev/null +++ b/test/go.work.sum @@ -0,0 +1,15 @@ +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/test/repo_test.go b/test/repo_test.go index 3b40644..296e26b 100644 --- a/test/repo_test.go +++ b/test/repo_test.go @@ -127,15 +127,6 @@ func dotest(ctx context.Context, db *sql.DB, t *testing.T) { t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } - if err := r.Purge(ctx, testID); err != nil { - t.Error(err) - } - - if err := r.Purge(ctx, testID); err == nil || !errors.Is(err, repo.ErrNotFound) { - // can only purge once - t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) - } - if _, err := r.Read(ctx, incorrectID); err == nil || !errors.Is(err, repo.ErrNotFound) { t.Errorf("incorrect error on read for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } @@ -148,7 +139,4 @@ func dotest(ctx context.Context, db *sql.DB, t *testing.T) { t.Errorf("incorrect error on delete for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) } - if err := r.Purge(ctx, incorrectID); err == nil || !errors.Is(err, repo.ErrNotFound) { - t.Errorf("incorrect error on purge for non-existing id, want: %v, have: %v", repo.ErrNotFound, err) - } }