Skip to content

Commit 60d2758

Browse files
authored
refactor: remove the custom ErrDBUniqueConstraint error (#197)
Remove common.ErrDBUniqueConstraint, which was used as a workaround for the lack of abstraction in gorm. With the update in go-gorm/gorm#6004 we can now fully use gorm for db related errors (fe. gorm.ErrDuplicatedKey).
1 parent fa37c16 commit 60d2758

File tree

8 files changed

+58
-136
lines changed

8 files changed

+58
-136
lines changed

go.mod

+19-24
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ require (
99
github.com/go-testfixtures/testfixtures/v3 v3.8.0
1010
github.com/gofiber/contrib/paseto v0.0.0-20220621082844-83549332c36e
1111
github.com/gofiber/fiber/v2 v2.46.0
12-
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
13-
github.com/stretchr/testify v1.7.5
14-
gorm.io/driver/postgres v1.3.7
15-
gorm.io/driver/sqlite v1.4.3
16-
gorm.io/gorm v1.24.1
12+
github.com/stretchr/testify v1.8.1
13+
gorm.io/driver/postgres v1.5.2
14+
gorm.io/driver/sqlite v1.5.2
15+
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55
1716
)
1817

1918
require (
@@ -26,21 +25,14 @@ require (
2625
github.com/cespare/xxhash/v2 v2.1.2 // indirect
2726
github.com/gofiber/adaptor/v2 v2.1.25 // indirect
2827
github.com/golang/protobuf v1.5.2 // indirect
29-
github.com/mattn/go-colorable v0.1.13 // indirect
30-
github.com/mattn/go-isatty v0.0.18 // indirect
31-
github.com/mattn/go-runewidth v0.0.14 // indirect
32-
github.com/mattn/go-sqlite3 v1.14.16 // indirect
28+
github.com/jackc/pgx/v5 v5.3.1 // indirect
29+
github.com/mattn/go-sqlite3 v1.14.17 // indirect
3330
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
34-
github.com/philhofer/fwd v1.1.2 // indirect
3531
github.com/prometheus/client_golang v1.12.2 // indirect
3632
github.com/prometheus/client_model v0.2.0 // indirect
3733
github.com/prometheus/common v0.32.1 // indirect
3834
github.com/prometheus/procfs v0.7.3 // indirect
39-
github.com/rivo/uniseg v0.2.0 // indirect
40-
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
41-
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
42-
github.com/tinylib/msgp v1.1.8 // indirect
43-
golang.org/x/net v0.8.0 // indirect
35+
golang.org/x/net v0.9.0 // indirect
4436
google.golang.org/protobuf v1.26.0 // indirect
4537
)
4638

@@ -59,25 +51,28 @@ require (
5951
github.com/davecgh/go-spew v1.1.1 // indirect
6052
github.com/go-playground/locales v0.14.0 // indirect
6153
github.com/go-playground/universal-translator v0.18.0 // indirect
62-
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
63-
github.com/jackc/pgconn v1.12.1
64-
github.com/jackc/pgio v1.0.0 // indirect
6554
github.com/jackc/pgpassfile v1.0.0 // indirect
66-
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
67-
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
68-
github.com/jackc/pgtype v1.11.0 // indirect
69-
github.com/jackc/pgx/v4 v4.16.1 // indirect
55+
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
7056
github.com/jinzhu/inflection v1.0.0 // indirect
7157
github.com/jinzhu/now v1.1.5 // indirect
7258
github.com/klauspost/compress v1.16.3 // indirect
7359
github.com/leodido/go-urn v1.2.1 // indirect
60+
github.com/lib/pq v1.10.9 // indirect
61+
github.com/mattn/go-colorable v0.1.13 // indirect
62+
github.com/mattn/go-isatty v0.0.18 // indirect
63+
github.com/mattn/go-runewidth v0.0.14 // indirect
64+
github.com/philhofer/fwd v1.1.2 // indirect
7465
github.com/pkg/errors v0.9.1 // indirect
7566
github.com/pmezard/go-difflib v1.0.0 // indirect
67+
github.com/rivo/uniseg v0.2.0 // indirect
68+
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
69+
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
70+
github.com/tinylib/msgp v1.1.8 // indirect
7671
github.com/valyala/bytebufferpool v1.0.0 // indirect
7772
github.com/valyala/fasthttp v1.47.0 // indirect
7873
github.com/valyala/tcplisten v1.0.0 // indirect
79-
golang.org/x/crypto v0.7.0 // indirect
74+
golang.org/x/crypto v0.8.0 // indirect
8075
golang.org/x/sys v0.8.0 // indirect
81-
golang.org/x/text v0.8.0 // indirect
76+
golang.org/x/text v0.9.0 // indirect
8277
gopkg.in/yaml.v3 v3.0.1 // indirect
8378
)

go.sum

+26-68
Large diffs are not rendered by default.

internal/common/errors.go

-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ var (
1010
ErrAuthentication = errors.New("token authentication failed")
1111
ErrInvalidDateTime = errors.New("invalid date time format (RFC 3339 needed)")
1212
ErrKeyLen = errors.New("PASETO_KEY must be 32 bytes long once base64-decoded")
13-
14-
ErrDBUniqueConstraint = errors.New("db constraint violation")
15-
ErrDBRecordNotFound = errors.New("record not found")
1613
)
1714

1815
func Error(status int, title string, detail string) ProblemJSONError {

internal/database/database.go

-28
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
package database
22

33
import (
4-
"errors"
54
"log"
6-
"strings"
7-
8-
"github.com/jackc/pgconn"
95

106
"github.com/italia/developers-italia-api/internal/common"
11-
"github.com/jackc/pgerrcode"
127
"gorm.io/gorm"
138
)
149

15-
const (
16-
uniqueConstraintFailedErrorSQLite = "UNIQUE constraint failed"
17-
)
18-
1910
type Database interface {
2011
Init(dsn string) (*gorm.DB, error)
2112
}
@@ -36,22 +27,3 @@ func NewDatabase(env common.Environment) Database {
3627
dsn: env.Database,
3728
}
3829
}
39-
40-
//nolint:errorlint
41-
func WrapErrors(dbError error) error {
42-
if strings.Contains(dbError.Error(), uniqueConstraintFailedErrorSQLite) {
43-
return common.ErrDBUniqueConstraint
44-
}
45-
46-
if e, ok := dbError.(*pgconn.PgError); ok {
47-
if e.Code == pgerrcode.UniqueViolation {
48-
return common.ErrDBUniqueConstraint
49-
}
50-
}
51-
52-
if errors.Is(dbError, gorm.ErrRecordNotFound) {
53-
return common.ErrDBRecordNotFound
54-
}
55-
56-
return dbError
57-
}

internal/database/postgres_database.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ func (d *PostgresDB) Init(dsn string) (*gorm.DB, error) {
1717
var err error
1818

1919
database, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
20-
PrepareStmt: true,
20+
TranslateError: true,
21+
PrepareStmt: true,
2122
// Disable logging in production
2223
Logger: logger.Default.LogMode(logger.Silent),
2324
})

internal/database/sqlite_database.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type SQLiteDB struct {
1515
func (d *SQLiteDB) Init(dsn string) (*gorm.DB, error) {
1616
var err error
1717

18-
database, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
18+
database, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{TranslateError: true})
1919
if err != nil {
2020
return nil, fmt.Errorf("can't open database: %w", err)
2121
}

internal/handlers/publishers.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"net/url"
77
"sort"
88

9-
"github.com/italia/developers-italia-api/internal/database"
109
"golang.org/x/exp/slices"
1110

1211
"github.com/italia/developers-italia-api/internal/handlers/general"
@@ -135,12 +134,12 @@ func (p *Publisher) PostPublisher(ctx *fiber.Ctx) error {
135134
}
136135

137136
if err := p.db.Create(&publisher).Error; err != nil {
138-
switch database.WrapErrors(err) { //nolint:errorlint
139-
case common.ErrDBRecordNotFound:
137+
switch {
138+
case errors.Is(err, gorm.ErrRecordNotFound):
140139
return common.Error(fiber.StatusNotFound,
141140
"can't create Publisher",
142141
"Publisher was not found")
143-
case common.ErrDBUniqueConstraint:
142+
case errors.Is(err, gorm.ErrDuplicatedKey):
144143
return common.Error(fiber.StatusConflict,
145144
"can't create Publisher",
146145
"description, alternativeId or codeHosting URL already exists")

internal/models/models_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func init() {
3737
// TODO: investigate the root cause
3838
sqlitedb.Exec("PRAGMA journal_mode=WAL;")
3939

40-
db, err = gorm.Open(sqlite.Open(dsn), &gorm.Config{})
40+
db, err = gorm.Open(sqlite.Open(dsn), &gorm.Config{TranslateError: true})
4141
if err != nil {
4242
log.Fatal(err)
4343
}
@@ -93,7 +93,7 @@ func TestSoftwareCreate(t *testing.T) {
9393
PubliccodeYml: "-",
9494
},
9595
).Error
96-
assert.EqualError(t, err, "UNIQUE constraint failed: software.software_url_id")
96+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
9797
}
9898

9999
func TestSoftwareURLCreate(t *testing.T) {
@@ -117,7 +117,7 @@ func TestSoftwareURLCreate(t *testing.T) {
117117
URL: "https://new-2.example.org",
118118
},
119119
).Error
120-
assert.EqualError(t, err, "UNIQUE constraint failed: software_urls.id")
120+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
121121
}
122122

123123
func TestPublisherCreate(t *testing.T) {
@@ -144,7 +144,7 @@ func TestPublisherCreate(t *testing.T) {
144144
Email: &email,
145145
},
146146
).Error
147-
assert.EqualError(t, err, "UNIQUE constraint failed: publishers.description")
147+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
148148

149149
// Duplicate alternativeId
150150
alternativeID := "alternative-id-12345"
@@ -155,7 +155,7 @@ func TestPublisherCreate(t *testing.T) {
155155
AlternativeID: &alternativeID,
156156
},
157157
).Error
158-
assert.EqualError(t, err, "UNIQUE constraint failed: publishers.alternative_id")
158+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
159159
}
160160

161161
func TestWebhookCreate(t *testing.T) {
@@ -181,7 +181,7 @@ func TestWebhookCreate(t *testing.T) {
181181
URL: "https://new-webhook-2.example.org",
182182
},
183183
).Error
184-
assert.EqualError(t, err, "UNIQUE constraint failed: webhooks.id")
184+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
185185
}
186186

187187
func TestEventCreate(t *testing.T) {
@@ -207,5 +207,5 @@ func TestEventCreate(t *testing.T) {
207207
EntityType: "software",
208208
},
209209
).Error
210-
assert.EqualError(t, err, "UNIQUE constraint failed: events.id")
210+
assert.ErrorIs(t, err, gorm.ErrDuplicatedKey)
211211
}

0 commit comments

Comments
 (0)