diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/golite.go | 219 |
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 } |