// Open database and return a new connection. // You can specify DSN string with URI filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: 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 db *C.sqlite3 name := C.CString(dsn) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, C.SQLITE_OPEN_FULLMUTEX| C.SQLITE_OPEN_READWRITE| C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } rv = C.sqlite3_busy_timeout(db, 5000) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } return &SQLiteConn{db}, nil }
// Open database and return a new connection. // You can specify DSN string with URI filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: 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 db *C.sqlite3 name := C.CString(dsn) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, C.SQLITE_OPEN_FULLMUTEX| C.SQLITE_OPEN_READWRITE| C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, Error{Code: ErrNo(rv)} } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } rv = C.sqlite3_busy_timeout(db, 5000) if rv != C.SQLITE_OK { return nil, Error{Code: ErrNo(rv)} } conn := &SQLiteConn{db} if len(d.Extensions) > 0 { rv = C.sqlite3_enable_load_extension(db, 1) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } for _, extension := range d.Extensions { cext := C.CString(extension) defer C.free(unsafe.Pointer(cext)) rv = C.sqlite3_load_extension(db, cext, nil, nil) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } } rv = C.sqlite3_enable_load_extension(db, 0) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } } if d.ConnectHook != nil { if err := d.ConnectHook(conn); err != nil { return nil, err } } runtime.SetFinalizer(conn, (*SQLiteConn).Close) return conn, nil }
func (s *SQLiteStmt) bind(args []driver.Value) error { rv := C.sqlite3_reset(s.s) if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } for i, v := range args { n := C.int(i + 1) switch v := v.(type) { case nil: rv = C.sqlite3_bind_null(s.s, n) case string: if len(v) == 0 { b := []byte{0} rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0)) } else { b := []byte(v) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) } case int: rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v)) case int32: rv = C.sqlite3_bind_int(s.s, n, C.int(v)) case int64: rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v)) case byte: rv = C.sqlite3_bind_int(s.s, n, C.int(v)) case bool: if bool(v) { rv = C.sqlite3_bind_int(s.s, n, 1) } else { rv = C.sqlite3_bind_int(s.s, n, 0) } case float32: rv = C.sqlite3_bind_double(s.s, n, C.double(v)) case float64: rv = C.sqlite3_bind_double(s.s, n, C.double(v)) case []byte: var p *byte if len(v) > 0 { p = &v[0] } rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v))) case time.Time: b := []byte(v.UTC().Format(SQLiteTimestampFormats[0])) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) } if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } } return nil }
func (s *SQLiteStmt) Close() error { rv := C.sqlite3_finalize(s.s) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } return nil }
// Close the rows. func (rc *SQLiteRows) Close() error { rv := C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } return nil }
func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: dest[i] = int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) p := C.sqlite3_column_blob(rc.s.s, C.int(i)) dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: dest[i] = C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) } } return nil }
func (c *SQLiteConn) lastError() Error { return Error{ Code: ErrNo(C.sqlite3_errcode(c.db)), ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)), err: C.GoString(C.sqlite3_errmsg(c.db)), } }
func (rc *SQLiteRows) Next(dest []driver.Value) error { rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF } if rv != C.SQLITE_ROW { return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) } if rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) } } for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) switch rc.decltype[i] { case "timestamp": dest[i] = time.Unix(val, 0) case "boolean": dest[i] = val > 0 default: dest[i] = val } case C.SQLITE_FLOAT: dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) case C.SQLITE_BLOB: n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) p := C.sqlite3_column_blob(rc.s.s, C.int(i)) switch dest[i].(type) { case sql.RawBytes: dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] default: slice := make([]byte, n) copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) dest[i] = slice } case C.SQLITE_NULL: dest[i] = nil case C.SQLITE_TEXT: var err error s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) if rc.decltype[i] == "timestamp" { dest[i], err = time.Parse(SQLiteTimestampFormat, s) if err != nil { return err } } else { dest[i] = s } } } return nil }
func (c *conn) error(rv C.int) error { if rv == 0 { return nil } if rv == 21 || c.closed { return errno(rv) } return errors.New(errno(rv).Error() + ": " + C.GoString(C.sqlite3_errmsg(c.db))) }
func (self *sqlConnection) sqlErrorMessage() string { cp := C.sqlite3_errmsg(self.handle) if cp == nil { // The call can't really fail since it returns // a string constant, but let's be safe... sqlPanic("can't get error message") } return C.GoString(cp) }
func (c *SQLiteConn) exec(cmd string) error { pcmd := C.CString(cmd) defer C.free(unsafe.Pointer(pcmd)) rv := C.sqlite3_exec(c.db, pcmd, nil, nil, nil) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } return nil }
func (c *Conn) error(rv C.int) os.Error { if c == nil || c.db == nil { return os.NewError("nil sqlite database") } if rv == 21 { // misuse return Errno(rv) } return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db))) }
// LastError returns the error for the most recent failed sqlite3_* API call associated with a database connection. // (See http://sqlite.org/c3ref/errcode.html) func (c *Conn) LastError() error { if c == nil { return errors.New("nil sqlite database") } errorCode := C.sqlite3_errcode(c.db) if errorCode == C.SQLITE_OK { return nil } return &ConnError{c: c, code: Errno(errorCode), msg: C.GoString(C.sqlite3_errmsg(c.db))} }
// Execute the statement with arguments. Return result object. func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) { if err := s.bind(args); err != nil { return nil, err } rv := C.sqlite3_step(s.s) if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } return &SQLiteResult{s}, nil }
func (c *SQLiteConn) loadExtensions(extensions []string) error { rv := C.sqlite3_enable_load_extension(c.db, 1) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } for _, extension := range extensions { cext := C.CString(extension) defer C.free(unsafe.Pointer(cext)) rv = C.sqlite3_load_extension(c.db, cext, nil, nil) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } } rv = C.sqlite3_enable_load_extension(c.db, 0) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } return nil }
func (c *Conn) error(rv C.int, details ...string) error { if c == nil { return errors.New("nil sqlite database") } if rv == C.SQLITE_OK { return nil } err := &ConnError{c: c, code: Errno(rv), msg: C.GoString(C.sqlite3_errmsg(c.db))} if len(details) > 0 { err.details = details[0] } return err }
func (s *Stmt) error(rv C.int, details ...string) error { if s == nil { return errors.New("nil sqlite statement") } if rv == C.SQLITE_OK { return nil } err := ConnError{c: s.c, code: Errno(rv), msg: C.GoString(C.sqlite3_errmsg(s.c.db))} if len(details) > 0 { err.details = details[0] } return StmtError{err, s} }
// Open database and return a new connection. // You can specify DSN string with URI filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: 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") } //encrypt dsn type "file.db@123456" isp := strings.Index(dsn, "@") var fileName string var pKey string if isp > 0 { fileName = dsn[:isp] pKey = dsn[isp+1:] } else { fileName = dsn } var db *C.sqlite3 name := C.CString(fileName) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, C.SQLITE_OPEN_FULLMUTEX| C.SQLITE_OPEN_READWRITE| C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } rv = C.sqlite3_busy_timeout(db, 5000) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } //encrypt db key(db, pKey) return &SQLiteConn{db}, nil }
// Close the statement. func (s *SQLiteStmt) Close() error { if s.closed { return nil } s.closed = true if s.c == nil || s.c.db == nil { return errors.New("sqlite statement with already closed database connection") } rv := C.sqlite3_finalize(s.s) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } return nil }
// LoadExtension load the sqlite3 extension. func (c *SQLiteConn) LoadExtension(lib string, entry string) error { rv := C.sqlite3_enable_load_extension(c.db, 1) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } clib := C.CString(lib) defer C.free(unsafe.Pointer(clib)) centry := C.CString(entry) defer C.free(unsafe.Pointer(centry)) rv = C.sqlite3_load_extension(c.db, clib, centry, nil) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } rv = C.sqlite3_enable_load_extension(c.db, 0) if rv != C.SQLITE_OK { return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } return nil }
// Prepare query string. Return a new statement. func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) { pquery := C.CString(query) defer C.free(unsafe.Pointer(pquery)) var s *C.sqlite3_stmt var perror *C.char rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &perror) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(c.db))) } var t string if perror != nil && C.strlen(perror) > 0 { t = C.GoString(perror) } return &SQLiteStmt{c: c, s: s, t: t}, nil }
// Execute the statement with arguments. Return result object. func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) { if err := s.bind(args); err != nil { return nil, err } rv := C.sqlite3_step(s.s) if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) } res := &SQLiteResult{ int64(C._sqlite3_last_insert_rowid(s.c.db)), int64(C._sqlite3_changes(s.c.db)), } return res, nil }
// OpenVfs opens a new database with a specified virtual file system. func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error) { if C.sqlite3_threadsafe() == 0 { return nil, errors.New("sqlite library was not compiled for thread-safe operation") } var openFlags int if len(flags) > 0 { for _, flag := range flags { openFlags |= int(flag) } } else { openFlags = C.SQLITE_OPEN_FULLMUTEX | C.SQLITE_OPEN_READWRITE | C.SQLITE_OPEN_CREATE } var db *C.sqlite3 cname := C.CString(filename) defer C.free(unsafe.Pointer(cname)) var vfs *C.char if len(vfsname) > 0 { vfs = C.CString(vfsname) defer C.free(unsafe.Pointer(vfs)) } rv := C.sqlite3_open_v2(cname, &db, C.int(openFlags), vfs) if rv != C.SQLITE_OK { if db != nil { // try to extract futher details from db... err := OpenError{Code: Errno(rv), ExtendedCode: int(C.sqlite3_extended_errcode(db)), Msg: C.GoString(C.sqlite3_errmsg(db)), Filename: filename, } C.sqlite3_close(db) return nil, err } return nil, Errno(rv) } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } c := &Conn{db: db, stmtCache: newCache(), DefaultTimeLayout: "2006-01-02 15:04:05.000Z07:00"} if os.Getenv("SQLITE_DEBUG") != "" { //c.SetAuthorizer(authorizer, c.db) c.Trace(trace, "TRACE") //c.SetCacheSize(0) } return c, nil }
func (c *Conn) error(rv C.int) os.Error { if rv == 21 { // misuse return Errno(rv) } return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db))) }
// Open database and return a new connection. // You can specify DSN string with URI filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: // go-sqlite handle especially query parameters. // _loc=XXX // Specify location of time format. It's possible to specify "auto". // _busy_timeout=XXX // Specify value for sqlite3_busy_timeout. // _txlock=XXX // Specify locking behavior for transactions. XXX can be "immediate", // "deferred", "exclusive". 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 loc *time.Location txlock := "BEGIN" busy_timeout := 5000 pos := strings.IndexRune(dsn, '?') if pos >= 1 { params, err := url.ParseQuery(dsn[pos+1:]) if err != nil { return nil, err } // _loc if val := params.Get("_loc"); val != "" { if val == "auto" { loc = time.Local } else { loc, err = time.LoadLocation(val) if err != nil { return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err) } } } // _busy_timeout if val := params.Get("_busy_timeout"); val != "" { iv, err := strconv.ParseInt(val, 10, 64) if err != nil { return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) } busy_timeout = int(iv) } // _txlock if val := params.Get("_txlock"); val != "" { switch val { case "immediate": txlock = "BEGIN IMMEDIATE" case "exclusive": txlock = "BEGIN EXCLUSIVE" case "deferred": txlock = "BEGIN" default: return nil, fmt.Errorf("Invalid _txlock: %v", val) } } if !strings.HasPrefix(dsn, "file:") { dsn = dsn[:pos] } } var db *C.sqlite3 name := C.CString(dsn) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, C.SQLITE_OPEN_FULLMUTEX| C.SQLITE_OPEN_READWRITE| C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, Error{Code: ErrNo(rv)} } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } rv = C.sqlite3_busy_timeout(db, C.int(busy_timeout)) if rv != C.SQLITE_OK { return nil, Error{Code: ErrNo(rv)} } conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} if len(d.Extensions) > 0 { rv = C.sqlite3_enable_load_extension(db, 1) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } for _, extension := range d.Extensions { cext := C.CString(extension) defer C.free(unsafe.Pointer(cext)) rv = C.sqlite3_load_extension(db, cext, nil, nil) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } } rv = C.sqlite3_enable_load_extension(db, 0) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } } if d.ConnectHook != nil { if err := d.ConnectHook(conn); err != nil { return nil, err } } runtime.SetFinalizer(conn, (*SQLiteConn).Close) return conn, nil }
// Open database and return a new connection. // You can specify DSN string with URI filename. // test.db // file:test.db?cache=shared&mode=memory // :memory: // file::memory: 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 db *C.sqlite3 name := C.CString(dsn) defer C.free(unsafe.Pointer(name)) rv := C._sqlite3_open_v2(name, &db, C.SQLITE_OPEN_FULLMUTEX| C.SQLITE_OPEN_READWRITE| C.SQLITE_OPEN_CREATE, nil) if rv != 0 { return nil, ErrNo(rv) } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") } rv = C.sqlite3_busy_timeout(db, 5000) if rv != C.SQLITE_OK { return nil, ErrNo(rv) } conn := &SQLiteConn{db} if len(d.Extensions) > 0 { rv = C.sqlite3_enable_load_extension(db, 1) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } stmt, err := conn.Prepare("SELECT load_extension(?);") if err != nil { return nil, err } for _, extension := range d.Extensions { if _, err = stmt.Exec([]driver.Value{extension}); err != nil { return nil, err } } if err = stmt.Close(); err != nil { return nil, err } rv = C.sqlite3_enable_load_extension(db, 0) if rv != C.SQLITE_OK { return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) } } if d.ConnectHook != nil { if err := d.ConnectHook(conn); err != nil { return nil, err } } return conn, nil }
func fillDBError(dbErr *Error, db *C.sqlite3) { // See SQLiteConn.lastError(), in file 'sqlite3.go' at the time of writing (Sept 5, 2016) dbErr.Code = ErrNo(C.sqlite3_errcode(db)) dbErr.ExtendedCode = ErrNoExtended(C.sqlite3_extended_errcode(db)) dbErr.err = C.GoString(C.sqlite3_errmsg(db)) }
func (h *Handle) ErrMsg() (err string) { return C.GoString(C.sqlite3_errmsg(h.cptr)) }
// LastError returns the error for the most recent failed sqlite3_* API call associated with a database connection. // (See http://sqlite.org/c3ref/errcode.html) func (c *Conn) LastError() error { if c == nil { return errors.New("nil sqlite database") } return &ConnError{c: c, code: Errno(C.sqlite3_errcode(c.db)), msg: C.GoString(C.sqlite3_errmsg(c.db))} }
// libErr reports an error originating in SQLite. The error message is obtained // from the database connection when possible, which may include some additional // information. Otherwise, the result code is translated to a generic message. func libErr(rc C.int, db *C.sqlite3) error { if db != nil && rc == C.sqlite3_errcode(db) { return &Error{int(rc), C.GoString(C.sqlite3_errmsg(db))} } return &Error{int(rc), C.GoString(C.sqlite3_errstr(rc))} }