diff --git a/cmd/dendrite-demo-pinecone/main.go b/cmd/dendrite-demo-pinecone/main.go index ab5414823..6c719a1ee 100644 --- a/cmd/dendrite-demo-pinecone/main.go +++ b/cmd/dendrite-demo-pinecone/main.go @@ -54,8 +54,6 @@ import ( pineconeSessions "github.com/matrix-org/pinecone/sessions" "github.com/sirupsen/logrus" - - _ "modernc.org/sqlite" ) var ( diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go index d2f50906e..1226496c3 100644 --- a/cmd/dendrite-demo-yggdrasil/main.go +++ b/cmd/dendrite-demo-yggdrasil/main.go @@ -48,8 +48,6 @@ import ( "github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/userapi" "github.com/sirupsen/logrus" - - _ "modernc.org/sqlite" ) var ( diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go index 15830843a..ff980dc1c 100644 --- a/cmd/dendrite-monolith-server/main.go +++ b/cmd/dendrite-monolith-server/main.go @@ -30,8 +30,6 @@ import ( "github.com/matrix-org/dendrite/userapi" uapi "github.com/matrix-org/dendrite/userapi/api" "github.com/sirupsen/logrus" - - _ "modernc.org/sqlite" ) var ( diff --git a/cmd/dendrite-polylith-multi/main.go b/cmd/dendrite-polylith-multi/main.go index a6f809c9e..c6a560b19 100644 --- a/cmd/dendrite-polylith-multi/main.go +++ b/cmd/dendrite-polylith-multi/main.go @@ -24,8 +24,6 @@ import ( "github.com/matrix-org/dendrite/setup/base" "github.com/matrix-org/dendrite/setup/config" "github.com/sirupsen/logrus" - - _ "modernc.org/sqlite" ) type entrypoint func(base *base.BaseDendrite, cfg *config.Dendrite) diff --git a/go.mod b/go.mod index 2383d5ee9..cf56aafaa 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/matrix-org/gomatrixserverlib v0.0.0-20221101165746-0e4a8bb6db7e github.com/matrix-org/pinecone v0.0.0-20221026160848-639feeff74d6 github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 + github.com/mattn/go-sqlite3 v1.14.15 github.com/nats-io/nats-server/v2 v2.9.4 github.com/nats-io/nats.go v1.19.0 github.com/neilalexander/utp v0.1.1-0.20210727203401-54ae7b1cd5f9 diff --git a/go.sum b/go.sum index 5a493a2ce..36dcfdf5e 100644 --- a/go.sum +++ b/go.sum @@ -397,6 +397,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattomatic/dijkstra v0.0.0-20130617153013-6f6d134eb237/go.mod h1:UOnLAUmVG5paym8pD3C4B9BQylUDC2vXFJJpT7JrlEA= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= diff --git a/internal/sqlutil/migrate_test.go b/internal/sqlutil/migrate_test.go index aa952f624..2d4fe4c67 100644 --- a/internal/sqlutil/migrate_test.go +++ b/internal/sqlutil/migrate_test.go @@ -88,7 +88,7 @@ func Test_migrations_Up(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - driverName := "sqlite" + driverName := sqlutil.SQLITE_DRIVER_NAME if dbType == test.DBTypePostgres { driverName = "postgres" } @@ -117,7 +117,7 @@ func Test_insertMigration(t *testing.T) { test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) { conStr, close := test.PrepareDBConnectionString(t, dbType) defer close() - driverName := "sqlite" + driverName := sqlutil.SQLITE_DRIVER_NAME if dbType == test.DBTypePostgres { driverName = "postgres" } diff --git a/internal/sqlutil/sqlite_cgo.go b/internal/sqlutil/sqlite_cgo.go new file mode 100644 index 000000000..efb743fc7 --- /dev/null +++ b/internal/sqlutil/sqlite_cgo.go @@ -0,0 +1,19 @@ +//go:build cgo +// +build cgo + +package sqlutil + +import ( + "github.com/mattn/go-sqlite3" + _ "github.com/mattn/go-sqlite3" +) + +const SQLITE_DRIVER_NAME = "sqlite3" + +func sqliteDSNExtension(dsn string) string { + return dsn +} + +func sqliteDriver() *sqlite3.SQLiteDriver { + return &sqlite3.SQLiteDriver{} +} diff --git a/internal/sqlutil/sqlite_native.go b/internal/sqlutil/sqlite_native.go new file mode 100644 index 000000000..ed500afc6 --- /dev/null +++ b/internal/sqlutil/sqlite_native.go @@ -0,0 +1,29 @@ +//go:build !cgo +// +build !cgo + +package sqlutil + +import ( + "modernc.org/sqlite" + "strings" +) + +const SQLITE_DRIVER_NAME = "sqlite" + +func sqliteDSNExtension(dsn string) string { + // add query parameters to the dsn + if strings.Contains(dsn, "?") { + dsn += "&" + } else { + dsn += "?" + } + + // wait some time before erroring if the db is locked + // https://gitlab.com/cznic/sqlite/-/issues/106#note_1058094993 + dsn += "_pragma=busy_timeout%3d10000" + return dsn +} + +func sqliteDriver() *sqlite.Driver { + return &sqlite.Driver{} +} diff --git a/internal/sqlutil/sqlutil.go b/internal/sqlutil/sqlutil.go index b0c339294..39a067e52 100644 --- a/internal/sqlutil/sqlutil.go +++ b/internal/sqlutil/sqlutil.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "regexp" - "strings" "github.com/matrix-org/dendrite/setup/config" "github.com/sirupsen/logrus" @@ -21,22 +20,12 @@ func Open(dbProperties *config.DatabaseOptions, writer Writer) (*sql.DB, error) var driverName, dsn string switch { case dbProperties.ConnectionString.IsSQLite(): - driverName = "sqlite" + driverName = SQLITE_DRIVER_NAME dsn, err = ParseFileURI(dbProperties.ConnectionString) if err != nil { return nil, fmt.Errorf("ParseFileURI: %w", err) } - - // add query parameters to the dsn - if strings.Contains(dsn, "?") { - dsn += "&" - } else { - dsn += "?" - } - - // wait some time before erroring if the db is locked - // https://gitlab.com/cznic/sqlite/-/issues/106#note_1058094993 - dsn += "_pragma=busy_timeout%3d10000" + dsn = sqliteDSNExtension(dsn) case dbProperties.ConnectionString.IsPostgres(): driverName = "postgres" dsn = string(dbProperties.ConnectionString) @@ -51,7 +40,7 @@ func Open(dbProperties *config.DatabaseOptions, writer Writer) (*sql.DB, error) if err != nil { return nil, err } - if driverName != "sqlite" { + if driverName != SQLITE_DRIVER_NAME { logger := logrus.WithFields(logrus.Fields{ "max_open_conns": dbProperties.MaxOpenConns(), "max_idle_conns": dbProperties.MaxIdleConns(), diff --git a/internal/sqlutil/trace_driver.go b/internal/sqlutil/trace_driver.go index ae64bced3..a2e0d12e2 100644 --- a/internal/sqlutil/trace_driver.go +++ b/internal/sqlutil/trace_driver.go @@ -22,7 +22,6 @@ import ( "github.com/lib/pq" "github.com/ngrok/sqlmw" - sqlite "modernc.org/sqlite" ) func registerDrivers() { @@ -31,6 +30,6 @@ func registerDrivers() { } // install the wrapped drivers sql.Register("postgres-trace", sqlmw.Driver(&pq.Driver{}, new(traceInterceptor))) - sql.Register("sqlite3-trace", sqlmw.Driver(&sqlite.Driver{}, new(traceInterceptor))) + sql.Register("sqlite3-trace", sqlmw.Driver(sqliteDriver(), new(traceInterceptor))) } diff --git a/internal/sqlutil/unique_constraint.go b/internal/sqlutil/unique_constraint.go index f821f73bc..767a586ec 100644 --- a/internal/sqlutil/unique_constraint.go +++ b/internal/sqlutil/unique_constraint.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !wasm -// +build !wasm +//go:build !wasm && !cgo +// +build !wasm,!cgo package sqlutil diff --git a/internal/sqlutil/unique_constraint_cgo.go b/internal/sqlutil/unique_constraint_cgo.go new file mode 100644 index 000000000..edeb7c450 --- /dev/null +++ b/internal/sqlutil/unique_constraint_cgo.go @@ -0,0 +1,36 @@ +// Copyright 2020 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !wasm && cgo +// +build !wasm,cgo + +package sqlutil + +import ( + "github.com/lib/pq" + "github.com/mattn/go-sqlite3" +) + +// IsUniqueConstraintViolationErr returns true if the error is an unique_violation error +func IsUniqueConstraintViolationErr(err error) bool { + switch e := err.(type) { + case *pq.Error: + return e.Code == "23505" + case *sqlite3.Error: + return e.Code == sqlite3.ErrConstraint + case sqlite3.Error: + return e.Code == sqlite3.ErrConstraint + } + return false +}