From a81452b437323e1cdd7bae107601f8012389c923 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 29 May 2023 15:55:35 +0100 Subject: [PATCH] [v10.0.x] SQLStore: Align SQLite IsUniqueConstraintViolation() with other backend implementations (#69227) SQLStore: Align SQLite IsUniqueConstraintViolation() with other backend implementations (#69224) * Add integration test for primary key and unique constrain violation * Align SQLite IsUniqueConstraintViolation implementation with other backends (cherry picked from commit 74e87ccbbd7d7ce498fc6f94a4a806eb99b5e5dd) Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> --- .../sqlstore/migrator/sqlite_dialect.go | 2 +- pkg/services/sqlstore/sqlstore_test.go | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pkg/services/sqlstore/migrator/sqlite_dialect.go b/pkg/services/sqlstore/migrator/sqlite_dialect.go index 9b57d26ad0a..20002be9718 100644 --- a/pkg/services/sqlstore/migrator/sqlite_dialect.go +++ b/pkg/services/sqlstore/migrator/sqlite_dialect.go @@ -148,7 +148,7 @@ func (db *SQLite3) ErrorMessage(err error) string { } func (db *SQLite3) IsUniqueConstraintViolation(err error) bool { - return db.isThisError(err, int(sqlite3.ErrConstraintUnique)) + return db.isThisError(err, int(sqlite3.ErrConstraintUnique)) || db.isThisError(err, int(sqlite3.ErrConstraintPrimaryKey)) } func (db *SQLite3) IsDeadlock(err error) bool { diff --git a/pkg/services/sqlstore/sqlstore_test.go b/pkg/services/sqlstore/sqlstore_test.go index b85c7dd77b0..b643216ea0a 100644 --- a/pkg/services/sqlstore/sqlstore_test.go +++ b/pkg/services/sqlstore/sqlstore_test.go @@ -1,12 +1,16 @@ package sqlstore import ( + "context" "errors" "net/url" "testing" + "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/setting" ) @@ -99,6 +103,54 @@ func TestIntegrationSQLConnectionString(t *testing.T) { } } +func TestIntegrationIsUniqueConstraintViolation(t *testing.T) { + store := InitTestDB(t) + + testCases := []struct { + desc string + f func(*testing.T, *DBSession) error + }{ + { + desc: "successfully detect primary key violations", + f: func(t *testing.T, sess *DBSession) error { + // Attempt to insert org with provided ID (primary key) twice + now := time.Now() + org := org.Org{Name: "test org primary key violation", Created: now, Updated: now, ID: 42} + err := sess.InsertId(&org, store.Dialect) + require.NoError(t, err) + + // Provide a different name to avoid unique constraint violation + org.Name = "test org 2" + return sess.InsertId(&org, store.Dialect) + }, + }, + { + desc: "successfully detect unique constrain violations", + f: func(t *testing.T, sess *DBSession) error { + // Attempt to insert org with reserved name + now := time.Now() + org := org.Org{Name: "test org unique constrain violation", Created: now, Updated: now, ID: 43} + err := sess.InsertId(&org, store.Dialect) + require.NoError(t, err) + + // Provide a different ID to avoid primary key violation + org.ID = 44 + return sess.InsertId(&org, store.Dialect) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + err := store.WithDbSession(context.Background(), func(sess *DBSession) error { + return tc.f(t, sess) + }) + require.Error(t, err) + assert.True(t, store.Dialect.IsUniqueConstraintViolation(err)) + }) + } +} + func makeSQLStoreTestConfig(t *testing.T, dbType, host, dbURL string) *setting.Cfg { t.Helper()