Skip to content

Commit 7fc7fb0

Browse files
Merge pull request #9 from ibuildthecloud/master
Detect "unique constraint" errors and return ErrKeyExists
2 parents bdc0bed + 48b4c8c commit 7fc7fb0

File tree

6 files changed

+40
-12
lines changed

6 files changed

+40
-12
lines changed

pkg/drivers/dqlite/dqlite.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ func New(ctx context.Context, datasourceName string) (server.Backend, error) {
9191
if err != nil {
9292
return nil, err
9393
}
94-
9594
if err := migrate(ctx, generic.DB); err != nil {
9695
return nil, errors.Wrap(err, "failed to migrate DB from sqlite")
9796
}
@@ -103,6 +102,12 @@ func New(ctx context.Context, datasourceName string) (server.Backend, error) {
103102
}
104103
return false
105104
}
105+
generic.TranslateErr = func(err error) error {
106+
if strings.Contains(err.Error(), "UNIQUE constraint") {
107+
return server.ErrKeyExists
108+
}
109+
return err
110+
}
106111

107112
return backend, nil
108113
}

pkg/drivers/generic/generic.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"github.com/Rican7/retry/backoff"
1414
"github.com/Rican7/retry/strategy"
15-
1615
"github.com/sirupsen/logrus"
1716
)
1817

@@ -63,6 +62,7 @@ func (s Stripped) String() string {
6362
}
6463

6564
type ErrRetry func(error) bool
65+
type TranslateErr func(error) error
6666

6767
type Generic struct {
6868
sync.Mutex
@@ -83,6 +83,7 @@ type Generic struct {
8383
FillSQL string
8484
InsertLastInsertIDSQL string
8585
Retry ErrRetry
86+
TranslateErr TranslateErr
8687
}
8788

8889
func q(sql, param string, numbered bool) string {
@@ -308,6 +309,14 @@ func (d *Generic) IsFill(key string) bool {
308309
}
309310

310311
func (d *Generic) Insert(ctx context.Context, key string, create, delete bool, createRevision, previousRevision int64, ttl int64, value, prevValue []byte) (id int64, err error) {
312+
if d.TranslateErr != nil {
313+
defer func() {
314+
if err != nil {
315+
err = d.TranslateErr(err)
316+
}
317+
}()
318+
}
319+
311320
cVal := 0
312321
dVal := 0
313322
if create {
@@ -320,7 +329,7 @@ func (d *Generic) Insert(ctx context.Context, key string, create, delete bool, c
320329
if d.LastInsertID {
321330
row, err := d.execute(ctx, d.InsertLastInsertIDSQL, key, cVal, dVal, createRevision, previousRevision, ttl, value, prevValue)
322331
if err != nil {
323-
return 00, err
332+
return 0, err
324333
}
325334
return row.LastInsertId()
326335
}

pkg/drivers/mysql/mysql.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var (
2323
`create table if not exists kine
2424
(
2525
id INTEGER AUTO_INCREMENT,
26-
name TEXT,
26+
name VARCHAR(630),
2727
created INTEGER,
2828
deleted INTEGER,
2929
create_revision INTEGER,
@@ -34,8 +34,8 @@ var (
3434
PRIMARY KEY (id)
3535
);`,
3636
}
37-
nameIdx = "create index kine_name_index on kine (name(100))"
38-
revisionIdx = "create unique index kine_name_prev_revision_uindex on kine (name(100), prev_revision)"
37+
nameIdx = "create index kine_name_index on kine (name)"
38+
revisionIdx = "create unique index kine_name_prev_revision_uindex on kine (name, prev_revision)"
3939
createDB = "create database if not exists "
4040
)
4141

@@ -63,6 +63,12 @@ func New(dataSourceName string, tlsInfo tls.Config) (server.Backend, error) {
6363
return nil, err
6464
}
6565
dialect.LastInsertID = true
66+
dialect.TranslateErr = func(err error) error {
67+
if err, ok := err.(*mysql.MySQLError); ok && err.Number == 1062 {
68+
return server.ErrKeyExists
69+
}
70+
return err
71+
}
6672
if err := setup(dialect.DB); err != nil {
6773
return nil, err
6874
}

pkg/drivers/pgsql/pgsql.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var (
2525
`create table if not exists kine
2626
(
2727
id SERIAL PRIMARY KEY,
28-
name TEXT,
28+
name VARCHAR(630),
2929
created INTEGER,
3030
deleted INTEGER,
3131
create_revision INTEGER,
@@ -54,6 +54,12 @@ func New(dataSourceName string, tlsInfo tls.Config) (server.Backend, error) {
5454
if err != nil {
5555
return nil, err
5656
}
57+
dialect.TranslateErr = func(err error) error {
58+
if err, ok := err.(*pq.Error); ok && err.Code == "23505" {
59+
return server.ErrKeyExists
60+
}
61+
return err
62+
}
5763

5864
if err := setup(dialect.DB); err != nil {
5965
return nil, err

pkg/drivers/sqlite/sqlite.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"database/sql"
66
"os"
77

8+
"github.com/mattn/go-sqlite3"
89
"github.com/rancher/kine/pkg/drivers/generic"
910
"github.com/rancher/kine/pkg/logstructured"
1011
"github.com/rancher/kine/pkg/logstructured/sqllog"
@@ -51,6 +52,12 @@ func NewVariant(driverName, dataSourceName string) (server.Backend, *generic.Gen
5152
return nil, nil, err
5253
}
5354
dialect.LastInsertID = true
55+
dialect.TranslateErr = func(err error) error {
56+
if err, ok := err.(sqlite3.Error); ok && err.ExtendedCode == sqlite3.ErrConstraintUnique {
57+
return server.ErrKeyExists
58+
}
59+
return err
60+
}
5461

5562
if err := setup(dialect.DB); err != nil {
5663
return nil, nil, err

pkg/logstructured/logstructured.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,6 @@ func (l *LogStructured) Create(ctx context.Context, key string, value []byte, le
108108
}
109109

110110
revRet, errRet = l.log.Append(ctx, createEvent)
111-
if errRet != nil {
112-
if _, prevEvent, err := l.get(ctx, key, 0, true); err == nil && prevEvent != nil && !prevEvent.Delete {
113-
return 0, server.ErrKeyExists
114-
}
115-
}
116111
return
117112
}
118113

0 commit comments

Comments
 (0)