Skip to content

Commit

Permalink
add support for multiple pragma statements and driver syntax (#3031)
Browse files Browse the repository at this point in the history
* add support for multiple pragma statements and driver syntax

* Update common/persistence/sql/sqlplugin/sqlite/driver.go

Co-authored-by: Alex Shtin <alex@shtin.com>

* Update common/persistence/sql/sqlplugin/sqlite/plugin.go

Co-authored-by: Alex Shtin <alex@shtin.com>

Co-authored-by: Alex Shtin <alex@shtin.com>
  • Loading branch information
jbreiding and alexshtin committed Jun 30, 2022
1 parent 79844fd commit 0f13b23
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 120 deletions.
19 changes: 16 additions & 3 deletions common/persistence/sql/sqlplugin/sqlite/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,34 @@ package sqlite

import (
"errors"
"regexp"

"modernc.org/sqlite"
sqlite3 "modernc.org/sqlite/lib"
)

const (
goSqlDriverName = "sqlite"
sqlConstraintCodes = sqlite3.SQLITE_CONSTRAINT | sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY | sqlite3.SQLITE_CONSTRAINT_UNIQUE
goSqlDriverName = "sqlite"
sqlConstraintCodes = sqlite3.SQLITE_CONSTRAINT | sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY | sqlite3.SQLITE_CONSTRAINT_UNIQUE
sqlTableExistsPattern = "SQL logic error: table .* already exists \\(1\\)"
)

func (mdb *db) IsDupEntryError(err error) bool {
var sqlTableExistsRegex = regexp.MustCompile(sqlTableExistsPattern)

func (*db) IsDupEntryError(err error) bool {
var sqlErr *sqlite.Error
if errors.As(err, &sqlErr) {
return sqlErr.Code()&sqlConstraintCodes != 0
}

return false
}

func isTableExistsError(err error) bool {
var sqlErr *sqlite.Error
if errors.As(err, &sqlErr) {
return sqlTableExistsRegex.MatchString(sqlErr.Error())
}

return false
}
35 changes: 30 additions & 5 deletions common/persistence/sql/sqlplugin/sqlite/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ const (
PluginName = "sqlite"
)

// List of non-pragma parameters
// Taken from https://www.sqlite.org/uri.html
var queryParameters = map[string]struct{}{
"cache": {},
"immutable": {},
"mode": {},
"modeof": {},
"nolock": {},
"psow": {},
"setup": {},
"vfs": {},
}

type plugin struct {
connPool *connPool
}
Expand Down Expand Up @@ -123,14 +136,19 @@ func (p *plugin) createDBConnection(
// Maps struct names in CamelCase to snake without need for db struct tags.
db.MapperFunc(strcase.ToSnake)

// only suitable for in memory databases!
if cfg.ConnectAttributes["mode"] == "memory" {
switch {
case cfg.ConnectAttributes["mode"] == "memory":
// creates temporary DB overlay in order to configure database and schemas
err := p.setupSQLiteDatabase(cfg, db)
if err != nil {
if err := p.setupSQLiteDatabase(cfg, db); err != nil {
_ = db.Close()
return nil, err
}
case cfg.ConnectAttributes["setup"] == "true": // file mode, optional setting to setup the schema
if err := p.setupSQLiteDatabase(cfg, db); err != nil && !isTableExistsError(err) { // benign error indicating tables already exist
_ = db.Close()
return nil, err
}

}

return db, nil
Expand Down Expand Up @@ -177,7 +195,14 @@ func buildDSNAttr(cfg *config.SQL) (url.Values, error) {
key, value,
)
}
parameters.Set(key, value)

if _, isValidQueryParameter := queryParameters[key]; isValidQueryParameter {
parameters.Set(key, value)
continue
}

// assume pragma
parameters.Add("_pragma", fmt.Sprintf("%s=%s", key, value))
}
return parameters, nil
}
Loading

0 comments on commit 0f13b23

Please sign in to comment.