aboutsummaryrefslogtreecommitdiff
path: root/src/golite.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/golite.go')
-rw-r--r--src/golite.go219
1 files changed, 14 insertions, 205 deletions
diff --git a/src/golite.go b/src/golite.go
index be02de6..62bbeb5 100644
--- a/src/golite.go
+++ b/src/golite.go
@@ -1128,7 +1128,6 @@ type SQLiteConn struct {
mu sync.Mutex
db *C.sqlite3
loc *time.Location
- txlock string
funcs []*functionInfo
aggregators []*aggInfo
}
@@ -1623,7 +1622,7 @@ func (c *SQLiteConn) Begin() (driver.Tx, error) {
}
func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
- if _, err := c.exec(ctx, c.txlock, nil); err != nil {
+ if _, err := c.exec(ctx, "BEGIN", nil); err != nil {
return nil, err
}
return &SQLiteTx{c}, nil
@@ -1646,15 +1645,6 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
// :memory:
// file::memory:
//
-// mode
-// Access mode of the database.
-// https://www.sqlite.org/c3ref/open.html
-// Values:
-// - ro
-// - rw
-// - rwc
-// - memory
-//
// cache
// SQLite Shared-Cache Mode
// https://www.sqlite.org/sharedcache.html
@@ -1662,61 +1652,13 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
// - shared
// - private
//
-// immutable=Boolean
-// The immutable parameter is a boolean query parameter that indicates
-// that the database file is stored on read-only media. When immutable is set,
-// SQLite assumes that the database file cannot be changed,
-// even by a process with higher privilege,
-// and so the database is opened read-only and all locking and change detection is disabled.
-// Caution: Setting the immutable property on a database file that
-// does in fact change can result in incorrect query results and/or SQLITE_CORRUPT errors.
-//
// go-sqlite3 adds the following query parameters to those used by SQLite:
//
// _loc=XXX
// Specify location of time format. It's possible to specify "auto".
-//
-// _mutex=XXX
-// Specify mutex mode. XXX can be "no", "full".
-//
-// _txlock=XXX
-// Specify locking behavior for transactions. XXX can be "immediate",
-// "deferred", "exclusive".
-//
-// _busy_timeout=XXX"| _timeout=XXX
-// Specify value for sqlite3_busy_timeout.
-//
-// _defer_foreign_keys=Boolean | _defer_fk=Boolean
-// Defer Foreign Keys until outermost transaction is committed.
-//
-// _ignore_check_constraints=Boolean
-// This pragma enables or disables the enforcement of CHECK constraints.
-// The default setting is off, meaning that CHECK constraints are enforced by default.
-//
-// _recursive_triggers=Boolean | _rt=Boolean
-// Enable or disable recursive triggers.
-//
-// _writable_schema=Boolean
-// When this pragma is on, the SQLITE_MASTER tables in which database
-// can be changed using ordinary UPDATE, INSERT, and DELETE statements.
-// Warning: misuse of this pragma can easily result in a corrupt database file.
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
- if C.sqlite3_threadsafe() == 0 {
- return nil, errors.New("sqlite library was not compiled for thread-safe operation")
- }
-
- var pkey string
-
// Options
var loc *time.Location
- txlock := "BEGIN"
-
- // PRAGMA's
- busyTimeout := 5000
- deferForeignKeys := -1
- recursiveTriggers := -1
- writableSchema := -1
- vfsName := ""
pos := strings.IndexRune(dsn, '?')
if pos >= 1 {
@@ -1738,102 +1680,6 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
}
}
- // _txlock
- if val := params.Get("_txlock"); val != "" {
- switch strings.ToLower(val) {
- case "immediate":
- txlock = "BEGIN IMMEDIATE"
- case "exclusive":
- txlock = "BEGIN EXCLUSIVE"
- case "deferred":
- txlock = "BEGIN"
- default:
- return nil, fmt.Errorf("Invalid _txlock: %v", val)
- }
- }
-
- // Busy Timeout (_busy_timeout)
- //
- // https://www.sqlite.org/pragma.html#pragma_busy_timeout
- //
- pkey = "" // Reset pkey
- if _, ok := params["_busy_timeout"]; ok {
- pkey = "_busy_timeout"
- }
- if _, ok := params["_timeout"]; ok {
- pkey = "_timeout"
- }
- if val := params.Get(pkey); val != "" {
- iv, err := strconv.ParseInt(val, 10, 64)
- if err != nil {
- return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)
- }
- busyTimeout = int(iv)
- }
-
- // Defer Foreign Keys (_defer_foreign_keys | _defer_fk)
- //
- // https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys
- //
- pkey = "" // Reset pkey
- if _, ok := params["_defer_foreign_keys"]; ok {
- pkey = "_defer_foreign_keys"
- }
- if _, ok := params["_defer_fk"]; ok {
- pkey = "_defer_fk"
- }
- if val := params.Get(pkey); val != "" {
- switch strings.ToLower(val) {
- case "0", "no", "false", "off":
- deferForeignKeys = 0
- case "1", "yes", "true", "on":
- deferForeignKeys = 1
- default:
- return nil, fmt.Errorf("Invalid _defer_foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val)
- }
- }
-
- // Recursive Triggers (_recursive_triggers)
- //
- // https://www.sqlite.org/pragma.html#pragma_recursive_triggers
- //
- pkey = "" // Reset pkey
- if _, ok := params["_recursive_triggers"]; ok {
- pkey = "_recursive_triggers"
- }
- if _, ok := params["_rt"]; ok {
- pkey = "_rt"
- }
- if val := params.Get(pkey); val != "" {
- switch strings.ToLower(val) {
- case "0", "no", "false", "off":
- recursiveTriggers = 0
- case "1", "yes", "true", "on":
- recursiveTriggers = 1
- default:
- return nil, fmt.Errorf("Invalid _recursive_triggers: %v, expecting boolean value of '0 1 false true no yes off on'", val)
- }
- }
-
- // Writable Schema (_writeable_schema)
- //
- // https://www.sqlite.org/pragma.html#pragma_writeable_schema
- //
- if val := params.Get("_writable_schema"); val != "" {
- switch strings.ToLower(val) {
- case "0", "no", "false", "off":
- writableSchema = 0
- case "1", "yes", "true", "on":
- writableSchema = 1
- default:
- return nil, fmt.Errorf("Invalid _writable_schema: %v, expecting boolean value of '0 1 false true no yes off on'", val)
- }
- }
-
- if val := params.Get("vfs"); val != "" {
- vfsName = val
- }
-
if !strings.HasPrefix(dsn, "file:") {
dsn = dsn[:pos]
}
@@ -1842,18 +1688,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
var db *C.sqlite3
name := C.CString(dsn)
defer C.free(unsafe.Pointer(name))
- var vfs *C.char
- if vfsName != "" {
- vfs = C.CString(vfsName)
- defer C.free(unsafe.Pointer(vfs))
- }
var openFlags C.int =
- C.SQLITE_OPEN_READWRITE |
+ C.SQLITE_OPEN_READWRITE | // FIXME: fails if RO FS?
C.SQLITE_OPEN_CREATE |
C.SQLITE_OPEN_URI |
C.SQLITE_OPEN_FULLMUTEX
- rv := C.sqlite3_open_v2(name, &db, openFlags, vfs)
+ rv := C.sqlite3_open_v2(name, &db, openFlags, nil)
if rv != 0 {
// Save off the error _before_ closing the database.
// This is safe even if db is nil.
@@ -1867,54 +1708,21 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, errors.New("sqlite succeeded without returning a database")
}
- exec := func(s string) error {
- cs := C.CString(s)
- rv := C.sqlite3_exec(db, cs, nil, nil, nil)
- C.free(unsafe.Pointer(cs))
- if rv != C.SQLITE_OK {
- return lastError(db)
- }
- return nil
- }
-
- // FIXME: these should be compiled into SQLite
- // Busy timeout
- if err := exec(fmt.Sprintf("PRAGMA busy_timeout = %d;", busyTimeout)); err != nil {
+ const setup = `
+ PRAGMA journal_mode = WAL;
+ PRAGMA busy_timeout = 10000;
+ `
+ setupCStr := C.CString(setup)
+ defer C.free(unsafe.Pointer(setupCStr))
+ rv = C.sqlite3_exec(db, setupCStr, nil, nil, nil)
+ if rv != C.SQLITE_OK {
+ err := lastError(db)
C.sqlite3_close_v2(db)
return nil, err
}
// Create connection to SQLite
- conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
-
- // Defer Foreign Keys
- if deferForeignKeys > -1 {
- if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
- }
- }
-
- if err := exec("PRAGMA journal_mode = WAL;"); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
- }
-
- // Recursive Triggers
- if recursiveTriggers > -1 {
- if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
- }
- }
-
- // Writable Schema
- if writableSchema > -1 {
- if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
- }
- }
+ conn := &SQLiteConn{db: db, loc: loc}
if d.ConnectHook != nil {
if err := d.ConnectHook(conn); err != nil {
@@ -1922,6 +1730,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, err
}
}
+
runtime.SetFinalizer(conn, (*SQLiteConn).Close)
return conn, nil
}