├── .gitignore ├── LICENSE ├── README.md ├── defines.go ├── errors.go ├── functions.go ├── register_dll.go ├── sqlite3.go ├── sqlite3_conn.go ├── sqlite3_raw.go ├── sqlite3_rows.go ├── sqlite3_stmt.go └── sqlite3_tx.go /.gitignore: -------------------------------------------------------------------------------- 1 | support/* 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Yasuhiro Matsumoto & 2016 Samuel Melrose 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go-SQLite3-Win64 2 | ## GoLang Wrapper for sqlite3.dll on Windows 64Bit 3 | 4 | This package provides an alternative to [go-sqlite3](https://github.com/mattn/go-sqlite3) on Windows 64bit. 5 | 6 | Although I don't think you can call it pure-Go since it requires the DLL, it doesn't require CGo to build, so the build is pure-Go. 7 | 8 | This should allow really easy cross compile support when building from another OS (e.g. Linux). 9 | 10 | Basic functionality is implemented, but it doesn't support things like user defined functions that call back to Go code. 11 | 12 | You'll need [sqlite3.dll](https://sqlite.org/download.html) in either the same folder as you finished executable, or in a "support" folder in the same path as your exe. 13 | 14 | Otherwise, usage should be the same as for go-sqlite3. 15 | -------------------------------------------------------------------------------- /defines.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "time" 14 | "database/sql/driver" 15 | ) 16 | 17 | // SQLiteTimestampFormats is timestamp formats understood by both this module 18 | // and SQLite. The first format in the slice will be used when saving time 19 | // values into the database. When parsing a string from a timestamp or datetime 20 | // column, the formats are tried in order. 21 | var SQLiteTimestampFormats = []string{ 22 | // By default, store timestamps with whatever timezone they come with. 23 | // When parsed, they will be returned with the same timezone. 24 | "2006-01-02 15:04:05.999999999-07:00", 25 | "2006-01-02T15:04:05.999999999-07:00", 26 | "2006-01-02 15:04:05.999999999", 27 | "2006-01-02T15:04:05.999999999", 28 | "2006-01-02 15:04:05", 29 | "2006-01-02T15:04:05", 30 | "2006-01-02 15:04", 31 | "2006-01-02T15:04", 32 | "2006-01-02", 33 | } 34 | 35 | const ( 36 | SQLITE_OK = 0 37 | SQLITE_OPEN_READONLY = 0x00000001 /* Ok for sqlite3_open_v2() */ 38 | SQLITE_OPEN_READWRITE = 0x00000002 /* Ok for sqlite3_open_v2() */ 39 | SQLITE_OPEN_CREATE = 0x00000004 /* Ok for sqlite3_open_v2() */ 40 | SQLITE_OPEN_DELETEONCLOSE = 0x00000008 /* VFS only */ 41 | SQLITE_OPEN_EXCLUSIVE = 0x00000010 /* VFS only */ 42 | SQLITE_OPEN_AUTOPROXY = 0x00000020 /* VFS only */ 43 | SQLITE_OPEN_URI = 0x00000040 /* Ok for sqlite3_open_v2() */ 44 | SQLITE_OPEN_MEMORY = 0x00000080 /* Ok for sqlite3_open_v2() */ 45 | SQLITE_OPEN_MAIN_DB = 0x00000100 /* VFS only */ 46 | SQLITE_OPEN_TEMP_DB = 0x00000200 /* VFS only */ 47 | SQLITE_OPEN_TRANSIENT_DB = 0x00000400 /* VFS only */ 48 | SQLITE_OPEN_MAIN_JOURNAL = 0x00000800 /* VFS only */ 49 | SQLITE_OPEN_TEMP_JOURNAL = 0x00001000 /* VFS only */ 50 | SQLITE_OPEN_SUBJOURNAL = 0x00002000 /* VFS only */ 51 | SQLITE_OPEN_MASTER_JOURNAL = 0x00004000 /* VFS only */ 52 | SQLITE_OPEN_NOMUTEX = 0x00008000 /* Ok for sqlite3_open_v2() */ 53 | SQLITE_OPEN_FULLMUTEX = 0x00010000 /* Ok for sqlite3_open_v2() */ 54 | SQLITE_OPEN_SHAREDCACHE = 0x00020000 /* Ok for sqlite3_open_v2() */ 55 | SQLITE_OPEN_PRIVATECACHE = 0x00040000 /* Ok for sqlite3_open_v2() */ 56 | SQLITE_OPEN_WAL = 0x00080000 /* VFS only */ 57 | SQLITE_STATIC = 0 58 | SQLITE_TRANSIENT = 18446744073709551615 // Can't do -1 for overflow like in C, so use largest unsigned 64bit int. 59 | 60 | SQLITE_BUSY = 5 61 | SQLITE_DONE = 101 62 | SQLITE_ROW = 100 63 | 64 | SQLITE_INTEGER = 1 65 | SQLITE_FLOAT = 2 66 | SQLITE_BLOB = 4 67 | SQLITE_NULL = 5 68 | SQLITE_TEXT = 3 69 | ) 70 | 71 | type sqlite3 uintptr 72 | type sqlite3_stmt uintptr 73 | 74 | // SQLiteDriver implement sql.Driver. 75 | type SQLiteDriver struct { 76 | Extensions []string 77 | ConnectHook func(*SQLiteConn) error 78 | } 79 | 80 | // SQLiteConn implement sql.Conn. 81 | type SQLiteConn struct { 82 | db sqlite3 83 | loc *time.Location 84 | txlock string 85 | } 86 | 87 | // SQLiteTx implemen sql.Tx. 88 | type SQLiteTx struct { 89 | c *SQLiteConn 90 | } 91 | 92 | // SQLiteStmt implement sql.Stmt. 93 | type SQLiteStmt struct { 94 | c *SQLiteConn 95 | s sqlite3_stmt 96 | t string 97 | closed bool 98 | cls bool 99 | } 100 | 101 | // SQLiteResult implement sql.Result. 102 | type SQLiteResult struct { 103 | id int64 104 | changes int64 105 | } 106 | 107 | // SQLiteRows implement sql.Rows. 108 | type SQLiteRows struct { 109 | s *SQLiteStmt 110 | nc int 111 | cols []string 112 | decltype []string 113 | cls bool 114 | done chan struct{} 115 | } 116 | 117 | type namedValue struct { 118 | Name string 119 | Ordinal int 120 | Value driver.Value 121 | } 122 | 123 | type bindArg struct { 124 | n int 125 | v driver.Value 126 | } 127 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Edited by Samuel Melrose 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Copyright (C) 2014 Yasuhiro Matsumoto . 8 | // 9 | // Use of this source code is governed by an MIT-style 10 | // license that can be found in the LICENSE file. 11 | 12 | package sqlite3 13 | 14 | // ErrNo inherit errno. 15 | type ErrNo int 16 | 17 | // ErrNoMask is mask code. 18 | const ErrNoMask = 0xff 19 | 20 | // ErrNoExtended is extended errno. 21 | type ErrNoExtended int 22 | 23 | // Error implement sqlite error code. 24 | type Error struct { 25 | Code ErrNo /* The error code returned by SQLite */ 26 | ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */ 27 | err string /* The error string returned by sqlite3_errmsg(), 28 | this usually contains more specific details. */ 29 | } 30 | 31 | // result codes from http://www.sqlite.org/c3ref/c_abort.html 32 | var ( 33 | ErrError = ErrNo(1) /* SQL error or missing database */ 34 | ErrInternal = ErrNo(2) /* Internal logic error in SQLite */ 35 | ErrPerm = ErrNo(3) /* Access permission denied */ 36 | ErrAbort = ErrNo(4) /* Callback routine requested an abort */ 37 | ErrBusy = ErrNo(5) /* The database file is locked */ 38 | ErrLocked = ErrNo(6) /* A table in the database is locked */ 39 | ErrNomem = ErrNo(7) /* A malloc() failed */ 40 | ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */ 41 | ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */ 42 | ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */ 43 | ErrCorrupt = ErrNo(11) /* The database disk image is malformed */ 44 | ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */ 45 | ErrFull = ErrNo(13) /* Insertion failed because database is full */ 46 | ErrCantOpen = ErrNo(14) /* Unable to open the database file */ 47 | ErrProtocol = ErrNo(15) /* Database lock protocol error */ 48 | ErrEmpty = ErrNo(16) /* Database is empty */ 49 | ErrSchema = ErrNo(17) /* The database schema changed */ 50 | ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */ 51 | ErrConstraint = ErrNo(19) /* Abort due to constraint violation */ 52 | ErrMismatch = ErrNo(20) /* Data type mismatch */ 53 | ErrMisuse = ErrNo(21) /* Library used incorrectly */ 54 | ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */ 55 | ErrAuth = ErrNo(23) /* Authorization denied */ 56 | ErrFormat = ErrNo(24) /* Auxiliary database format error */ 57 | ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */ 58 | ErrNotADB = ErrNo(26) /* File opened that is not a database file */ 59 | ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */ 60 | ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */ 61 | ) 62 | 63 | // Error return error message from errno. 64 | func (err ErrNo) Error() string { 65 | return Error{Code: err}.Error() 66 | } 67 | 68 | // Extend return extended errno. 69 | func (err ErrNo) Extend(by int) ErrNoExtended { 70 | return ErrNoExtended(int(err) | (by << 8)) 71 | } 72 | 73 | // Error return error message that is extended code. 74 | func (err ErrNoExtended) Error() string { 75 | return Error{Code: ErrNo(int(err) & ErrNoMask), ExtendedCode: err}.Error() 76 | } 77 | 78 | // Error return error message. 79 | func (err Error) Error() string { 80 | if err.err != "" { 81 | return err.err 82 | } 83 | return errorString(err) 84 | } 85 | 86 | // result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html 87 | var ( 88 | ErrIoErrRead = ErrIoErr.Extend(1) 89 | ErrIoErrShortRead = ErrIoErr.Extend(2) 90 | ErrIoErrWrite = ErrIoErr.Extend(3) 91 | ErrIoErrFsync = ErrIoErr.Extend(4) 92 | ErrIoErrDirFsync = ErrIoErr.Extend(5) 93 | ErrIoErrTruncate = ErrIoErr.Extend(6) 94 | ErrIoErrFstat = ErrIoErr.Extend(7) 95 | ErrIoErrUnlock = ErrIoErr.Extend(8) 96 | ErrIoErrRDlock = ErrIoErr.Extend(9) 97 | ErrIoErrDelete = ErrIoErr.Extend(10) 98 | ErrIoErrBlocked = ErrIoErr.Extend(11) 99 | ErrIoErrNoMem = ErrIoErr.Extend(12) 100 | ErrIoErrAccess = ErrIoErr.Extend(13) 101 | ErrIoErrCheckReservedLock = ErrIoErr.Extend(14) 102 | ErrIoErrLock = ErrIoErr.Extend(15) 103 | ErrIoErrClose = ErrIoErr.Extend(16) 104 | ErrIoErrDirClose = ErrIoErr.Extend(17) 105 | ErrIoErrSHMOpen = ErrIoErr.Extend(18) 106 | ErrIoErrSHMSize = ErrIoErr.Extend(19) 107 | ErrIoErrSHMLock = ErrIoErr.Extend(20) 108 | ErrIoErrSHMMap = ErrIoErr.Extend(21) 109 | ErrIoErrSeek = ErrIoErr.Extend(22) 110 | ErrIoErrDeleteNoent = ErrIoErr.Extend(23) 111 | ErrIoErrMMap = ErrIoErr.Extend(24) 112 | ErrIoErrGetTempPath = ErrIoErr.Extend(25) 113 | ErrIoErrConvPath = ErrIoErr.Extend(26) 114 | ErrLockedSharedCache = ErrLocked.Extend(1) 115 | ErrBusyRecovery = ErrBusy.Extend(1) 116 | ErrBusySnapshot = ErrBusy.Extend(2) 117 | ErrCantOpenNoTempDir = ErrCantOpen.Extend(1) 118 | ErrCantOpenIsDir = ErrCantOpen.Extend(2) 119 | ErrCantOpenFullPath = ErrCantOpen.Extend(3) 120 | ErrCantOpenConvPath = ErrCantOpen.Extend(4) 121 | ErrCorruptVTab = ErrCorrupt.Extend(1) 122 | ErrReadonlyRecovery = ErrReadonly.Extend(1) 123 | ErrReadonlyCantLock = ErrReadonly.Extend(2) 124 | ErrReadonlyRollback = ErrReadonly.Extend(3) 125 | ErrReadonlyDbMoved = ErrReadonly.Extend(4) 126 | ErrAbortRollback = ErrAbort.Extend(2) 127 | ErrConstraintCheck = ErrConstraint.Extend(1) 128 | ErrConstraintCommitHook = ErrConstraint.Extend(2) 129 | ErrConstraintForeignKey = ErrConstraint.Extend(3) 130 | ErrConstraintFunction = ErrConstraint.Extend(4) 131 | ErrConstraintNotNull = ErrConstraint.Extend(5) 132 | ErrConstraintPrimaryKey = ErrConstraint.Extend(6) 133 | ErrConstraintTrigger = ErrConstraint.Extend(7) 134 | ErrConstraintUnique = ErrConstraint.Extend(8) 135 | ErrConstraintVTab = ErrConstraint.Extend(9) 136 | ErrConstraintRowID = ErrConstraint.Extend(10) 137 | ErrNoticeRecoverWAL = ErrNotice.Extend(1) 138 | ErrNoticeRecoverRollback = ErrNotice.Extend(2) 139 | ErrWarningAutoIndex = ErrWarning.Extend(1) 140 | ) 141 | -------------------------------------------------------------------------------- /functions.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "os" 14 | "unsafe" 15 | "path/filepath" 16 | ) 17 | 18 | func exists(path string) (bool, error) { 19 | _, err := os.Stat(path) 20 | if err == nil { return true, nil } 21 | if os.IsNotExist(err) { return false, nil } 22 | return true, err 23 | } 24 | 25 | func basePath() (string) { 26 | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 27 | if err != nil { 28 | return "" 29 | } 30 | 31 | return dir + string(os.PathSeparator) 32 | } 33 | 34 | func BytePtrToString(p *byte) string { 35 | var ( 36 | sizeTest byte 37 | finalStr []byte = make([]byte, 0) 38 | ) 39 | for { 40 | if *p == byte(0) { 41 | break 42 | } 43 | 44 | finalStr = append(finalStr, *p) 45 | p = (*byte)(unsafe.Pointer( uintptr(unsafe.Pointer(p)) + unsafe.Sizeof(sizeTest) )) 46 | } 47 | return string(finalStr[0:]) 48 | } 49 | -------------------------------------------------------------------------------- /register_dll.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "os" 14 | "fmt" 15 | "syscall" 16 | ) 17 | 18 | var ( 19 | dllRegistered bool = false 20 | 21 | modSQLite3 *syscall.LazyDLL 22 | 23 | dll_sqlite3_libversion *syscall.LazyProc 24 | dll_sqlite3_libversion_number *syscall.LazyProc 25 | dll_sqlite3_sourceid *syscall.LazyProc 26 | 27 | dll_sqlite3_errstr *syscall.LazyProc 28 | dll_sqlite3_errcode *syscall.LazyProc 29 | dll_sqlite3_extended_errcode *syscall.LazyProc 30 | dll_sqlite3_errmsg *syscall.LazyProc 31 | dll_sqlite3_threadsafe *syscall.LazyProc 32 | 33 | dll_sqlite3_open_v2 *syscall.LazyProc 34 | dll_sqlite3_busy_timeout *syscall.LazyProc 35 | dll_sqlite3_close_v2 *syscall.LazyProc 36 | 37 | dll_sqlite3_prepare_v2 *syscall.LazyProc 38 | dll_sqlite3_get_autocommit *syscall.LazyProc 39 | 40 | dll_sqlite3_finalize *syscall.LazyProc 41 | dll_sqlite3_bind_parameter_count *syscall.LazyProc 42 | dll_sqlite3_bind_parameter_index *syscall.LazyProc 43 | dll_sqlite3_reset *syscall.LazyProc 44 | dll_sqlite3_bind_null *syscall.LazyProc 45 | dll_sqlite3_bind_int64 *syscall.LazyProc 46 | dll_sqlite3_bind_int *syscall.LazyProc 47 | dll_sqlite3_bind_text *syscall.LazyProc 48 | dll_sqlite3_bind_double *syscall.LazyProc 49 | dll_sqlite3_bind_blob *syscall.LazyProc 50 | dll_sqlite3_column_count *syscall.LazyProc 51 | dll_sqlite3_column_name *syscall.LazyProc 52 | dll_sqlite3_interrupt *syscall.LazyProc 53 | dll_sqlite3_clear_bindings *syscall.LazyProc 54 | 55 | dll_sqlite3_step *syscall.LazyProc 56 | dll_sqlite3_column_decltype *syscall.LazyProc 57 | dll_sqlite3_column_type *syscall.LazyProc 58 | dll_sqlite3_column_int64 *syscall.LazyProc 59 | dll_sqlite3_column_double *syscall.LazyProc 60 | dll_sqlite3_column_bytes *syscall.LazyProc 61 | dll_sqlite3_column_blob *syscall.LazyProc 62 | dll_sqlite3_column_text *syscall.LazyProc 63 | ) 64 | 65 | func registerDLLFunctions() { 66 | if err := registerDLL(); err != nil { 67 | dllRegistered = false 68 | return 69 | } 70 | 71 | dll_sqlite3_libversion = modSQLite3.NewProc("sqlite3_libversion") 72 | dll_sqlite3_libversion_number = modSQLite3.NewProc("sqlite3_libversion_number") 73 | dll_sqlite3_sourceid = modSQLite3.NewProc("sqlite3_sourceid") 74 | 75 | dll_sqlite3_errstr = modSQLite3.NewProc("sqlite3_errstr") 76 | dll_sqlite3_errcode = modSQLite3.NewProc("sqlite3_errcode") 77 | dll_sqlite3_extended_errcode = modSQLite3.NewProc("sqlite3_extended_errcode") 78 | dll_sqlite3_errmsg = modSQLite3.NewProc("sqlite3_errmsg") 79 | dll_sqlite3_threadsafe = modSQLite3.NewProc("sqlite3_threadsafe") 80 | 81 | dll_sqlite3_open_v2 = modSQLite3.NewProc("sqlite3_open_v2") 82 | dll_sqlite3_busy_timeout = modSQLite3.NewProc("sqlite3_busy_timeout") 83 | dll_sqlite3_close_v2 = modSQLite3.NewProc("sqlite3_close_v2") 84 | 85 | dll_sqlite3_prepare_v2 = modSQLite3.NewProc("sqlite3_prepare_v2") 86 | dll_sqlite3_get_autocommit = modSQLite3.NewProc("sqlite3_get_autocommit") 87 | 88 | dll_sqlite3_finalize = modSQLite3.NewProc("sqlite3_finalize") 89 | dll_sqlite3_bind_parameter_count = modSQLite3.NewProc("sqlite3_bind_parameter_count") 90 | dll_sqlite3_bind_parameter_index = modSQLite3.NewProc("sqlite3_bind_parameter_index") 91 | dll_sqlite3_reset = modSQLite3.NewProc("sqlite3_reset") 92 | dll_sqlite3_bind_null = modSQLite3.NewProc("sqlite3_bind_null") 93 | dll_sqlite3_bind_int64 = modSQLite3.NewProc("sqlite3_bind_int64") 94 | dll_sqlite3_bind_int = modSQLite3.NewProc("sqlite3_bind_int") 95 | dll_sqlite3_bind_text = modSQLite3.NewProc("sqlite3_bind_text") 96 | dll_sqlite3_bind_double = modSQLite3.NewProc("sqlite3_bind_double") 97 | dll_sqlite3_bind_blob = modSQLite3.NewProc("sqlite3_bind_blob") 98 | dll_sqlite3_column_count = modSQLite3.NewProc("sqlite3_column_count") 99 | dll_sqlite3_column_name = modSQLite3.NewProc("sqlite3_column_name") 100 | dll_sqlite3_interrupt = modSQLite3.NewProc("sqlite3_interrupt") 101 | dll_sqlite3_clear_bindings = modSQLite3.NewProc("sqlite3_clear_bindings") 102 | 103 | dll_sqlite3_step = modSQLite3.NewProc("sqlite3_step") 104 | dll_sqlite3_column_decltype = modSQLite3.NewProc("sqlite3_column_decltype") 105 | dll_sqlite3_column_type = modSQLite3.NewProc("sqlite3_column_type") 106 | dll_sqlite3_column_int64 = modSQLite3.NewProc("sqlite3_column_int64") 107 | dll_sqlite3_column_double = modSQLite3.NewProc("sqlite3_column_double") 108 | dll_sqlite3_column_bytes = modSQLite3.NewProc("sqlite3_column_bytes") 109 | dll_sqlite3_column_blob = modSQLite3.NewProc("sqlite3_column_blob") 110 | dll_sqlite3_column_text = modSQLite3.NewProc("sqlite3_column_text") 111 | 112 | dllRegistered = true 113 | } 114 | 115 | func registerDLL() (error) { 116 | dllName := "sqlite3.dll" 117 | 118 | filePath := basePath() + dllName 119 | if exist, _ := exists(filePath); exist { 120 | modSQLite3 = syscall.NewLazyDLL(filePath) 121 | return nil 122 | } 123 | 124 | filePath = basePath() + "support" + string(os.PathSeparator) + dllName 125 | if exist, _ := exists(filePath); exist { 126 | modSQLite3 = syscall.NewLazyDLL(filePath) 127 | return nil 128 | } 129 | 130 | return fmt.Errorf("%s not found.", dllName) 131 | } 132 | -------------------------------------------------------------------------------- /sqlite3.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "fmt" 14 | "time" 15 | "strings" 16 | "net/url" 17 | "strconv" 18 | "runtime" 19 | "database/sql" 20 | "database/sql/driver" 21 | ) 22 | 23 | func init() { 24 | registerDLLFunctions() 25 | 26 | sql.Register("sqlite3", &SQLiteDriver{}) 27 | } 28 | 29 | func Version() (libVersion string, libVersionNumber int, sourceID string) { 30 | return sqlite3_libversion(), sqlite3_libversion_number(), sqlite3_sourceid() 31 | } 32 | 33 | func errorString(err Error) string { 34 | return sqlite3_errstr(int(err.Code)) 35 | } 36 | 37 | func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { 38 | if ! dllRegistered { 39 | registerDLLFunctions() 40 | if ! dllRegistered { 41 | return nil, fmt.Errorf("sqlite library not found") 42 | } 43 | } 44 | if sqlite3_threadsafe() == 0 { 45 | return nil, fmt.Errorf("sqlite library was not compiled for thread-safe operation") 46 | } 47 | 48 | var loc *time.Location 49 | txlock := "BEGIN" 50 | busyTimeout := 5000 51 | pos := strings.IndexRune(dsn, '?') 52 | if pos >= 1 { 53 | params, err := url.ParseQuery(dsn[pos+1:]) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | // _loc 59 | if val := params.Get("_loc"); val != "" { 60 | if val == "auto" { 61 | loc = time.Local 62 | } else { 63 | loc, err = time.LoadLocation(val) 64 | if err != nil { 65 | return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err) 66 | } 67 | } 68 | } 69 | 70 | // _busy_timeout 71 | if val := params.Get("_busy_timeout"); val != "" { 72 | iv, err := strconv.ParseInt(val, 10, 64) 73 | if err != nil { 74 | return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) 75 | } 76 | busyTimeout = int(iv) 77 | } 78 | 79 | // _txlock 80 | if val := params.Get("_txlock"); val != "" { 81 | switch val { 82 | case "immediate": 83 | txlock = "BEGIN IMMEDIATE" 84 | case "exclusive": 85 | txlock = "BEGIN EXCLUSIVE" 86 | case "deferred": 87 | txlock = "BEGIN" 88 | default: 89 | return nil, fmt.Errorf("Invalid _txlock: %v", val) 90 | } 91 | } 92 | 93 | if !strings.HasPrefix(dsn, "file:") { 94 | dsn = dsn[:pos] 95 | } 96 | } 97 | 98 | var db sqlite3 99 | rv := sqlite3_open_v2(dsn, &db, SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "") 100 | if rv != 0 { 101 | return nil, Error{Code: ErrNo(rv)} 102 | } 103 | if db == sqlite3(uintptr(0)) { 104 | return nil, fmt.Errorf("sqlite succeeded without returning a database") 105 | } 106 | 107 | rv = sqlite3_busy_timeout(db, busyTimeout) 108 | if rv != SQLITE_OK { 109 | return nil, Error{Code: ErrNo(rv)} 110 | } 111 | 112 | conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} 113 | 114 | if d.ConnectHook != nil { 115 | if err := d.ConnectHook(conn); err != nil { 116 | return nil, err 117 | } 118 | } 119 | runtime.SetFinalizer(conn, (*SQLiteConn).Close) 120 | return conn, nil 121 | } 122 | -------------------------------------------------------------------------------- /sqlite3_conn.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | "runtime" 16 | "database/sql/driver" 17 | "golang.org/x/net/context" 18 | ) 19 | 20 | // Exec implements Execer. 21 | func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, error) { 22 | list := make([]namedValue, len(args)) 23 | for i, v := range args { 24 | list[i] = namedValue{ 25 | Ordinal: i + 1, 26 | Value: v, 27 | } 28 | } 29 | return c.exec(context.Background(), query, list) 30 | } 31 | 32 | func (c *SQLiteConn) exec(ctx context.Context, query string, args []namedValue) (driver.Result, error) { 33 | start := 0 34 | for { 35 | s, err := c.prepare(ctx, query) 36 | if err != nil { 37 | return nil, err 38 | } 39 | var res driver.Result 40 | if s.(*SQLiteStmt).s != sqlite3_stmt(uintptr(0)) { 41 | na := s.NumInput() 42 | if len(args) < na { 43 | return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args)) 44 | } 45 | for i := 0; i < na; i++ { 46 | args[i].Ordinal -= start 47 | } 48 | res, err = s.(*SQLiteStmt).exec(ctx, args[:na]) 49 | if err != nil && err != driver.ErrSkip { 50 | s.Close() 51 | return nil, err 52 | } 53 | args = args[na:] 54 | start += na 55 | } 56 | tail := s.(*SQLiteStmt).t 57 | s.Close() 58 | if tail == "" { 59 | return res, nil 60 | } 61 | query = tail 62 | } 63 | } 64 | 65 | // Query implements Queryer. 66 | func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, error) { 67 | list := make([]namedValue, len(args)) 68 | for i, v := range args { 69 | list[i] = namedValue{ 70 | Ordinal: i + 1, 71 | Value: v, 72 | } 73 | } 74 | return c.query(context.Background(), query, list) 75 | } 76 | 77 | func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue) (driver.Rows, error) { 78 | start := 0 79 | for { 80 | s, err := c.prepare(ctx, query) 81 | if err != nil { 82 | return nil, err 83 | } 84 | s.(*SQLiteStmt).cls = true 85 | na := s.NumInput() 86 | if len(args) < na { 87 | return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args)) 88 | } 89 | for i := 0; i < na; i++ { 90 | args[i].Ordinal -= start 91 | } 92 | rows, err := s.(*SQLiteStmt).query(ctx, args[:na]) 93 | if err != nil && err != driver.ErrSkip { 94 | s.Close() 95 | return rows, err 96 | } 97 | args = args[na:] 98 | start += na 99 | tail := s.(*SQLiteStmt).t 100 | if tail == "" { 101 | return rows, nil 102 | } 103 | rows.Close() 104 | s.Close() 105 | query = tail 106 | } 107 | } 108 | 109 | // Begin transaction. 110 | func (c *SQLiteConn) Begin() (driver.Tx, error) { 111 | return c.begin(context.Background()) 112 | } 113 | 114 | func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) { 115 | if _, err := c.exec(ctx, c.txlock, nil); err != nil { 116 | return nil, err 117 | } 118 | return &SQLiteTx{c}, nil 119 | } 120 | 121 | // Prepare the query string. Return a new statement. 122 | func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) { 123 | return c.prepare(context.Background(), query) 124 | } 125 | 126 | func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, error) { 127 | rv, s, tail := sqlite3_prepare_v2(c.db, query) 128 | if rv != SQLITE_OK { 129 | return nil, c.lastError() 130 | } 131 | t := strings.TrimSpace(tail) 132 | ss := &SQLiteStmt{c: c, s: s, t: t} 133 | runtime.SetFinalizer(ss, (*SQLiteStmt).Close) 134 | return ss, nil 135 | } 136 | 137 | // AutoCommit return which currently auto commit or not. 138 | func (c *SQLiteConn) AutoCommit() bool { 139 | return sqlite3_get_autocommit(c.db) != 0 140 | } 141 | 142 | // Close the connection. 143 | func (c *SQLiteConn) Close() error { 144 | rv := sqlite3_close_v2(c.db) 145 | if rv != SQLITE_OK { 146 | return c.lastError() 147 | } 148 | c.db = sqlite3(uintptr(0)) 149 | runtime.SetFinalizer(c, nil) 150 | return nil 151 | } 152 | 153 | func (c *SQLiteConn) lastError() Error { 154 | return Error{ 155 | Code: ErrNo(sqlite3_errcode(c.db)), 156 | ExtendedCode: ErrNoExtended(sqlite3_extended_errcode(c.db)), 157 | err: sqlite3_errmsg(c.db), 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /sqlite3_raw.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | func sqlite3_libversion() (string) { 17 | msgPtr, _, _ := dll_sqlite3_libversion.Call() 18 | if msgPtr == uintptr(0) { 19 | return "Unknown" 20 | } 21 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 22 | } 23 | 24 | func sqlite3_libversion_number() (int) { 25 | intPtr, _, _ := dll_sqlite3_libversion_number.Call() 26 | if intPtr == uintptr(0) { 27 | return 0 28 | } 29 | return int(intPtr) 30 | } 31 | 32 | func sqlite3_sourceid() (string) { 33 | msgPtr, _, _ := dll_sqlite3_sourceid.Call() 34 | if msgPtr == uintptr(0) { 35 | return "Unknown" 36 | } 37 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 38 | } 39 | 40 | func sqlite3_errstr(code int) (msg string) { 41 | msgPtr, _, _ := dll_sqlite3_errstr.Call(uintptr(code)) 42 | if msgPtr == uintptr(0) { 43 | return "Unknown Error" 44 | } 45 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 46 | } 47 | 48 | func sqlite3_errcode(db sqlite3) (code int) { 49 | retInt, _, _ := dll_sqlite3_errcode.Call(uintptr(db)) 50 | return int(retInt) 51 | } 52 | 53 | func sqlite3_extended_errcode(db sqlite3) (code int) { 54 | retInt, _, _ := dll_sqlite3_extended_errcode.Call(uintptr(db)) 55 | return int(retInt) 56 | } 57 | 58 | func sqlite3_errmsg(db sqlite3) (msg string) { 59 | msgPtr, _, _ := dll_sqlite3_errmsg.Call(uintptr(db)) 60 | if msgPtr == uintptr(0) { 61 | return "Unknown Error" 62 | } 63 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 64 | } 65 | 66 | func sqlite3_threadsafe() (int) { 67 | intPtr, _, _ := dll_sqlite3_threadsafe.Call() 68 | return int(intPtr) 69 | } 70 | 71 | func sqlite3_open_v2(filename string, ppDb *sqlite3, flags int, zVfs string) (int) { 72 | var fn uintptr 73 | if len(filename) > 0 { 74 | var tfn []byte = []byte(filename) 75 | fn = uintptr(unsafe.Pointer(&tfn[0])) 76 | } else { 77 | fn = uintptr(0) 78 | } 79 | var vfs uintptr 80 | if len(zVfs) > 0 { 81 | var tvfs []byte = []byte(zVfs) 82 | vfs = uintptr(unsafe.Pointer(&tvfs[0])) 83 | } else { 84 | vfs = uintptr(0) 85 | } 86 | retInt, _, _ := dll_sqlite3_open_v2.Call( 87 | fn, 88 | uintptr(unsafe.Pointer(ppDb)), 89 | uintptr(flags), 90 | vfs, 91 | ) 92 | return int(retInt) 93 | } 94 | 95 | func sqlite3_busy_timeout(db sqlite3, busyTimeout int) (int) { 96 | retInt, _, _ := dll_sqlite3_busy_timeout.Call(uintptr(db), uintptr(busyTimeout)) 97 | return int(retInt) 98 | } 99 | 100 | func sqlite3_close_v2(db sqlite3) (int) { 101 | retInt, _, _ := dll_sqlite3_close_v2.Call(uintptr(db)) 102 | return int(retInt) 103 | } 104 | 105 | func sqlite3_prepare_v2(db sqlite3, zSql string) (retCode int, stmtHandle sqlite3_stmt, tail string) { 106 | var sql []byte = []byte(zSql + "\x00") 107 | var handle uintptr 108 | var thandle uintptr 109 | retInt, _, _ := dll_sqlite3_prepare_v2.Call( 110 | uintptr(db), 111 | uintptr(unsafe.Pointer(&sql[0])), 112 | uintptr(SQLITE_TRANSIENT), 113 | uintptr(unsafe.Pointer(&handle)), 114 | uintptr(unsafe.Pointer(&thandle)), 115 | ) 116 | 117 | return int(retInt), sqlite3_stmt(handle), BytePtrToString((*byte)(unsafe.Pointer(thandle))) 118 | } 119 | 120 | func sqlite3_get_autocommit(db sqlite3) (int) { 121 | retInt, _, _ := dll_sqlite3_get_autocommit.Call(uintptr(db)) 122 | return int(retInt) 123 | } 124 | 125 | func sqlite3_finalize(stmt sqlite3_stmt) (int) { 126 | retInt, _, _ := dll_sqlite3_finalize.Call(uintptr(stmt)) 127 | return int(retInt) 128 | } 129 | 130 | func sqlite3_bind_parameter_count(stmt sqlite3_stmt) (int) { 131 | retInt, _, _ := dll_sqlite3_bind_parameter_count.Call(uintptr(stmt)) 132 | return int(retInt) 133 | } 134 | 135 | func sqlite3_bind_parameter_index(stmt sqlite3_stmt, name string) (int) { 136 | var pName []byte = []byte(name) 137 | retInt, _, _ := dll_sqlite3_bind_parameter_index.Call( 138 | uintptr(stmt), 139 | uintptr(unsafe.Pointer(&pName[0])), 140 | ) 141 | return int(retInt) 142 | } 143 | 144 | func sqlite3_reset(stmt sqlite3_stmt) (int) { 145 | retInt, _, _ := dll_sqlite3_reset.Call(uintptr(stmt)) 146 | return int(retInt) 147 | } 148 | 149 | func sqlite3_bind_null(stmt sqlite3_stmt, ord int) (int) { 150 | retInt, _, _ := dll_sqlite3_bind_null.Call( 151 | uintptr(stmt), 152 | uintptr(ord), 153 | ) 154 | return int(retInt) 155 | } 156 | 157 | func sqlite3_bind_text(stmt sqlite3_stmt, ord int, data string) (int) { 158 | var b []byte 159 | if len(data) == 0 { 160 | b = []byte{0} 161 | } else { 162 | b = []byte(data) 163 | } 164 | retInt, _, _ := dll_sqlite3_bind_text.Call( 165 | uintptr(stmt), 166 | uintptr(ord), 167 | uintptr(unsafe.Pointer(&b[0])), 168 | uintptr(len(data)), 169 | uintptr(SQLITE_TRANSIENT), 170 | ) 171 | return int(retInt) 172 | } 173 | 174 | func sqlite3_bind_int64(stmt sqlite3_stmt, ord int, data int64) (int) { 175 | retInt, _, _ := dll_sqlite3_bind_int64.Call( 176 | uintptr(stmt), 177 | uintptr(ord), 178 | uintptr(data), 179 | ) 180 | return int(retInt) 181 | } 182 | 183 | func sqlite3_bind_int(stmt sqlite3_stmt, ord int, data int) (int) { 184 | retInt, _, _ := dll_sqlite3_bind_int.Call( 185 | uintptr(stmt), 186 | uintptr(ord), 187 | uintptr(data), 188 | ) 189 | return int(retInt) 190 | } 191 | 192 | func sqlite3_bind_double(stmt sqlite3_stmt, ord int, data float64) (int) { 193 | retInt, _, _ := dll_sqlite3_bind_double.Call( 194 | uintptr(stmt), 195 | uintptr(ord), 196 | uintptr(data), 197 | ) 198 | return int(retInt) 199 | } 200 | 201 | func sqlite3_bind_blob(stmt sqlite3_stmt, ord int, data []byte) (int) { 202 | var pData uintptr 203 | if len(data) == 0 { 204 | pData = 0 205 | } else { 206 | pData = uintptr(unsafe.Pointer(&data[0])) 207 | } 208 | retInt, _, _ := dll_sqlite3_bind_blob.Call( 209 | uintptr(stmt), 210 | uintptr(ord), 211 | pData, 212 | uintptr(len(data)), 213 | uintptr(SQLITE_TRANSIENT), 214 | ) 215 | return int(retInt) 216 | } 217 | 218 | func sqlite3_column_count(stmt sqlite3_stmt) (int) { 219 | retInt, _, _ := dll_sqlite3_column_count.Call(uintptr(stmt)) 220 | return int(retInt) 221 | } 222 | 223 | func sqlite3_column_name(stmt sqlite3_stmt, index int) (string) { 224 | msgPtr, _, _ := dll_sqlite3_column_name.Call( 225 | uintptr(stmt), 226 | uintptr(index), 227 | ) 228 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 229 | } 230 | 231 | func sqlite3_interrupt(db sqlite3) { 232 | dll_sqlite3_interrupt.Call(uintptr(db)) 233 | } 234 | 235 | func sqlite3_clear_bindings(stmt sqlite3_stmt){ 236 | dll_sqlite3_clear_bindings.Call(uintptr(stmt)) 237 | } 238 | 239 | func sqlite3_step(stmt sqlite3_stmt, rowid *int64, changes *int64) (int) { 240 | retInt, _, _ := dll_sqlite3_step.Call( 241 | uintptr(stmt), 242 | uintptr(unsafe.Pointer(rowid)), 243 | uintptr(unsafe.Pointer(changes)), 244 | ) 245 | return int(retInt) 246 | } 247 | 248 | func sqlite3_column_decltype(stmt sqlite3_stmt, index int) (string) { 249 | msgPtr, _, _ := dll_sqlite3_column_decltype.Call( 250 | uintptr(stmt), 251 | uintptr(index), 252 | ) 253 | if msgPtr == uintptr(0) { 254 | return "" 255 | } else { 256 | return BytePtrToString((*byte)(unsafe.Pointer(msgPtr))) 257 | } 258 | } 259 | 260 | func sqlite3_column_type(stmt sqlite3_stmt, index int) (int) { 261 | retInt, _, _ := dll_sqlite3_column_type.Call( 262 | uintptr(stmt), 263 | uintptr(index), 264 | ) 265 | return int(retInt) 266 | } 267 | 268 | func sqlite3_column_int64(stmt sqlite3_stmt, index int) (int64) { 269 | intPtr, _, _ := dll_sqlite3_column_int64.Call( 270 | uintptr(stmt), 271 | uintptr(index), 272 | ) 273 | return int64(intPtr) 274 | } 275 | 276 | func sqlite3_column_double(stmt sqlite3_stmt, index int) (float64) { 277 | intPtr, _, _ := dll_sqlite3_column_double.Call( 278 | uintptr(stmt), 279 | uintptr(index), 280 | ) 281 | return float64(intPtr) 282 | } 283 | 284 | func sqlite3_column_bytes(stmt sqlite3_stmt, index int) (int) { 285 | intPtr, _, _ := dll_sqlite3_column_bytes.Call( 286 | uintptr(stmt), 287 | uintptr(index), 288 | ) 289 | return int(intPtr) 290 | } 291 | 292 | func sqlite3_column_blob(stmt sqlite3_stmt, index int) ([]byte) { 293 | bytesPtr, _, _ := dll_sqlite3_column_blob.Call( 294 | uintptr(stmt), 295 | uintptr(index), 296 | ) 297 | 298 | n := sqlite3_column_bytes(stmt, index) 299 | 300 | slice := make([]byte, n) 301 | copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(bytesPtr))[0:n]) 302 | return slice 303 | } 304 | 305 | func sqlite3_column_text(stmt sqlite3_stmt, index int) (string) { 306 | bytesPtr, _, _ := dll_sqlite3_column_text.Call( 307 | uintptr(stmt), 308 | uintptr(index), 309 | ) 310 | 311 | n := sqlite3_column_bytes(stmt, index) 312 | 313 | slice := make([]byte, n) 314 | copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(bytesPtr))[0:n]) 315 | return string(slice) 316 | } 317 | -------------------------------------------------------------------------------- /sqlite3_rows.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "io" 14 | "time" 15 | "strings" 16 | "database/sql/driver" 17 | ) 18 | 19 | // Close the rows. 20 | func (rc *SQLiteRows) Close() error { 21 | if rc.s.closed { 22 | return nil 23 | } 24 | if rc.done != nil { 25 | close(rc.done) 26 | } 27 | if rc.cls { 28 | return rc.s.Close() 29 | } 30 | rv := sqlite3_reset(rc.s.s) 31 | if rv != SQLITE_OK { 32 | return rc.s.c.lastError() 33 | } 34 | return nil 35 | } 36 | 37 | // Columns return column names. 38 | func (rc *SQLiteRows) Columns() []string { 39 | if rc.nc != len(rc.cols) { 40 | rc.cols = make([]string, rc.nc) 41 | for i := 0; i < rc.nc; i++ { 42 | rc.cols[i] = sqlite3_column_name(rc.s.s, i) 43 | } 44 | } 45 | return rc.cols 46 | } 47 | 48 | // DeclTypes return column types. 49 | func (rc *SQLiteRows) DeclTypes() []string { 50 | if rc.decltype == nil { 51 | rc.decltype = make([]string, rc.nc) 52 | for i := 0; i < rc.nc; i++ { 53 | rc.decltype[i] = strings.ToLower(sqlite3_column_decltype(rc.s.s, i)) 54 | } 55 | } 56 | return rc.decltype 57 | } 58 | 59 | // Next move cursor to next. 60 | func (rc *SQLiteRows) Next(dest []driver.Value) error { 61 | var rowid, changes int64 62 | rv := sqlite3_step(rc.s.s, &rowid, &changes) 63 | if rv == SQLITE_DONE { 64 | return io.EOF 65 | } 66 | if rv != SQLITE_ROW { 67 | rv = sqlite3_reset(rc.s.s) 68 | if rv != SQLITE_OK { 69 | return rc.s.c.lastError() 70 | } 71 | return nil 72 | } 73 | 74 | rc.DeclTypes() 75 | 76 | for i := range dest { 77 | switch sqlite3_column_type(rc.s.s, i) { 78 | case SQLITE_INTEGER: 79 | val := sqlite3_column_int64(rc.s.s, i) 80 | switch rc.decltype[i] { 81 | case "timestamp", "datetime", "date": 82 | var t time.Time 83 | // Assume a millisecond unix timestamp if it's 13 digits -- too 84 | // large to be a reasonable timestamp in seconds. 85 | if val > 1e12 || val < -1e12 { 86 | val *= int64(time.Millisecond) // convert ms to nsec 87 | } else { 88 | val *= int64(time.Second) // convert sec to nsec 89 | } 90 | t = time.Unix(0, val).UTC() 91 | if rc.s.c.loc != nil { 92 | t = t.In(rc.s.c.loc) 93 | } 94 | dest[i] = t 95 | case "boolean": 96 | dest[i] = val > 0 97 | default: 98 | dest[i] = val 99 | } 100 | case SQLITE_FLOAT: 101 | dest[i] = sqlite3_column_double(rc.s.s, i) 102 | case SQLITE_BLOB: 103 | dest[i] = sqlite3_column_blob(rc.s.s, i) 104 | case SQLITE_NULL: 105 | dest[i] = nil 106 | case SQLITE_TEXT: 107 | var err error 108 | var timeVal time.Time 109 | 110 | s := sqlite3_column_text(rc.s.s, i) 111 | 112 | switch rc.decltype[i] { 113 | case "timestamp", "datetime", "date": 114 | var t time.Time 115 | s = strings.TrimSuffix(s, "Z") 116 | for _, format := range SQLiteTimestampFormats { 117 | if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil { 118 | t = timeVal 119 | break 120 | } 121 | } 122 | if err != nil { 123 | // The column is a time value, so return the zero time on parse failure. 124 | t = time.Time{} 125 | } 126 | if rc.s.c.loc != nil { 127 | t = t.In(rc.s.c.loc) 128 | } 129 | dest[i] = t 130 | default: 131 | dest[i] = []byte(s) 132 | } 133 | } 134 | } 135 | return nil 136 | } 137 | -------------------------------------------------------------------------------- /sqlite3_stmt.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "fmt" 14 | "time" 15 | "runtime" 16 | "database/sql/driver" 17 | "golang.org/x/net/context" 18 | ) 19 | 20 | // Close the statement. 21 | func (s *SQLiteStmt) Close() error { 22 | if s.closed { 23 | return nil 24 | } 25 | s.closed = true 26 | if s.c == nil || s.c.db == sqlite3(uintptr(0)) { 27 | return fmt.Errorf("sqlite statement with already closed database connection") 28 | } 29 | rv := sqlite3_finalize(s.s) 30 | if rv != SQLITE_OK { 31 | return s.c.lastError() 32 | } 33 | runtime.SetFinalizer(s, nil) 34 | return nil 35 | } 36 | 37 | // NumInput return a number of parameters. 38 | func (s *SQLiteStmt) NumInput() int { 39 | return sqlite3_bind_parameter_count(s.s) 40 | } 41 | 42 | func (s *SQLiteStmt) bind(args []namedValue) error { 43 | rv := sqlite3_reset(s.s) 44 | if rv != SQLITE_ROW && rv != SQLITE_OK && rv != SQLITE_DONE { 45 | return s.c.lastError() 46 | } 47 | 48 | for i, v := range args { 49 | if v.Name != "" { 50 | args[i].Ordinal = sqlite3_bind_parameter_index(s.s, v.Name) 51 | } 52 | } 53 | 54 | for _, arg := range args { 55 | n := arg.Ordinal 56 | switch v := arg.Value.(type) { 57 | case nil: 58 | rv = sqlite3_bind_null(s.s, n) 59 | case string: 60 | rv = sqlite3_bind_text(s.s, n, v) 61 | case int64: 62 | rv = sqlite3_bind_int64(s.s, n, v) 63 | case bool: 64 | if bool(v) { 65 | rv = sqlite3_bind_int(s.s, n, 1) 66 | } else { 67 | rv = sqlite3_bind_int(s.s, n, 0) 68 | } 69 | case float64: 70 | rv = sqlite3_bind_double(s.s, n, v) 71 | case []byte: 72 | rv = sqlite3_bind_blob(s.s, n, v) 73 | case time.Time: 74 | b := v.Format(SQLiteTimestampFormats[0]) 75 | rv = sqlite3_bind_text(s.s, n, b) 76 | } 77 | if rv != SQLITE_OK { 78 | return s.c.lastError() 79 | } 80 | } 81 | return nil 82 | } 83 | 84 | // Query the statement with arguments. Return records. 85 | func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) { 86 | list := make([]namedValue, len(args)) 87 | for i, v := range args { 88 | list[i] = namedValue{ 89 | Ordinal: i + 1, 90 | Value: v, 91 | } 92 | } 93 | return s.query(context.Background(), list) 94 | } 95 | 96 | func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows, error) { 97 | if err := s.bind(args); err != nil { 98 | return nil, err 99 | } 100 | 101 | rows := &SQLiteRows{ 102 | s: s, 103 | nc: sqlite3_column_count(s.s), 104 | cols: nil, 105 | decltype: nil, 106 | cls: s.cls, 107 | done: make(chan struct{}), 108 | } 109 | 110 | go func() { 111 | select { 112 | case <-ctx.Done(): 113 | sqlite3_interrupt(s.c.db) 114 | rows.Close() 115 | case <-rows.done: 116 | } 117 | }() 118 | 119 | return rows, nil 120 | } 121 | 122 | // LastInsertId teturn last inserted ID. 123 | func (r *SQLiteResult) LastInsertId() (int64, error) { 124 | return r.id, nil 125 | } 126 | 127 | // RowsAffected return how many rows affected. 128 | func (r *SQLiteResult) RowsAffected() (int64, error) { 129 | return r.changes, nil 130 | } 131 | 132 | // Exec execute the statement with arguments. Return result object. 133 | func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) { 134 | list := make([]namedValue, len(args)) 135 | for i, v := range args { 136 | list[i] = namedValue{ 137 | Ordinal: i + 1, 138 | Value: v, 139 | } 140 | } 141 | return s.exec(context.Background(), list) 142 | } 143 | 144 | func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result, error) { 145 | if err := s.bind(args); err != nil { 146 | sqlite3_reset(s.s) 147 | sqlite3_clear_bindings(s.s) 148 | return nil, err 149 | } 150 | 151 | done := make(chan struct{}) 152 | defer close(done) 153 | go func() { 154 | select { 155 | case <-ctx.Done(): 156 | sqlite3_interrupt(s.c.db) 157 | case <-done: 158 | } 159 | }() 160 | 161 | var rowid, changes int64 162 | rv := sqlite3_step(s.s, &rowid, &changes) 163 | if rv != SQLITE_ROW && rv != SQLITE_OK && rv != SQLITE_DONE { 164 | err := s.c.lastError() 165 | sqlite3_reset(s.s) 166 | sqlite3_clear_bindings(s.s) 167 | return nil, err 168 | } 169 | 170 | return &SQLiteResult{id: rowid, changes: changes}, nil 171 | } 172 | -------------------------------------------------------------------------------- /sqlite3_tx.go: -------------------------------------------------------------------------------- 1 | // +build windows,amd64 2 | // Copyright (C) 2016 Samuel Melrose . 3 | // 4 | // Based on work by Yasuhiro Matsumoto 5 | // https://github.com/mattn/go-sqlite3 6 | // 7 | // Use of this source code is governed by an MIT-style 8 | // license that can be found in the LICENSE file. 9 | 10 | package sqlite3 11 | 12 | import ( 13 | "golang.org/x/net/context" 14 | ) 15 | 16 | // Commit transaction. 17 | func (tx *SQLiteTx) Commit() error { 18 | _, err := tx.c.exec(context.Background(), "COMMIT", nil) 19 | if err != nil && err.(Error).Code == SQLITE_BUSY { 20 | // sqlite3 will leave the transaction open in this scenario. 21 | // However, database/sql considers the transaction complete once we 22 | // return from Commit() - we must clean up to honour its semantics. 23 | tx.c.exec(context.Background(), "ROLLBACK", nil) 24 | } 25 | return err 26 | } 27 | 28 | // Rollback transaction. 29 | func (tx *SQLiteTx) Rollback() error { 30 | _, err := tx.c.exec(context.Background(), "ROLLBACK", nil) 31 | return err 32 | } 33 | --------------------------------------------------------------------------------