├── .travis.yml ├── sqlite3_other.go ├── sqlite3_windows.go ├── README.mkd ├── example └── main.go ├── sqlite3.go ├── sqlite3_test.go └── sqlite3ext.h /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | -------------------------------------------------------------------------------- /sqlite3_other.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package sqlite 4 | 5 | /* 6 | #cgo pkg-config: sqlite3 7 | */ 8 | import "C" 9 | -------------------------------------------------------------------------------- /sqlite3_windows.go: -------------------------------------------------------------------------------- 1 | package sqlite 2 | 3 | /* 4 | #cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe 5 | #cgo LDFLAGS: -lmingwex -lmingw32 6 | */ 7 | import "C" 8 | -------------------------------------------------------------------------------- /README.mkd: -------------------------------------------------------------------------------- 1 | go-sqlite3 2 | ========== 3 | 4 | DESCRIPTION 5 | ----------- 6 | 7 | sqlite3 driver conforming to the built-in database/sql interface 8 | 9 | INSTALLATION 10 | ------------ 11 | 12 | It requires `pkg-config`. You can also confirm that permissions and dependancies are setup by running `pkg-config --cflags --libs sqlite3`. 13 | 14 | If you are using [Homebrew](http://mxcl.github.com/homebrew/) on Mac OS X, you can install with: 15 | 16 | brew install pkgconfig 17 | brew install sqlite3 18 | 19 | If you are using Ubuntu, you can install with: 20 | 21 | sudo apt-get install pkg-config 22 | sudo apt-get install sqlite3 23 | sudo apt-get install libsqlite3-dev 24 | 25 | If you are using Windows, you can get pkg-config from below. 26 | 27 | http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ 28 | 29 | Go does not support static linking for external C library; sqlite3 should be built as a shared library. If it runs on Windows, it needs dll. 30 | 31 | Finally, this package can be installed with the go get command: 32 | 33 | go get github.com/mattn/go-sqlite3 34 | 35 | LICENSE 36 | ------- 37 | 38 | MIT: http://mattn.mit-license.org/2012 39 | -------------------------------------------------------------------------------- /example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | _ "github.com/mattn/go-sqlite3" 7 | "os" 8 | ) 9 | 10 | func main() { 11 | os.Remove("./foo.db") 12 | 13 | db, err := sql.Open("sqlite3", "./foo.db") 14 | if err != nil { 15 | fmt.Println(err) 16 | return 17 | } 18 | defer db.Close() 19 | 20 | sqls := []string{ 21 | "create table foo (id integer not null primary key, name text)", 22 | "delete from foo", 23 | } 24 | for _, sql := range sqls { 25 | _, err = db.Exec(sql) 26 | if err != nil { 27 | fmt.Printf("%q: %s\n", err, sql) 28 | return 29 | } 30 | } 31 | 32 | tx, err := db.Begin() 33 | if err != nil { 34 | fmt.Println(err) 35 | return 36 | } 37 | stmt, err := tx.Prepare("insert into foo(id, name) values(?, ?)") 38 | if err != nil { 39 | fmt.Println(err) 40 | return 41 | } 42 | defer stmt.Close() 43 | for i := 0; i < 100; i++ { 44 | _, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i)) 45 | if err != nil { 46 | fmt.Println(err) 47 | return 48 | } 49 | } 50 | tx.Commit() 51 | 52 | rows, err := db.Query("select id, name from foo") 53 | if err != nil { 54 | fmt.Println(err) 55 | return 56 | } 57 | defer rows.Close() 58 | for rows.Next() { 59 | var id int 60 | var name string 61 | rows.Scan(&id, &name) 62 | println(id, name) 63 | } 64 | rows.Close() 65 | 66 | stmt, err = db.Prepare("select name from foo where id = ?") 67 | if err != nil { 68 | fmt.Println(err) 69 | return 70 | } 71 | defer stmt.Close() 72 | var name string 73 | err = stmt.QueryRow("3").Scan(&name) 74 | if err != nil { 75 | fmt.Println(err) 76 | return 77 | } 78 | println(name) 79 | } 80 | -------------------------------------------------------------------------------- /sqlite3.go: -------------------------------------------------------------------------------- 1 | package sqlite 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | 8 | static int 9 | _sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) { 10 | return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT); 11 | } 12 | 13 | static int 14 | _sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) { 15 | return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT); 16 | } 17 | */ 18 | import "C" 19 | import ( 20 | "database/sql" 21 | "database/sql/driver" 22 | "errors" 23 | "io" 24 | "strings" 25 | "time" 26 | "unsafe" 27 | ) 28 | 29 | const SQLiteTimestampFormat = "2006-01-02 15:04:05" 30 | const SQLiteDateFormat = "2006-01-02" 31 | const SQLiteDatetimeFormat = "2006-01-02 15:04:05.000" 32 | 33 | func init() { 34 | sql.Register("sqlite3", &SQLiteDriver{}) 35 | } 36 | 37 | type SQLiteDriver struct { 38 | } 39 | 40 | type SQLiteConn struct { 41 | db *C.sqlite3 42 | } 43 | 44 | type SQLiteTx struct { 45 | c *SQLiteConn 46 | } 47 | 48 | func (tx *SQLiteTx) Commit() error { 49 | if err := tx.c.exec("COMMIT"); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | func (tx *SQLiteTx) Rollback() error { 56 | if err := tx.c.exec("ROLLBACK"); err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | 62 | func (c *SQLiteConn) exec(cmd string) error { 63 | pcmd := C.CString(cmd) 64 | defer C.free(unsafe.Pointer(pcmd)) 65 | rv := C.sqlite3_exec(c.db, pcmd, nil, nil, nil) 66 | if rv != C.SQLITE_OK { 67 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 68 | } 69 | return nil 70 | } 71 | 72 | func (c *SQLiteConn) Begin() (driver.Tx, error) { 73 | if err := c.exec("BEGIN"); err != nil { 74 | return nil, err 75 | } 76 | return &SQLiteTx{c}, nil 77 | } 78 | 79 | func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { 80 | if C.sqlite3_threadsafe() == 0 { 81 | return nil, errors.New("sqlite library was not compiled for thread-safe operation") 82 | } 83 | 84 | var db *C.sqlite3 85 | name := C.CString(dsn) 86 | defer C.free(unsafe.Pointer(name)) 87 | rv := C.sqlite3_open_v2(name, &db, 88 | C.SQLITE_OPEN_FULLMUTEX| 89 | C.SQLITE_OPEN_READWRITE| 90 | C.SQLITE_OPEN_CREATE, 91 | nil) 92 | if rv != 0 { 93 | return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) 94 | } 95 | if db == nil { 96 | return nil, errors.New("sqlite succeeded without returning a database") 97 | } 98 | 99 | rv = C.sqlite3_busy_timeout(db, 5000) 100 | if rv != C.SQLITE_OK { 101 | return nil, errors.New(C.GoString(C.sqlite3_errmsg(db))) 102 | } 103 | 104 | return &SQLiteConn{db}, nil 105 | } 106 | 107 | func (c *SQLiteConn) Close() error { 108 | s := C.sqlite3_next_stmt(c.db, nil) 109 | for s != nil { 110 | C.sqlite3_finalize(s) 111 | s = C.sqlite3_next_stmt(c.db, nil) 112 | } 113 | rv := C.sqlite3_close(c.db) 114 | if rv != C.SQLITE_OK { 115 | return errors.New("sqlite succeeded without returning a database") 116 | } 117 | c.db = nil 118 | return nil 119 | } 120 | 121 | type SQLiteStmt struct { 122 | c *SQLiteConn 123 | s *C.sqlite3_stmt 124 | t string 125 | closed bool 126 | } 127 | 128 | func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) { 129 | pquery := C.CString(query) 130 | defer C.free(unsafe.Pointer(pquery)) 131 | var s *C.sqlite3_stmt 132 | var perror *C.char 133 | rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &perror) 134 | if rv != C.SQLITE_OK { 135 | return nil, errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 136 | } 137 | var t string 138 | if perror != nil && C.strlen(perror) > 0 { 139 | t = C.GoString(perror) 140 | } 141 | return &SQLiteStmt{c: c, s: s, t: t}, nil 142 | } 143 | 144 | func (s *SQLiteStmt) Close() error { 145 | if s.closed { 146 | return nil 147 | } 148 | s.closed = true 149 | rv := C.sqlite3_finalize(s.s) 150 | if rv != C.SQLITE_OK { 151 | return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) 152 | } 153 | return nil 154 | } 155 | 156 | func (s *SQLiteStmt) NumInput() int { 157 | return int(C.sqlite3_bind_parameter_count(s.s)) 158 | } 159 | 160 | func (s *SQLiteStmt) bind(args []driver.Value) error { 161 | rv := C.sqlite3_reset(s.s) 162 | if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { 163 | return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) 164 | } 165 | 166 | for i, v := range args { 167 | n := C.int(i + 1) 168 | switch v := v.(type) { 169 | case nil: 170 | rv = C.sqlite3_bind_null(s.s, n) 171 | case string: 172 | if len(v) == 0 { 173 | b := []byte{0} 174 | rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0)) 175 | } else { 176 | b := []byte(v) 177 | rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 178 | } 179 | case int: 180 | rv = C.sqlite3_bind_int(s.s, n, C.int(v)) 181 | case int64: 182 | rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v)) 183 | case byte: 184 | rv = C.sqlite3_bind_int(s.s, n, C.int(v)) 185 | case bool: 186 | if bool(v) { 187 | rv = C.sqlite3_bind_int(s.s, n, 1) 188 | } else { 189 | rv = C.sqlite3_bind_int(s.s, n, 0) 190 | } 191 | case float32: 192 | rv = C.sqlite3_bind_double(s.s, n, C.double(v)) 193 | case float64: 194 | rv = C.sqlite3_bind_double(s.s, n, C.double(v)) 195 | case []byte: 196 | var p *byte 197 | if len(v) > 0 { 198 | p = &v[0] 199 | } 200 | rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(p), C.int(len(v))) 201 | case time.Time: 202 | b := []byte(v.Format(SQLiteTimestampFormat)) 203 | rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 204 | } 205 | if rv != C.SQLITE_OK { 206 | return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) 207 | } 208 | } 209 | return nil 210 | } 211 | 212 | func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) { 213 | if err := s.bind(args); err != nil { 214 | return nil, err 215 | } 216 | return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil}, nil 217 | } 218 | 219 | type SQLiteResult struct { 220 | s *SQLiteStmt 221 | } 222 | 223 | func (r *SQLiteResult) LastInsertId() (int64, error) { 224 | var rr int64 225 | rr = int64(C.sqlite3_last_insert_rowid(r.s.c.db)) 226 | return rr, nil 227 | } 228 | 229 | func (r *SQLiteResult) RowsAffected() (int64, error) { 230 | return int64(C.sqlite3_changes(r.s.c.db)), nil 231 | } 232 | 233 | func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) { 234 | if err := s.bind(args); err != nil { 235 | return nil, err 236 | } 237 | rv := C.sqlite3_step(s.s) 238 | if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { 239 | return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db))) 240 | } 241 | return &SQLiteResult{s}, nil 242 | } 243 | 244 | type SQLiteRows struct { 245 | s *SQLiteStmt 246 | nc int 247 | cols []string 248 | decltype []string 249 | } 250 | 251 | func (rc *SQLiteRows) Close() error { 252 | rv := C.sqlite3_reset(rc.s.s) 253 | if rv != C.SQLITE_OK { 254 | return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) 255 | } 256 | return nil 257 | } 258 | 259 | func (rc *SQLiteRows) Columns() []string { 260 | if rc.nc != len(rc.cols) { 261 | rc.cols = make([]string, rc.nc) 262 | for i := 0; i < rc.nc; i++ { 263 | rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i))) 264 | } 265 | } 266 | return rc.cols 267 | } 268 | 269 | func (rc *SQLiteRows) Next(dest []driver.Value) error { 270 | rv := C.sqlite3_step(rc.s.s) 271 | if rv == C.SQLITE_DONE { 272 | return io.EOF 273 | } 274 | if rv != C.SQLITE_ROW { 275 | return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db))) 276 | } 277 | 278 | if rc.decltype == nil { 279 | rc.decltype = make([]string, rc.nc) 280 | for i := 0; i < rc.nc; i++ { 281 | rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) 282 | } 283 | } 284 | 285 | for i := range dest { 286 | switch C.sqlite3_column_type(rc.s.s, C.int(i)) { 287 | case C.SQLITE_INTEGER: 288 | val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) 289 | switch rc.decltype[i] { 290 | case "timestamp": 291 | dest[i] = time.Unix(val, 0) 292 | case "boolean": 293 | dest[i] = val > 0 294 | default: 295 | dest[i] = val 296 | } 297 | case C.SQLITE_FLOAT: 298 | dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i))) 299 | case C.SQLITE_BLOB: 300 | n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) 301 | p := C.sqlite3_column_blob(rc.s.s, C.int(i)) 302 | switch dest[i].(type) { 303 | case sql.RawBytes: 304 | dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n] 305 | default: 306 | slice := make([]byte, n) 307 | copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) 308 | dest[i] = slice 309 | } 310 | case C.SQLITE_NULL: 311 | dest[i] = nil 312 | case C.SQLITE_TEXT: 313 | var err error 314 | s := C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i))))) 315 | if rc.decltype[i] == "timestamp" || rc.decltype[i] == "datetime" { 316 | dest[i], err = time.Parse(SQLiteTimestampFormat, s) 317 | if err != nil { 318 | dest[i], err = time.Parse(SQLiteDateFormat, s) 319 | if err != nil { 320 | dest[i], err = time.Parse(SQLiteDatetimeFormat, s) 321 | if err != nil { 322 | return err 323 | } 324 | } 325 | } 326 | } else { 327 | dest[i] = s 328 | } 329 | } 330 | } 331 | return nil 332 | } 333 | -------------------------------------------------------------------------------- /sqlite3_test.go: -------------------------------------------------------------------------------- 1 | package sqlite 2 | 3 | import ( 4 | "database/sql" 5 | "os" 6 | "strings" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | func TestOpen(t *testing.T) { 12 | db, err := sql.Open("sqlite3", "./foo.db") 13 | if err != nil { 14 | t.Fatal("Failed to open database:", err) 15 | } 16 | defer os.Remove("./foo.db") 17 | defer db.Close() 18 | 19 | _, err = db.Exec("drop table foo") 20 | _, err = db.Exec("create table foo (id integer)") 21 | if err != nil { 22 | t.Fatal("Failed to create table:", err) 23 | } 24 | 25 | if stat, err := os.Stat("./foo.db"); err != nil || stat.IsDir() { 26 | t.Error("Failed to create ./foo.db") 27 | } 28 | } 29 | 30 | func TestInsert(t *testing.T) { 31 | db, err := sql.Open("sqlite3", "./foo.db") 32 | if err != nil { 33 | t.Fatal("Failed to open database:", err) 34 | } 35 | defer os.Remove("./foo.db") 36 | defer db.Close() 37 | 38 | _, err = db.Exec("drop table foo") 39 | _, err = db.Exec("create table foo (id integer)") 40 | if err != nil { 41 | t.Fatal("Failed to create table:", err) 42 | } 43 | 44 | res, err := db.Exec("insert into foo(id) values(123)") 45 | if err != nil { 46 | t.Fatal("Failed to insert record:", err) 47 | } 48 | affected, _ := res.RowsAffected() 49 | if affected != 1 { 50 | t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 51 | } 52 | 53 | rows, err := db.Query("select id from foo") 54 | if err != nil { 55 | t.Fatal("Failed to select records:", err) 56 | } 57 | defer rows.Close() 58 | 59 | rows.Next() 60 | 61 | var result int 62 | rows.Scan(&result) 63 | if result != 123 { 64 | t.Errorf("Fetched %q; expected %q", 123, result) 65 | } 66 | } 67 | 68 | func TestUpdate(t *testing.T) { 69 | db, err := sql.Open("sqlite3", "./foo.db") 70 | if err != nil { 71 | t.Fatal("Failed to open database:", err) 72 | } 73 | defer os.Remove("./foo.db") 74 | defer db.Close() 75 | 76 | _, err = db.Exec("drop table foo") 77 | _, err = db.Exec("create table foo (id integer)") 78 | if err != nil { 79 | t.Fatal("Failed to create table:", err) 80 | } 81 | 82 | res, err := db.Exec("insert into foo(id) values(123)") 83 | if err != nil { 84 | t.Fatal("Failed to insert record:", err) 85 | } 86 | expected, err := res.LastInsertId() 87 | if err != nil { 88 | t.Fatal("Failed to get LastInsertId:", err) 89 | } 90 | affected, _ := res.RowsAffected() 91 | if err != nil { 92 | t.Fatal("Failed to get RowsAffected:", err) 93 | } 94 | if affected != 1 { 95 | t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 96 | } 97 | 98 | res, err = db.Exec("update foo set id = 234") 99 | if err != nil { 100 | t.Fatal("Failed to update record:", err) 101 | } 102 | lastId, err := res.LastInsertId() 103 | if err != nil { 104 | t.Fatal("Failed to get LastInsertId:", err) 105 | } 106 | if expected != lastId { 107 | t.Errorf("Expected %q for last Id, but %q:", expected, lastId) 108 | } 109 | affected, _ = res.RowsAffected() 110 | if err != nil { 111 | t.Fatal("Failed to get RowsAffected:", err) 112 | } 113 | if affected != 1 { 114 | t.Fatalf("Expected %d for affected rows, but %d:", 1, affected) 115 | } 116 | 117 | rows, err := db.Query("select id from foo") 118 | if err != nil { 119 | t.Fatal("Failed to select records:", err) 120 | } 121 | defer rows.Close() 122 | 123 | rows.Next() 124 | 125 | var result int 126 | rows.Scan(&result) 127 | if result != 234 { 128 | t.Errorf("Fetched %q; expected %q", 234, result) 129 | } 130 | } 131 | 132 | func TestDelete(t *testing.T) { 133 | db, err := sql.Open("sqlite3", "./foo.db") 134 | if err != nil { 135 | t.Fatal("Failed to open database:", err) 136 | } 137 | defer os.Remove("./foo.db") 138 | defer db.Close() 139 | 140 | _, err = db.Exec("drop table foo") 141 | _, err = db.Exec("create table foo (id integer)") 142 | if err != nil { 143 | t.Fatal("Failed to create table:", err) 144 | } 145 | 146 | res, err := db.Exec("insert into foo(id) values(123)") 147 | if err != nil { 148 | t.Fatal("Failed to insert record:", err) 149 | } 150 | expected, err := res.LastInsertId() 151 | if err != nil { 152 | t.Fatal("Failed to get LastInsertId:", err) 153 | } 154 | affected, err := res.RowsAffected() 155 | if err != nil { 156 | t.Fatal("Failed to get RowsAffected:", err) 157 | } 158 | if affected != 1 { 159 | t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) 160 | } 161 | 162 | res, err = db.Exec("delete from foo where id = 123") 163 | if err != nil { 164 | t.Fatal("Failed to delete record:", err) 165 | } 166 | lastId, err := res.LastInsertId() 167 | if err != nil { 168 | t.Fatal("Failed to get LastInsertId:", err) 169 | } 170 | if expected != lastId { 171 | t.Errorf("Expected %q for last Id, but %q:", expected, lastId) 172 | } 173 | affected, err = res.RowsAffected() 174 | if err != nil { 175 | t.Fatal("Failed to get RowsAffected:", err) 176 | } 177 | if affected != 1 { 178 | t.Errorf("Expected %d for cout of affected rows, but %q:", 1, affected) 179 | } 180 | 181 | rows, err := db.Query("select id from foo") 182 | if err != nil { 183 | t.Fatal("Failed to select records:", err) 184 | } 185 | defer rows.Close() 186 | 187 | if rows.Next() { 188 | t.Error("Fetched row but expected not rows") 189 | } 190 | } 191 | 192 | func TestBooleanRoundtrip(t *testing.T) { 193 | db, err := sql.Open("sqlite3", "./foo.db") 194 | if err != nil { 195 | t.Fatal("Failed to open database:", err) 196 | } 197 | defer os.Remove("./foo.db") 198 | defer db.Close() 199 | 200 | _, err = db.Exec("DROP TABLE foo") 201 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, value BOOL)") 202 | if err != nil { 203 | t.Fatal("Failed to create table:", err) 204 | } 205 | 206 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(1, ?)", true) 207 | if err != nil { 208 | t.Fatal("Failed to insert true value:", err) 209 | } 210 | 211 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(2, ?)", false) 212 | if err != nil { 213 | t.Fatal("Failed to insert false value:", err) 214 | } 215 | 216 | rows, err := db.Query("SELECT id, value FROM foo") 217 | if err != nil { 218 | t.Fatal("Unable to query foo table:", err) 219 | } 220 | defer rows.Close() 221 | 222 | for rows.Next() { 223 | var id int 224 | var value bool 225 | 226 | if err := rows.Scan(&id, &value); err != nil { 227 | t.Error("Unable to scan results:", err) 228 | continue 229 | } 230 | 231 | if id == 1 && !value { 232 | t.Error("Value for id 1 should be true, not false") 233 | 234 | } else if id == 2 && value { 235 | t.Error("Value for id 2 should be false, not true") 236 | } 237 | } 238 | } 239 | 240 | func TestTimestamp(t *testing.T) { 241 | db, err := sql.Open("sqlite3", "./foo.db") 242 | if err != nil { 243 | t.Fatal("Failed to open database:", err) 244 | } 245 | defer os.Remove("./foo.db") 246 | defer db.Close() 247 | 248 | _, err = db.Exec("DROP TABLE foo") 249 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, ts timeSTAMP)") 250 | if err != nil { 251 | t.Fatal("Failed to create table:", err) 252 | } 253 | 254 | timestamp1 := time.Date(2012, time.April, 6, 22, 50, 0, 0, time.UTC) 255 | _, err = db.Exec("INSERT INTO foo(id, ts) VALUES(1, ?)", timestamp1) 256 | if err != nil { 257 | t.Fatal("Failed to insert timestamp:", err) 258 | } 259 | 260 | timestamp2 := time.Date(2012, time.April, 6, 23, 22, 0, 0, time.UTC) 261 | _, err = db.Exec("INSERT INTO foo(id, ts) VALUES(2, ?)", timestamp2.Unix()) 262 | if err != nil { 263 | t.Fatal("Failed to insert timestamp:", err) 264 | } 265 | 266 | _, err = db.Exec("INSERT INTO foo(id, ts) VALUES(3, ?)", "nonsense") 267 | if err != nil { 268 | t.Fatal("Failed to insert nonsense:", err) 269 | } 270 | 271 | rows, err := db.Query("SELECT id, ts FROM foo ORDER BY id ASC") 272 | if err != nil { 273 | t.Fatal("Unable to query foo table:", err) 274 | } 275 | defer rows.Close() 276 | 277 | seen := 0 278 | for rows.Next() { 279 | var id int 280 | var ts time.Time 281 | 282 | if err := rows.Scan(&id, &ts); err != nil { 283 | t.Error("Unable to scan results:", err) 284 | continue 285 | } 286 | 287 | if id == 1 { 288 | seen += 1 289 | if !timestamp1.Equal(ts) { 290 | t.Errorf("Value for id 1 should be %v, not %v", timestamp1, ts) 291 | } 292 | } 293 | 294 | if id == 2 { 295 | seen += 1 296 | if !timestamp2.Equal(ts) { 297 | t.Errorf("Value for id 2 should be %v, not %v", timestamp2, ts) 298 | } 299 | } 300 | } 301 | 302 | if seen != 2 { 303 | t.Error("Expected to see two valid timestamps") 304 | } 305 | 306 | // make sure "nonsense" triggered an error 307 | err = rows.Err() 308 | if err == nil || !strings.Contains(err.Error(), "cannot parse \"nonsense\"") { 309 | t.Error("Expected error from \"nonsense\" timestamp") 310 | } 311 | } 312 | 313 | func TestBoolean(t *testing.T) { 314 | db, err := sql.Open("sqlite3", "./foo.db") 315 | if err != nil { 316 | t.Fatal("Failed to open database:", err) 317 | } 318 | 319 | defer os.Remove("./foo.db") 320 | defer db.Close() 321 | 322 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, fbool BOOLEAN)") 323 | if err != nil { 324 | t.Fatal("Failed to create table:", err) 325 | } 326 | 327 | bool1 := true 328 | _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(1, ?)", bool1) 329 | if err != nil { 330 | t.Fatal("Failed to insert boolean:", err) 331 | } 332 | 333 | bool2 := false 334 | _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(2, ?)", bool2) 335 | if err != nil { 336 | t.Fatal("Failed to insert boolean:", err) 337 | } 338 | 339 | bool3 := "nonsense" 340 | _, err = db.Exec("INSERT INTO foo(id, fbool) VALUES(3, ?)", bool3) 341 | if err != nil { 342 | t.Fatal("Failed to insert nonsense:", err) 343 | } 344 | 345 | rows, err := db.Query("SELECT id, fbool FROM foo where fbool = ?", bool1) 346 | if err != nil { 347 | t.Fatal("Unable to query foo table:", err) 348 | } 349 | counter := 0 350 | 351 | var id int 352 | var fbool bool 353 | 354 | for rows.Next() { 355 | if err := rows.Scan(&id, &fbool); err != nil { 356 | t.Fatal("Unable to scan results:", err) 357 | } 358 | counter++ 359 | } 360 | 361 | if counter != 1 { 362 | t.Fatalf("Expected 1 row but %v", counter) 363 | } 364 | 365 | if id != 1 && fbool != true { 366 | t.Fatalf("Value for id 1 should be %v, not %v", bool1, fbool) 367 | } 368 | 369 | rows, err = db.Query("SELECT id, fbool FROM foo where fbool = ?", bool2) 370 | if err != nil { 371 | t.Fatal("Unable to query foo table:", err) 372 | } 373 | 374 | counter = 0 375 | 376 | for rows.Next() { 377 | if err := rows.Scan(&id, &fbool); err != nil { 378 | t.Fatal("Unable to scan results:", err) 379 | } 380 | counter++ 381 | } 382 | 383 | if counter != 1 { 384 | t.Fatalf("Expected 1 row but %v", counter) 385 | } 386 | 387 | if id != 2 && fbool != false { 388 | t.Fatalf("Value for id 2 should be %v, not %v", bool2, fbool) 389 | } 390 | 391 | // make sure "nonsense" triggered an error 392 | rows, err = db.Query("SELECT id, fbool FROM foo where id=?;", 3) 393 | if err != nil { 394 | t.Fatal("Unable to query foo table:", err) 395 | } 396 | 397 | rows.Next() 398 | err = rows.Scan(&id, &fbool) 399 | if err == nil { 400 | t.Error("Expected error from \"nonsense\" bool") 401 | } 402 | } 403 | 404 | func TestDateOnlyTimestamp(t *testing.T) { 405 | // make sure that timestamps without times are extractable. these are generated when 406 | // e.g., you use the sqlite `DATE()` built-in. 407 | 408 | db, er := sql.Open("sqlite3", "db.sqlite") 409 | if er != nil { 410 | t.Fatal(er) 411 | } 412 | defer func() { 413 | db.Close() 414 | os.Remove("db.sqlite") 415 | }() 416 | 417 | _, er = db.Exec(` 418 | CREATE TABLE test 419 | ( entry_id INTEGER PRIMARY KEY AUTOINCREMENT 420 | , entry_published TIMESTAMP NOT NULL 421 | ) 422 | `) 423 | if er != nil { 424 | t.Fatal(er) 425 | } 426 | 427 | _, er = db.Exec(` 428 | INSERT INTO test VALUES ( 1, '2012-11-04') 429 | `) 430 | if er != nil { 431 | t.Fatal(er) 432 | } 433 | 434 | rows, er := db.Query("SELECT entry_id, entry_published FROM test") 435 | if er != nil { 436 | t.Fatal(er) 437 | } 438 | defer rows.Close() 439 | 440 | if !rows.Next() { 441 | if er := rows.Err(); er != nil { 442 | t.Fatal(er) 443 | } else { 444 | t.Fatalf("Unable to extract row containing date-only timestamp") 445 | } 446 | } 447 | 448 | var entryId int64 449 | var entryPublished time.Time 450 | 451 | if er := rows.Scan(&entryId, &entryPublished); er != nil { 452 | t.Fatal(er) 453 | } 454 | 455 | if entryId != 1 { 456 | t.Errorf("EntryId does not match inserted value") 457 | } 458 | 459 | if entryPublished.Year() != 2012 || entryPublished.Month() != 11 || entryPublished.Day() != 4 { 460 | t.Errorf("Extracted time does not match inserted value") 461 | } 462 | } 463 | 464 | func TestDatetime(t *testing.T) { 465 | db, err := sql.Open("sqlite3", "./datetime.db") 466 | if err != nil { 467 | t.Fatal("Failed to open database:", err) 468 | } 469 | 470 | defer func() { 471 | db.Close() 472 | os.Remove("./datetime.db") 473 | }() 474 | 475 | _, err = db.Exec("DROP TABLE datetimetest") 476 | _, err = db.Exec(` 477 | CREATE TABLE datetimetest 478 | ( entry_id INTEGER 479 | , my_datetime DATETIME 480 | ) 481 | `) 482 | 483 | if err != nil { 484 | t.Fatal("Failed to create table:", err) 485 | } 486 | datetime := "2006-01-02 15:04:05.003" 487 | _, err = db.Exec(` 488 | INSERT INTO datetimetest(entry_id, my_datetime) 489 | VALUES(1, ?)`, datetime) 490 | if err != nil { 491 | t.Fatal("Failed to insert datetime:", err) 492 | } 493 | 494 | rows, err := db.Query( 495 | "SELECT entry_id, my_datetime FROM datetimetest ORDER BY entry_id ASC") 496 | if err != nil { 497 | t.Fatal("Unable to query datetimetest table:", err) 498 | } 499 | defer rows.Close() 500 | 501 | if !rows.Next() { 502 | if er := rows.Err(); er != nil { 503 | t.Fatal(er) 504 | } else { 505 | t.Fatalf("Unable to extract row containing datetime") 506 | } 507 | } 508 | 509 | var entryId int 510 | var myDatetime time.Time 511 | 512 | if err := rows.Scan(&entryId, &myDatetime); err != nil { 513 | t.Error("Unable to scan results:", err) 514 | } 515 | 516 | if entryId != 1 { 517 | t.Errorf("EntryId does not match inserted value") 518 | } 519 | 520 | if myDatetime.Year() != 2006 || 521 | myDatetime.Month() != 1 || 522 | myDatetime.Day() != 2 || 523 | myDatetime.Hour() != 15 || 524 | myDatetime.Minute() != 4 || 525 | myDatetime.Second() != 5 || 526 | myDatetime.Nanosecond() != 3000000 { 527 | t.Errorf("Extracted time does not match inserted value") 528 | } 529 | 530 | } 531 | -------------------------------------------------------------------------------- /sqlite3ext.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2006 June 7 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This header file defines the SQLite interface for use by 13 | ** shared libraries that want to be imported as extensions into 14 | ** an SQLite instance. Shared libraries that intend to be loaded 15 | ** as extensions by SQLite should #include this file instead of 16 | ** sqlite3.h. 17 | */ 18 | #ifndef _SQLITE3EXT_H_ 19 | #define _SQLITE3EXT_H_ 20 | #include "sqlite3.h" 21 | 22 | typedef struct sqlite3_api_routines sqlite3_api_routines; 23 | 24 | /* 25 | ** The following structure holds pointers to all of the SQLite API 26 | ** routines. 27 | ** 28 | ** WARNING: In order to maintain backwards compatibility, add new 29 | ** interfaces to the end of this structure only. If you insert new 30 | ** interfaces in the middle of this structure, then older different 31 | ** versions of SQLite will not be able to load each others' shared 32 | ** libraries! 33 | */ 34 | struct sqlite3_api_routines { 35 | void * (*aggregate_context)(sqlite3_context*,int nBytes); 36 | int (*aggregate_count)(sqlite3_context*); 37 | int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); 38 | int (*bind_double)(sqlite3_stmt*,int,double); 39 | int (*bind_int)(sqlite3_stmt*,int,int); 40 | int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); 41 | int (*bind_null)(sqlite3_stmt*,int); 42 | int (*bind_parameter_count)(sqlite3_stmt*); 43 | int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); 44 | const char * (*bind_parameter_name)(sqlite3_stmt*,int); 45 | int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); 46 | int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); 47 | int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); 48 | int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); 49 | int (*busy_timeout)(sqlite3*,int ms); 50 | int (*changes)(sqlite3*); 51 | int (*close)(sqlite3*); 52 | int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, 53 | int eTextRep,const char*)); 54 | int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, 55 | int eTextRep,const void*)); 56 | const void * (*column_blob)(sqlite3_stmt*,int iCol); 57 | int (*column_bytes)(sqlite3_stmt*,int iCol); 58 | int (*column_bytes16)(sqlite3_stmt*,int iCol); 59 | int (*column_count)(sqlite3_stmt*pStmt); 60 | const char * (*column_database_name)(sqlite3_stmt*,int); 61 | const void * (*column_database_name16)(sqlite3_stmt*,int); 62 | const char * (*column_decltype)(sqlite3_stmt*,int i); 63 | const void * (*column_decltype16)(sqlite3_stmt*,int); 64 | double (*column_double)(sqlite3_stmt*,int iCol); 65 | int (*column_int)(sqlite3_stmt*,int iCol); 66 | sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); 67 | const char * (*column_name)(sqlite3_stmt*,int); 68 | const void * (*column_name16)(sqlite3_stmt*,int); 69 | const char * (*column_origin_name)(sqlite3_stmt*,int); 70 | const void * (*column_origin_name16)(sqlite3_stmt*,int); 71 | const char * (*column_table_name)(sqlite3_stmt*,int); 72 | const void * (*column_table_name16)(sqlite3_stmt*,int); 73 | const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); 74 | const void * (*column_text16)(sqlite3_stmt*,int iCol); 75 | int (*column_type)(sqlite3_stmt*,int iCol); 76 | sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); 77 | void * (*commit_hook)(sqlite3*,int(*)(void*),void*); 78 | int (*complete)(const char*sql); 79 | int (*complete16)(const void*sql); 80 | int (*create_collation)(sqlite3*,const char*,int,void*, 81 | int(*)(void*,int,const void*,int,const void*)); 82 | int (*create_collation16)(sqlite3*,const void*,int,void*, 83 | int(*)(void*,int,const void*,int,const void*)); 84 | int (*create_function)(sqlite3*,const char*,int,int,void*, 85 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 86 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 87 | void (*xFinal)(sqlite3_context*)); 88 | int (*create_function16)(sqlite3*,const void*,int,int,void*, 89 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 90 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 91 | void (*xFinal)(sqlite3_context*)); 92 | int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); 93 | int (*data_count)(sqlite3_stmt*pStmt); 94 | sqlite3 * (*db_handle)(sqlite3_stmt*); 95 | int (*declare_vtab)(sqlite3*,const char*); 96 | int (*enable_shared_cache)(int); 97 | int (*errcode)(sqlite3*db); 98 | const char * (*errmsg)(sqlite3*); 99 | const void * (*errmsg16)(sqlite3*); 100 | int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); 101 | int (*expired)(sqlite3_stmt*); 102 | int (*finalize)(sqlite3_stmt*pStmt); 103 | void (*free)(void*); 104 | void (*free_table)(char**result); 105 | int (*get_autocommit)(sqlite3*); 106 | void * (*get_auxdata)(sqlite3_context*,int); 107 | int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); 108 | int (*global_recover)(void); 109 | void (*interruptx)(sqlite3*); 110 | sqlite_int64 (*last_insert_rowid)(sqlite3*); 111 | const char * (*libversion)(void); 112 | int (*libversion_number)(void); 113 | void *(*malloc)(int); 114 | char * (*mprintf)(const char*,...); 115 | int (*open)(const char*,sqlite3**); 116 | int (*open16)(const void*,sqlite3**); 117 | int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); 118 | int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); 119 | void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); 120 | void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); 121 | void *(*realloc)(void*,int); 122 | int (*reset)(sqlite3_stmt*pStmt); 123 | void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); 124 | void (*result_double)(sqlite3_context*,double); 125 | void (*result_error)(sqlite3_context*,const char*,int); 126 | void (*result_error16)(sqlite3_context*,const void*,int); 127 | void (*result_int)(sqlite3_context*,int); 128 | void (*result_int64)(sqlite3_context*,sqlite_int64); 129 | void (*result_null)(sqlite3_context*); 130 | void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); 131 | void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); 132 | void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); 133 | void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); 134 | void (*result_value)(sqlite3_context*,sqlite3_value*); 135 | void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); 136 | int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, 137 | const char*,const char*),void*); 138 | void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); 139 | char * (*snprintf)(int,char*,const char*,...); 140 | int (*step)(sqlite3_stmt*); 141 | int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, 142 | char const**,char const**,int*,int*,int*); 143 | void (*thread_cleanup)(void); 144 | int (*total_changes)(sqlite3*); 145 | void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); 146 | int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); 147 | void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, 148 | sqlite_int64),void*); 149 | void * (*user_data)(sqlite3_context*); 150 | const void * (*value_blob)(sqlite3_value*); 151 | int (*value_bytes)(sqlite3_value*); 152 | int (*value_bytes16)(sqlite3_value*); 153 | double (*value_double)(sqlite3_value*); 154 | int (*value_int)(sqlite3_value*); 155 | sqlite_int64 (*value_int64)(sqlite3_value*); 156 | int (*value_numeric_type)(sqlite3_value*); 157 | const unsigned char * (*value_text)(sqlite3_value*); 158 | const void * (*value_text16)(sqlite3_value*); 159 | const void * (*value_text16be)(sqlite3_value*); 160 | const void * (*value_text16le)(sqlite3_value*); 161 | int (*value_type)(sqlite3_value*); 162 | char *(*vmprintf)(const char*,va_list); 163 | /* Added ??? */ 164 | int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); 165 | /* Added by 3.3.13 */ 166 | int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); 167 | int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); 168 | int (*clear_bindings)(sqlite3_stmt*); 169 | /* Added by 3.4.1 */ 170 | int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, 171 | void (*xDestroy)(void *)); 172 | /* Added by 3.5.0 */ 173 | int (*bind_zeroblob)(sqlite3_stmt*,int,int); 174 | int (*blob_bytes)(sqlite3_blob*); 175 | int (*blob_close)(sqlite3_blob*); 176 | int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, 177 | int,sqlite3_blob**); 178 | int (*blob_read)(sqlite3_blob*,void*,int,int); 179 | int (*blob_write)(sqlite3_blob*,const void*,int,int); 180 | int (*create_collation_v2)(sqlite3*,const char*,int,void*, 181 | int(*)(void*,int,const void*,int,const void*), 182 | void(*)(void*)); 183 | int (*file_control)(sqlite3*,const char*,int,void*); 184 | sqlite3_int64 (*memory_highwater)(int); 185 | sqlite3_int64 (*memory_used)(void); 186 | sqlite3_mutex *(*mutex_alloc)(int); 187 | void (*mutex_enter)(sqlite3_mutex*); 188 | void (*mutex_free)(sqlite3_mutex*); 189 | void (*mutex_leave)(sqlite3_mutex*); 190 | int (*mutex_try)(sqlite3_mutex*); 191 | int (*open_v2)(const char*,sqlite3**,int,const char*); 192 | int (*release_memory)(int); 193 | void (*result_error_nomem)(sqlite3_context*); 194 | void (*result_error_toobig)(sqlite3_context*); 195 | int (*sleep)(int); 196 | void (*soft_heap_limit)(int); 197 | sqlite3_vfs *(*vfs_find)(const char*); 198 | int (*vfs_register)(sqlite3_vfs*,int); 199 | int (*vfs_unregister)(sqlite3_vfs*); 200 | int (*xthreadsafe)(void); 201 | void (*result_zeroblob)(sqlite3_context*,int); 202 | void (*result_error_code)(sqlite3_context*,int); 203 | int (*test_control)(int, ...); 204 | void (*randomness)(int,void*); 205 | sqlite3 *(*context_db_handle)(sqlite3_context*); 206 | int (*extended_result_codes)(sqlite3*,int); 207 | int (*limit)(sqlite3*,int,int); 208 | sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); 209 | const char *(*sql)(sqlite3_stmt*); 210 | int (*status)(int,int*,int*,int); 211 | int (*backup_finish)(sqlite3_backup*); 212 | sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); 213 | int (*backup_pagecount)(sqlite3_backup*); 214 | int (*backup_remaining)(sqlite3_backup*); 215 | int (*backup_step)(sqlite3_backup*,int); 216 | const char *(*compileoption_get)(int); 217 | int (*compileoption_used)(const char*); 218 | int (*create_function_v2)(sqlite3*,const char*,int,int,void*, 219 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), 220 | void (*xStep)(sqlite3_context*,int,sqlite3_value**), 221 | void (*xFinal)(sqlite3_context*), 222 | void(*xDestroy)(void*)); 223 | int (*db_config)(sqlite3*,int,...); 224 | sqlite3_mutex *(*db_mutex)(sqlite3*); 225 | int (*db_status)(sqlite3*,int,int*,int*,int); 226 | int (*extended_errcode)(sqlite3*); 227 | void (*log)(int,const char*,...); 228 | sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); 229 | const char *(*sourceid)(void); 230 | int (*stmt_status)(sqlite3_stmt*,int,int); 231 | int (*strnicmp)(const char*,const char*,int); 232 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); 233 | int (*wal_autocheckpoint)(sqlite3*,int); 234 | int (*wal_checkpoint)(sqlite3*,const char*); 235 | void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); 236 | int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); 237 | int (*vtab_config)(sqlite3*,int op,...); 238 | int (*vtab_on_conflict)(sqlite3*); 239 | }; 240 | 241 | /* 242 | ** The following macros redefine the API routines so that they are 243 | ** redirected throught the global sqlite3_api structure. 244 | ** 245 | ** This header file is also used by the loadext.c source file 246 | ** (part of the main SQLite library - not an extension) so that 247 | ** it can get access to the sqlite3_api_routines structure 248 | ** definition. But the main library does not want to redefine 249 | ** the API. So the redefinition macros are only valid if the 250 | ** SQLITE_CORE macros is undefined. 251 | */ 252 | #ifndef SQLITE_CORE 253 | #define sqlite3_aggregate_context sqlite3_api->aggregate_context 254 | #ifndef SQLITE_OMIT_DEPRECATED 255 | #define sqlite3_aggregate_count sqlite3_api->aggregate_count 256 | #endif 257 | #define sqlite3_bind_blob sqlite3_api->bind_blob 258 | #define sqlite3_bind_double sqlite3_api->bind_double 259 | #define sqlite3_bind_int sqlite3_api->bind_int 260 | #define sqlite3_bind_int64 sqlite3_api->bind_int64 261 | #define sqlite3_bind_null sqlite3_api->bind_null 262 | #define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count 263 | #define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index 264 | #define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name 265 | #define sqlite3_bind_text sqlite3_api->bind_text 266 | #define sqlite3_bind_text16 sqlite3_api->bind_text16 267 | #define sqlite3_bind_value sqlite3_api->bind_value 268 | #define sqlite3_busy_handler sqlite3_api->busy_handler 269 | #define sqlite3_busy_timeout sqlite3_api->busy_timeout 270 | #define sqlite3_changes sqlite3_api->changes 271 | #define sqlite3_close sqlite3_api->close 272 | #define sqlite3_collation_needed sqlite3_api->collation_needed 273 | #define sqlite3_collation_needed16 sqlite3_api->collation_needed16 274 | #define sqlite3_column_blob sqlite3_api->column_blob 275 | #define sqlite3_column_bytes sqlite3_api->column_bytes 276 | #define sqlite3_column_bytes16 sqlite3_api->column_bytes16 277 | #define sqlite3_column_count sqlite3_api->column_count 278 | #define sqlite3_column_database_name sqlite3_api->column_database_name 279 | #define sqlite3_column_database_name16 sqlite3_api->column_database_name16 280 | #define sqlite3_column_decltype sqlite3_api->column_decltype 281 | #define sqlite3_column_decltype16 sqlite3_api->column_decltype16 282 | #define sqlite3_column_double sqlite3_api->column_double 283 | #define sqlite3_column_int sqlite3_api->column_int 284 | #define sqlite3_column_int64 sqlite3_api->column_int64 285 | #define sqlite3_column_name sqlite3_api->column_name 286 | #define sqlite3_column_name16 sqlite3_api->column_name16 287 | #define sqlite3_column_origin_name sqlite3_api->column_origin_name 288 | #define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 289 | #define sqlite3_column_table_name sqlite3_api->column_table_name 290 | #define sqlite3_column_table_name16 sqlite3_api->column_table_name16 291 | #define sqlite3_column_text sqlite3_api->column_text 292 | #define sqlite3_column_text16 sqlite3_api->column_text16 293 | #define sqlite3_column_type sqlite3_api->column_type 294 | #define sqlite3_column_value sqlite3_api->column_value 295 | #define sqlite3_commit_hook sqlite3_api->commit_hook 296 | #define sqlite3_complete sqlite3_api->complete 297 | #define sqlite3_complete16 sqlite3_api->complete16 298 | #define sqlite3_create_collation sqlite3_api->create_collation 299 | #define sqlite3_create_collation16 sqlite3_api->create_collation16 300 | #define sqlite3_create_function sqlite3_api->create_function 301 | #define sqlite3_create_function16 sqlite3_api->create_function16 302 | #define sqlite3_create_module sqlite3_api->create_module 303 | #define sqlite3_create_module_v2 sqlite3_api->create_module_v2 304 | #define sqlite3_data_count sqlite3_api->data_count 305 | #define sqlite3_db_handle sqlite3_api->db_handle 306 | #define sqlite3_declare_vtab sqlite3_api->declare_vtab 307 | #define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache 308 | #define sqlite3_errcode sqlite3_api->errcode 309 | #define sqlite3_errmsg sqlite3_api->errmsg 310 | #define sqlite3_errmsg16 sqlite3_api->errmsg16 311 | #define sqlite3_exec sqlite3_api->exec 312 | #ifndef SQLITE_OMIT_DEPRECATED 313 | #define sqlite3_expired sqlite3_api->expired 314 | #endif 315 | #define sqlite3_finalize sqlite3_api->finalize 316 | #define sqlite3_free sqlite3_api->free 317 | #define sqlite3_free_table sqlite3_api->free_table 318 | #define sqlite3_get_autocommit sqlite3_api->get_autocommit 319 | #define sqlite3_get_auxdata sqlite3_api->get_auxdata 320 | #define sqlite3_get_table sqlite3_api->get_table 321 | #ifndef SQLITE_OMIT_DEPRECATED 322 | #define sqlite3_global_recover sqlite3_api->global_recover 323 | #endif 324 | #define sqlite3_interrupt sqlite3_api->interruptx 325 | #define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid 326 | #define sqlite3_libversion sqlite3_api->libversion 327 | #define sqlite3_libversion_number sqlite3_api->libversion_number 328 | #define sqlite3_malloc sqlite3_api->malloc 329 | #define sqlite3_mprintf sqlite3_api->mprintf 330 | #define sqlite3_open sqlite3_api->open 331 | #define sqlite3_open16 sqlite3_api->open16 332 | #define sqlite3_prepare sqlite3_api->prepare 333 | #define sqlite3_prepare16 sqlite3_api->prepare16 334 | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 335 | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 336 | #define sqlite3_profile sqlite3_api->profile 337 | #define sqlite3_progress_handler sqlite3_api->progress_handler 338 | #define sqlite3_realloc sqlite3_api->realloc 339 | #define sqlite3_reset sqlite3_api->reset 340 | #define sqlite3_result_blob sqlite3_api->result_blob 341 | #define sqlite3_result_double sqlite3_api->result_double 342 | #define sqlite3_result_error sqlite3_api->result_error 343 | #define sqlite3_result_error16 sqlite3_api->result_error16 344 | #define sqlite3_result_int sqlite3_api->result_int 345 | #define sqlite3_result_int64 sqlite3_api->result_int64 346 | #define sqlite3_result_null sqlite3_api->result_null 347 | #define sqlite3_result_text sqlite3_api->result_text 348 | #define sqlite3_result_text16 sqlite3_api->result_text16 349 | #define sqlite3_result_text16be sqlite3_api->result_text16be 350 | #define sqlite3_result_text16le sqlite3_api->result_text16le 351 | #define sqlite3_result_value sqlite3_api->result_value 352 | #define sqlite3_rollback_hook sqlite3_api->rollback_hook 353 | #define sqlite3_set_authorizer sqlite3_api->set_authorizer 354 | #define sqlite3_set_auxdata sqlite3_api->set_auxdata 355 | #define sqlite3_snprintf sqlite3_api->snprintf 356 | #define sqlite3_step sqlite3_api->step 357 | #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata 358 | #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup 359 | #define sqlite3_total_changes sqlite3_api->total_changes 360 | #define sqlite3_trace sqlite3_api->trace 361 | #ifndef SQLITE_OMIT_DEPRECATED 362 | #define sqlite3_transfer_bindings sqlite3_api->transfer_bindings 363 | #endif 364 | #define sqlite3_update_hook sqlite3_api->update_hook 365 | #define sqlite3_user_data sqlite3_api->user_data 366 | #define sqlite3_value_blob sqlite3_api->value_blob 367 | #define sqlite3_value_bytes sqlite3_api->value_bytes 368 | #define sqlite3_value_bytes16 sqlite3_api->value_bytes16 369 | #define sqlite3_value_double sqlite3_api->value_double 370 | #define sqlite3_value_int sqlite3_api->value_int 371 | #define sqlite3_value_int64 sqlite3_api->value_int64 372 | #define sqlite3_value_numeric_type sqlite3_api->value_numeric_type 373 | #define sqlite3_value_text sqlite3_api->value_text 374 | #define sqlite3_value_text16 sqlite3_api->value_text16 375 | #define sqlite3_value_text16be sqlite3_api->value_text16be 376 | #define sqlite3_value_text16le sqlite3_api->value_text16le 377 | #define sqlite3_value_type sqlite3_api->value_type 378 | #define sqlite3_vmprintf sqlite3_api->vmprintf 379 | #define sqlite3_overload_function sqlite3_api->overload_function 380 | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 381 | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 382 | #define sqlite3_clear_bindings sqlite3_api->clear_bindings 383 | #define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob 384 | #define sqlite3_blob_bytes sqlite3_api->blob_bytes 385 | #define sqlite3_blob_close sqlite3_api->blob_close 386 | #define sqlite3_blob_open sqlite3_api->blob_open 387 | #define sqlite3_blob_read sqlite3_api->blob_read 388 | #define sqlite3_blob_write sqlite3_api->blob_write 389 | #define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 390 | #define sqlite3_file_control sqlite3_api->file_control 391 | #define sqlite3_memory_highwater sqlite3_api->memory_highwater 392 | #define sqlite3_memory_used sqlite3_api->memory_used 393 | #define sqlite3_mutex_alloc sqlite3_api->mutex_alloc 394 | #define sqlite3_mutex_enter sqlite3_api->mutex_enter 395 | #define sqlite3_mutex_free sqlite3_api->mutex_free 396 | #define sqlite3_mutex_leave sqlite3_api->mutex_leave 397 | #define sqlite3_mutex_try sqlite3_api->mutex_try 398 | #define sqlite3_open_v2 sqlite3_api->open_v2 399 | #define sqlite3_release_memory sqlite3_api->release_memory 400 | #define sqlite3_result_error_nomem sqlite3_api->result_error_nomem 401 | #define sqlite3_result_error_toobig sqlite3_api->result_error_toobig 402 | #define sqlite3_sleep sqlite3_api->sleep 403 | #define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit 404 | #define sqlite3_vfs_find sqlite3_api->vfs_find 405 | #define sqlite3_vfs_register sqlite3_api->vfs_register 406 | #define sqlite3_vfs_unregister sqlite3_api->vfs_unregister 407 | #define sqlite3_threadsafe sqlite3_api->xthreadsafe 408 | #define sqlite3_result_zeroblob sqlite3_api->result_zeroblob 409 | #define sqlite3_result_error_code sqlite3_api->result_error_code 410 | #define sqlite3_test_control sqlite3_api->test_control 411 | #define sqlite3_randomness sqlite3_api->randomness 412 | #define sqlite3_context_db_handle sqlite3_api->context_db_handle 413 | #define sqlite3_extended_result_codes sqlite3_api->extended_result_codes 414 | #define sqlite3_limit sqlite3_api->limit 415 | #define sqlite3_next_stmt sqlite3_api->next_stmt 416 | #define sqlite3_sql sqlite3_api->sql 417 | #define sqlite3_status sqlite3_api->status 418 | #define sqlite3_backup_finish sqlite3_api->backup_finish 419 | #define sqlite3_backup_init sqlite3_api->backup_init 420 | #define sqlite3_backup_pagecount sqlite3_api->backup_pagecount 421 | #define sqlite3_backup_remaining sqlite3_api->backup_remaining 422 | #define sqlite3_backup_step sqlite3_api->backup_step 423 | #define sqlite3_compileoption_get sqlite3_api->compileoption_get 424 | #define sqlite3_compileoption_used sqlite3_api->compileoption_used 425 | #define sqlite3_create_function_v2 sqlite3_api->create_function_v2 426 | #define sqlite3_db_config sqlite3_api->db_config 427 | #define sqlite3_db_mutex sqlite3_api->db_mutex 428 | #define sqlite3_db_status sqlite3_api->db_status 429 | #define sqlite3_extended_errcode sqlite3_api->extended_errcode 430 | #define sqlite3_log sqlite3_api->log 431 | #define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 432 | #define sqlite3_sourceid sqlite3_api->sourceid 433 | #define sqlite3_stmt_status sqlite3_api->stmt_status 434 | #define sqlite3_strnicmp sqlite3_api->strnicmp 435 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify 436 | #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint 437 | #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint 438 | #define sqlite3_wal_hook sqlite3_api->wal_hook 439 | #define sqlite3_blob_reopen sqlite3_api->blob_reopen 440 | #define sqlite3_vtab_config sqlite3_api->vtab_config 441 | #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict 442 | #endif /* SQLITE_CORE */ 443 | 444 | #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; 445 | #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; 446 | 447 | #endif /* _SQLITE3EXT_H_ */ 448 | --------------------------------------------------------------------------------