├── .gitattributes ├── LICENSE ├── README └── sqlite3 ├── backup.go ├── codec.go ├── codec ├── aes-hmac.go ├── codec.go ├── codec_test.go ├── doc.go └── hexdump.go ├── const.go ├── doc.go ├── driver.go ├── io.go ├── lib ├── codec.c ├── codec.h ├── sqlite3.c └── sqlite3.h ├── sqlite3.c ├── sqlite3.go ├── sqlite3.h ├── sqlite3_test.go └── util.go /.gitattributes: -------------------------------------------------------------------------------- 1 | sqlite3/lib/sqlite3.[ch] -whitespace 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Go-SQLite Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of the go-sqlite project nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | SQLite Library for Go 2 | ===================== 3 | 4 | To download and install this package run: 5 | 6 | go get github.com/mxk/go-sqlite/sqlite3 7 | 8 | The full installation instructions and documentation are available at: 9 | 10 | http://godoc.org/github.com/mxk/go-sqlite/sqlite3 11 | -------------------------------------------------------------------------------- /sqlite3/backup.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #include "sqlite3.h" 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "io" 14 | "runtime" 15 | ) 16 | 17 | // Backup is a handle to an online backup operation between two databases. 18 | // [http://www.sqlite.org/c3ref/backup.html] 19 | type Backup struct { 20 | src *Conn 21 | dst *Conn 22 | bkup *C.sqlite3_backup 23 | } 24 | 25 | // newBackup initializes an online backup operation from src.srcName to 26 | // dst.dstName. 27 | func newBackup(src *Conn, srcName string, dst *Conn, dstName string) (*Backup, error) { 28 | srcName += "\x00" 29 | dstName += "\x00" 30 | 31 | bkup := C.sqlite3_backup_init(dst.db, cStr(dstName), src.db, cStr(srcName)) 32 | if bkup == nil { 33 | return nil, libErr(C.sqlite3_errcode(dst.db), dst.db) 34 | } 35 | 36 | b := &Backup{src, dst, bkup} 37 | runtime.SetFinalizer(b, (*Backup).Close) 38 | return b, nil 39 | } 40 | 41 | // Close releases all resources associated with the backup operation. It is safe 42 | // to call this method prior to backup completion to abort the operation. 43 | // [http://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish] 44 | func (b *Backup) Close() error { 45 | if bkup := b.bkup; bkup != nil { 46 | b.bkup = nil 47 | runtime.SetFinalizer(b, nil) 48 | if rc := C.sqlite3_backup_finish(bkup); rc != OK { 49 | return libErr(rc, b.dst.db) 50 | } 51 | } 52 | return nil 53 | } 54 | 55 | // Conn returns the source and destination connections that are used by this 56 | // backup operation. The destination connection must not be used until the 57 | // backup operation is closed. 58 | func (b *Backup) Conn() (src, dst *Conn) { 59 | return b.src, b.dst 60 | } 61 | 62 | // Step copies up to n pages to the destination database. If n is negative, all 63 | // remaining pages are copied. io.EOF is returned upon successful backup 64 | // completion. 65 | // [http://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep] 66 | func (b *Backup) Step(n int) error { 67 | if b.bkup == nil { 68 | return ErrBadBackup 69 | } 70 | if rc := C.sqlite3_backup_step(b.bkup, C.int(n)); rc != OK { 71 | // Do not close automatically since that clears the progress info 72 | if rc == DONE { 73 | return io.EOF 74 | } 75 | return libErr(rc, b.dst.db) 76 | } 77 | return nil 78 | } 79 | 80 | // Progress returns the number of pages that still need to be backed up and the 81 | // total number of pages in the source database. The values are updated after 82 | // each call to Step and are reset to 0 after the backup is closed. The total 83 | // number of pages may change if the source database is modified during the 84 | // backup operation. 85 | // [http://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining] 86 | func (b *Backup) Progress() (remaining, total int) { 87 | if b.bkup != nil { 88 | remaining = int(C.sqlite3_backup_remaining(b.bkup)) 89 | total = int(C.sqlite3_backup_pagecount(b.bkup)) 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /sqlite3/codec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #include "sqlite3.h" 9 | #include "lib/codec.h" 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "bytes" 15 | "sync" 16 | "unsafe" 17 | ) 18 | 19 | // CodecFunc is a codec initialization function registered for a specific key 20 | // prefix via RegisterCodec. It is called when a key with a matching prefix is 21 | // specified for an attached database. It returns the Codec implementation that 22 | // should be used to encode and decode all database and journal pages. Returning 23 | // (nil, nil) disables the codec. 24 | type CodecFunc func(ctx *CodecCtx, key []byte) (Codec, *Error) 25 | 26 | // CodecCtx describes the database to which a codec is being attached. 27 | type CodecCtx struct { 28 | Path string // Full path to the database file 29 | Name string // Database name as it is known to SQLite (e.g. "main") 30 | PageSize int // Current page size in bytes 31 | Reserve int // Current number of bytes reserved in each page 32 | Fixed bool // True if the PageSize and Reserve values cannot be changed 33 | } 34 | 35 | // newCodecCtx converts the C CodecCtx struct into its Go representation. 36 | func newCodecCtx(ctx *C.CodecCtx) *CodecCtx { 37 | return &CodecCtx{ 38 | Path: C.GoString(ctx.zPath), 39 | Name: C.GoString(ctx.zName), 40 | PageSize: int(ctx.nBuf), 41 | Reserve: int(ctx.nRes), 42 | Fixed: ctx.fixed != 0, 43 | } 44 | } 45 | 46 | // Codec is the interface used to encode/decode database and journal pages as 47 | // they are written to and read from the disk. 48 | // 49 | // The op value passed to Encode and Decode methods identifies the operation 50 | // being performed. It is undocumented and changed meanings over time since the 51 | // codec API was first introduced in 2004. It is believed to be a bitmask of the 52 | // following values: 53 | // 54 | // 1 = journal page, not set for WAL, always set when decoding 55 | // 2 = disk I/O, always set 56 | // 4 = encode 57 | // 58 | // In the current implementation, op is always 3 when decoding, 6 when encoding 59 | // for the database file or the WAL, and 7 when encoding for the journal. Search 60 | // lib/sqlite3.c for "CODEC1" and "CODEC2" for more information. 61 | type Codec interface { 62 | // Reserve returns the number of bytes that should be reserved for the codec 63 | // at the end of each page. The upper limit is 255 (32 if the page size is 64 | // 512). Returning -1 leaves the current value unchanged. 65 | Reserve() int 66 | 67 | // Resize is called when the codec is first attached to the pager and for 68 | // all subsequent page size changes. It can be used to allocate the encode 69 | // buffer. 70 | Resize(pageSize, reserve int) 71 | 72 | // Encode returns an encoded copy of a page. The data outside of the reserve 73 | // area in the original page must not be modified. The codec can either copy 74 | // this data into a buffer for encoding or return the original page without 75 | // making any changes. Bytes 16 through 23 of page 1 cannot be encoded. Any 76 | // non-nil error will be interpreted by SQLite as a NOMEM condition. This is 77 | // a limitation of underlying C API. 78 | Encode(page []byte, pageNum uint32, op int) ([]byte, *Error) 79 | 80 | // Decode decodes the page in-place, but it may use the encode buffer as 81 | // scratch space. Bytes 16 through 23 of page 1 must be left at their 82 | // original values. Any non-nil error will be interpreted by SQLite as a 83 | // NOMEM condition. This is a limitation of underlying C API. 84 | Decode(page []byte, pageNum uint32, op int) *Error 85 | 86 | // Key returns the original key that was used to initialize the codec. Some 87 | // implementations may be better off returning nil or a fake value. Search 88 | // lib/sqlite3.c for "sqlite3CodecGetKey" to see how the key is used. 89 | Key() []byte 90 | 91 | // Free releases codec resources when the pager is destroyed or when the 92 | // codec attachment fails. 93 | Free() 94 | } 95 | 96 | // Codec registry and state reference maps. 97 | var ( 98 | codecReg map[string]CodecFunc 99 | codecState map[*codec]struct{} 100 | codecMu sync.Mutex 101 | ) 102 | 103 | // RegisterCodec adds a new codec to the internal registry. Function f will be 104 | // called when a key in the format ":<...>" is provided to an attached 105 | // database. 106 | func RegisterCodec(name string, f CodecFunc) { 107 | codecMu.Lock() 108 | defer codecMu.Unlock() 109 | if f == nil { 110 | delete(codecReg, name) 111 | return 112 | } 113 | if codecReg == nil { 114 | codecReg = make(map[string]CodecFunc, 8) 115 | } 116 | codecReg[name] = f 117 | } 118 | 119 | // getCodec returns the CodecFunc for the given key. 120 | func getCodec(key []byte) CodecFunc { 121 | i := bytes.IndexByte(key, ':') 122 | if i == -1 { 123 | i = len(key) 124 | } 125 | codecMu.Lock() 126 | defer codecMu.Unlock() 127 | if codecReg == nil { 128 | return nil 129 | } 130 | return codecReg[bstr(key[:i])] 131 | } 132 | 133 | // codec is a wrapper around the actual Codec interface. It keeps track of the 134 | // current page size in order to convert page pointers into byte slices. 135 | type codec struct { 136 | Codec 137 | pageSize C.int 138 | } 139 | 140 | //export go_codec_init 141 | func go_codec_init(ctx *C.CodecCtx, pCodec *unsafe.Pointer, pzErrMsg **C.char) C.int { 142 | cf := getCodec(goBytes(ctx.pKey, ctx.nKey)) 143 | if cf == nil { 144 | *pzErrMsg = C.CString("codec not found") 145 | return ERROR 146 | } 147 | ci, err := cf(newCodecCtx(ctx), C.GoBytes(ctx.pKey, ctx.nKey)) 148 | if err != nil && err.rc != OK { 149 | if ci != nil { 150 | ci.Free() 151 | } 152 | if err.msg != "" { 153 | *pzErrMsg = C.CString(err.msg) 154 | } 155 | return C.int(err.rc) 156 | } 157 | if ci != nil { 158 | cs := &codec{ci, ctx.nBuf} 159 | *pCodec = unsafe.Pointer(cs) 160 | codecMu.Lock() 161 | defer codecMu.Unlock() 162 | if codecState == nil { 163 | codecState = make(map[*codec]struct{}, 8) 164 | } 165 | codecState[cs] = struct{}{} 166 | } 167 | return OK 168 | } 169 | 170 | //export go_codec_reserve 171 | func go_codec_reserve(pCodec unsafe.Pointer) C.int { 172 | return C.int((*codec)(pCodec).Reserve()) 173 | } 174 | 175 | //export go_codec_resize 176 | func go_codec_resize(pCodec unsafe.Pointer, nBuf, nRes C.int) { 177 | cs := (*codec)(pCodec) 178 | cs.pageSize = nBuf 179 | cs.Resize(int(nBuf), int(nRes)) 180 | } 181 | 182 | //export go_codec_exec 183 | func go_codec_exec(pCodec, pData unsafe.Pointer, pgno uint32, op C.int) unsafe.Pointer { 184 | cs := (*codec)(pCodec) 185 | page := goBytes(pData, cs.pageSize) 186 | var err *Error 187 | if op&4 == 0 { 188 | err = cs.Decode(page, pgno, int(op)) 189 | } else { 190 | page, err = cs.Encode(page, pgno, int(op)) 191 | } 192 | if err == nil { 193 | return cBytes(page) 194 | } 195 | return nil // Can't do anything with the error at the moment 196 | } 197 | 198 | //export go_codec_get_key 199 | func go_codec_get_key(pCodec unsafe.Pointer, pKey *unsafe.Pointer, nKey *C.int) { 200 | if key := (*codec)(pCodec).Key(); len(key) > 0 { 201 | *pKey = cBytes(key) 202 | *nKey = C.int(len(key)) 203 | } 204 | } 205 | 206 | //export go_codec_free 207 | func go_codec_free(pCodec unsafe.Pointer) { 208 | cs := (*codec)(pCodec) 209 | codecMu.Lock() 210 | delete(codecState, cs) 211 | codecMu.Unlock() 212 | cs.Free() 213 | cs.Codec = nil 214 | } 215 | -------------------------------------------------------------------------------- /sqlite3/codec/aes-hmac.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package codec 6 | 7 | import ( 8 | "crypto/aes" 9 | "crypto/cipher" 10 | "crypto/hmac" 11 | "crypto/sha1" 12 | "crypto/sha256" 13 | "hash" 14 | 15 | . "github.com/mxk/go-sqlite/sqlite3" 16 | ) 17 | 18 | type aesHmac struct { 19 | key []byte // Key provided to newAesHmac with the master key removed 20 | buf []byte // Page encryption buffer 21 | hdr [4]byte // Header included in each HMAC calculation (page number) 22 | tLen int // Tag length in bytes (HMAC truncation) 23 | 24 | // Hash function and chaining mode constructors 25 | hash func() hash.Hash 26 | mode func(block cipher.Block, iv []byte) cipher.Stream 27 | 28 | // Block cipher and HMAC initialized from the master key 29 | block cipher.Block 30 | hmac hash.Hash 31 | } 32 | 33 | func newAesHmac(ctx *CodecCtx, key []byte) (Codec, *Error) { 34 | name, opts, mk := parseKey(key) 35 | if len(mk) == 0 { 36 | return nil, keyErr 37 | } 38 | defer wipe(mk) 39 | 40 | // Configure the codec 41 | c := &aesHmac{ 42 | key: key[:len(key)-len(mk)], 43 | tLen: 16, 44 | hash: sha1.New, 45 | mode: cipher.NewCTR, 46 | } 47 | suite := suiteId{ 48 | Cipher: "aes", 49 | KeySize: "128", 50 | Mode: "ctr", 51 | MAC: "hmac", 52 | Hash: "sha1", 53 | Trunc: "128", 54 | } 55 | kLen := 16 56 | if err := c.config(opts, &suite, &kLen); err != nil { 57 | return nil, err 58 | } 59 | 60 | // Derive encryption and authentication keys 61 | hLen := c.hash().Size() 62 | salt := make([]byte, hLen) 63 | copy(salt, name) 64 | dk := hkdf(mk, salt, kLen+hLen, c.hash)(suite.Id()) 65 | defer wipe(dk) 66 | 67 | // Initialize the block cipher and HMAC 68 | var err error 69 | if c.block, err = aes.NewCipher(dk[:kLen]); err != nil { 70 | return nil, NewError(MISUSE, err.Error()) 71 | } 72 | c.hmac = hmac.New(c.hash, dk[kLen:]) 73 | return c, nil 74 | } 75 | 76 | func (c *aesHmac) Reserve() int { 77 | return aes.BlockSize + c.tLen 78 | } 79 | 80 | func (c *aesHmac) Resize(pageSize, reserve int) { 81 | if reserve != c.Reserve() { 82 | panic("sqlite3: codec reserve value mismatch") 83 | } 84 | hLen := c.hash().Size() 85 | c.buf = make([]byte, pageSize, pageSize-c.tLen+hLen) 86 | } 87 | 88 | func (c *aesHmac) Encode(p []byte, n uint32, op int) ([]byte, *Error) { 89 | iv := c.pIV(c.buf) 90 | if !rnd(iv) { 91 | return nil, prngErr 92 | } 93 | c.mode(c.block, iv).XORKeyStream(c.buf, c.pText(p)) 94 | if n == 1 { 95 | copy(c.buf[16:], p[16:24]) 96 | } 97 | c.auth(c.buf, n, false) 98 | return c.buf, nil 99 | } 100 | 101 | func (c *aesHmac) Decode(p []byte, n uint32, op int) *Error { 102 | if !c.auth(p, n, true) { 103 | return codecErr 104 | } 105 | if n == 1 { 106 | copy(c.buf, p[16:24]) 107 | } 108 | c.mode(c.block, c.pIV(p)).XORKeyStream(p, c.pText(p)) 109 | if n == 1 { 110 | copy(p[16:24], c.buf) 111 | } 112 | return nil 113 | } 114 | 115 | func (c *aesHmac) Key() []byte { 116 | return c.key 117 | } 118 | 119 | func (c *aesHmac) Free() { 120 | c.buf = nil 121 | c.block = nil 122 | c.hmac = nil 123 | } 124 | 125 | // config applies the codec options that were provided in the key. 126 | func (c *aesHmac) config(opts map[string]string, s *suiteId, kLen *int) *Error { 127 | for k := range opts { 128 | switch k { 129 | case "192": 130 | s.KeySize = k 131 | *kLen = 24 132 | case "256": 133 | s.KeySize = k 134 | *kLen = 32 135 | case "ofb": 136 | s.Mode = k 137 | c.mode = cipher.NewOFB 138 | case "sha256": 139 | s.Hash = k 140 | c.hash = sha256.New 141 | default: 142 | return NewError(MISUSE, "invalid codec option: "+k) 143 | } 144 | } 145 | return nil 146 | } 147 | 148 | // auth calculates and verifies the HMAC tag for page p. It returns true iff the 149 | // tag is successfully verified. 150 | func (c *aesHmac) auth(p []byte, n uint32, verify bool) bool { 151 | c.hdr[0] = byte(n >> 24) 152 | c.hdr[1] = byte(n >> 16) 153 | c.hdr[2] = byte(n >> 8) 154 | c.hdr[3] = byte(n) 155 | 156 | tag := c.pTag(c.buf) 157 | c.hmac.Reset() 158 | c.hmac.Write(c.hdr[:]) 159 | c.hmac.Write(c.pAuth(p)) 160 | c.hmac.Sum(tag[:0]) 161 | 162 | return verify && hmac.Equal(tag, c.pTag(p)) 163 | } 164 | 165 | // pAuth returns the page subslice that gets authenticated. 166 | func (c *aesHmac) pAuth(p []byte) []byte { 167 | return p[:len(p)-c.tLen] 168 | } 169 | 170 | // pText returns the page subslice that gets encrypted. 171 | func (c *aesHmac) pText(p []byte) []byte { 172 | return p[:len(p)-c.tLen-aes.BlockSize] 173 | } 174 | 175 | // pIV returns the page initialization vector. 176 | func (c *aesHmac) pIV(p []byte) []byte { 177 | return p[len(p)-c.tLen-aes.BlockSize : len(p)-c.tLen] 178 | } 179 | 180 | // pTag returns the page authentication tag. 181 | func (c *aesHmac) pTag(p []byte) []byte { 182 | return p[len(p)-c.tLen:] 183 | } 184 | -------------------------------------------------------------------------------- /sqlite3/codec/codec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package codec 6 | 7 | import ( 8 | "bytes" 9 | "crypto/hmac" 10 | "crypto/rand" 11 | "hash" 12 | "io" 13 | "strings" 14 | 15 | . "github.com/mxk/go-sqlite/sqlite3" 16 | ) 17 | 18 | func init() { 19 | RegisterCodec("aes-hmac", newAesHmac) 20 | RegisterCodec("hexdump", newHexDump) 21 | } 22 | 23 | // Errors returned by codec implementations. 24 | var ( 25 | codecErr = NewError(ERROR, "unspecified codec error") 26 | prngErr = NewError(ERROR, "csprng not available") 27 | keyErr = NewError(MISUSE, "invalid codec key format") 28 | ) 29 | 30 | // parseKey extracts the codec name, options, and anything left over from a key 31 | // in the format "::". 32 | func parseKey(key []byte) (name string, opts map[string]string, tail []byte) { 33 | k := bytes.SplitN(key, []byte{':'}, 3) 34 | name = string(k[0]) 35 | opts = make(map[string]string) 36 | if len(k) > 1 && len(k[1]) > 0 { 37 | for _, opt := range strings.Split(string(k[1]), ",") { 38 | if i := strings.Index(opt, "="); i > 0 { 39 | opts[opt[:i]] = opt[i+1:] 40 | } else { 41 | opts[opt] = "" 42 | } 43 | } 44 | } 45 | if len(k) > 2 && len(k[2]) > 0 { 46 | tail = k[2] 47 | } 48 | return 49 | } 50 | 51 | // hkdf implements the HMAC-based Key Derivation Function, as described in RFC 52 | // 5869. The extract step is skipped if salt == nil. It is the caller's 53 | // responsibility to set salt "to a string of HashLen zeros," if such behavior 54 | // is desired. It returns the function that performs the expand step using the 55 | // provided info value, which must be appendable. The derived key is valid until 56 | // the next expansion. 57 | func hkdf(ikm, salt []byte, dkLen int, h func() hash.Hash) func(info []byte) []byte { 58 | if salt != nil { 59 | prf := hmac.New(h, salt) 60 | prf.Write(ikm) 61 | ikm = prf.Sum(nil) 62 | } 63 | prf := hmac.New(h, ikm) 64 | hLen := prf.Size() 65 | n := (dkLen + hLen - 1) / hLen 66 | dk := make([]byte, dkLen, n*hLen) 67 | 68 | return func(info []byte) []byte { 69 | info = append(info, 0) 70 | ctr := &info[len(info)-1] 71 | for i, t := 1, dk[:0]; i <= n; i++ { 72 | *ctr = byte(i) 73 | prf.Reset() 74 | prf.Write(t) 75 | prf.Write(info) 76 | t = prf.Sum(t[len(t):]) 77 | } 78 | return dk 79 | } 80 | } 81 | 82 | // rnd fills b with bytes from a CSPRNG. 83 | func rnd(b []byte) bool { 84 | _, err := io.ReadFull(rand.Reader, b) 85 | return err == nil 86 | } 87 | 88 | // wipe overwrites b with zeros. 89 | func wipe(b []byte) { 90 | for i := range b { 91 | b[i] = 0 92 | } 93 | } 94 | 95 | // suiteId constructs a canonical cipher suite identifier. 96 | type suiteId struct { 97 | Cipher string 98 | KeySize string 99 | Mode string 100 | MAC string 101 | Hash string 102 | Trunc string 103 | } 104 | 105 | func (s *suiteId) Id() []byte { 106 | id := make([]byte, 0, 64) 107 | section := func(parts ...string) { 108 | for i, p := range parts { 109 | if p != "" { 110 | parts = parts[i:] 111 | goto write 112 | } 113 | } 114 | return 115 | write: 116 | if len(id) > 0 { 117 | id = append(id, ',') 118 | } 119 | id = append(id, parts[0]...) 120 | for _, p := range parts[1:] { 121 | if p != "" { 122 | id = append(id, '-') 123 | id = append(id, p...) 124 | } 125 | } 126 | } 127 | section(s.Cipher, s.KeySize, s.Mode) 128 | section(s.MAC, s.Hash, s.Trunc) 129 | return id 130 | } 131 | -------------------------------------------------------------------------------- /sqlite3/codec/codec_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package codec 6 | 7 | import ( 8 | "crypto/sha1" 9 | "crypto/sha256" 10 | "encoding/hex" 11 | "hash" 12 | "testing" 13 | ) 14 | 15 | func TestHKDF(t *testing.T) { 16 | tests := []struct { 17 | ikm string 18 | salt string 19 | info string 20 | dkLen int 21 | h func() hash.Hash 22 | out string 23 | }{ 24 | // RFC 5869 Test Vectors 25 | { 26 | "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 27 | "000102030405060708090a0b0c", 28 | "f0f1f2f3f4f5f6f7f8f9", 29 | 42, 30 | sha256.New, 31 | "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", 32 | }, { 33 | "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", 34 | "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", 35 | "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 36 | 82, 37 | sha256.New, 38 | "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", 39 | }, { 40 | "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 41 | "", 42 | "", 43 | 42, 44 | sha256.New, 45 | "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", 46 | }, { 47 | "0b0b0b0b0b0b0b0b0b0b0b", 48 | "000102030405060708090a0b0c", 49 | "f0f1f2f3f4f5f6f7f8f9", 50 | 42, 51 | sha1.New, 52 | "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896", 53 | }, { 54 | "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", 55 | "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", 56 | "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 57 | 82, 58 | sha1.New, 59 | "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4", 60 | }, { 61 | "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", 62 | "", 63 | "", 64 | 42, 65 | sha1.New, 66 | "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918", 67 | }, { 68 | "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", 69 | "0000000000000000000000000000000000000000", 70 | "", 71 | 42, 72 | sha1.New, 73 | "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48", 74 | }, 75 | } 76 | for i, test := range tests { 77 | ikm, _ := hex.DecodeString(test.ikm) 78 | salt, _ := hex.DecodeString(test.salt) 79 | info, _ := hex.DecodeString(test.info) 80 | dk := hkdf(ikm, salt, test.dkLen, test.h)(info) 81 | if out := hex.EncodeToString(dk); out != test.out { 82 | t.Errorf("hkdf(%d) expected %q; got %q", i, test.out, out) 83 | } 84 | } 85 | } 86 | 87 | func TestSuiteId(t *testing.T) { 88 | tests := []struct { 89 | suite suiteId 90 | out string 91 | }{ 92 | {suiteId{}, 93 | ""}, 94 | {suiteId{Cipher: "aes"}, 95 | "aes"}, 96 | {suiteId{KeySize: "128"}, 97 | "128"}, 98 | {suiteId{Cipher: "aes", KeySize: "128"}, 99 | "aes-128"}, 100 | {suiteId{Cipher: "aes", Mode: "ctr"}, 101 | "aes-ctr"}, 102 | {suiteId{Cipher: "aes", KeySize: "128", Mode: "ctr"}, 103 | "aes-128-ctr"}, 104 | {suiteId{MAC: "hmac"}, 105 | "hmac"}, 106 | {suiteId{MAC: "hmac", Hash: "sha1"}, 107 | "hmac-sha1"}, 108 | {suiteId{MAC: "hmac", Hash: "sha1", Trunc: "128"}, 109 | "hmac-sha1-128"}, 110 | {suiteId{Cipher: "aes", MAC: "hmac"}, 111 | "aes,hmac"}, 112 | {suiteId{Cipher: "aes", Hash: "sha1"}, 113 | "aes,sha1"}, 114 | {suiteId{Mode: "ctr", Hash: "sha1"}, 115 | "ctr,sha1"}, 116 | {suiteId{Cipher: "aes", KeySize: "128", MAC: "hmac", Hash: "sha256"}, 117 | "aes-128,hmac-sha256"}, 118 | {suiteId{Cipher: "aes", Mode: "ctr", Hash: "sha256", Trunc: "128"}, 119 | "aes-ctr,sha256-128"}, 120 | {suiteId{Cipher: "aes", KeySize: "256", Mode: "ctr", MAC: "hmac", Hash: "sha256", Trunc: "128"}, 121 | "aes-256-ctr,hmac-sha256-128"}, 122 | } 123 | for _, test := range tests { 124 | if out := string(test.suite.Id()); out != test.out { 125 | t.Errorf("%#v expected %q; got %q", test.suite, test.out, out) 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /sqlite3/codec/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package codec provides authenticated encryption and other codecs for the sqlite3 7 | package. 8 | 9 | This package has no public interface and should be imported with the blank 10 | identifier to register the codecs. Use Conn.Key after opening a new connection, 11 | or the KEY clause in an ATTACH statement, to use one of the codecs: 12 | 13 | c, _ := sqlite3.Open("file1.db") 14 | c.Key("main", []byte("aes-hmac::secretkey1")) 15 | c.Exec("ATTACH DATABASE 'file2.db' AS two KEY 'aes-hmac::secretkey2'") 16 | 17 | If the KEY clause is omitted, SQLite uses the key from the main database, which 18 | may no longer be valid depending on how the codec is implemented (e.g. aes-hmac 19 | destroys the master key after initialization). Specify an empty string as the 20 | key to disable this behavior. 21 | 22 | Codec Operation 23 | 24 | Each SQLite database and journal file consists of one or more pages of identical 25 | size. Each page may have extra space reserved at the end, which SQLite will not 26 | use in any way. The exact number of bytes reserved is stored at offset 20 of the 27 | database file header, so the value is between 0 and 255. SQLite requires each 28 | page to have at least 480 usable bytes, so the value cannot exceed 32 bytes with 29 | a page size of 512. This extra space may be used by a codec to store per-page 30 | Initialization Vectors (IVs), Message Authentication Codes (MACs), or any other 31 | information. 32 | 33 | CodecFunc is called to initialize a registered codec when a key with a matching 34 | prefix is provided. If it returns a non-nil Codec implementation, Codec.Reserve 35 | is called to determine how much space this codec needs reserved in each page for 36 | correct operation. Codec.Resize is called to provide the current page size and 37 | reserve values, and for all subsequent changes. The page size may be changed 38 | before the database file is created. Once the first CREATE TABLE statement is 39 | executed, the page size and reserve values are fixed. 40 | 41 | Codec.Encode is called when a page is about to be written to the disk. 42 | Codec.Decode is called when a page was just read from the disk. This happens for 43 | both the main database file and the journal/WAL, so the pages are always encoded 44 | on the disk and decoded in memory. Codec.Free is called to free all codec 45 | resources when the database is detached. 46 | 47 | AES-HMAC 48 | 49 | The aes-hmac codec provides authenticated encryption using the Advanced 50 | Encryption Standard (AES) cipher and the Hash-based Message Authentication Code 51 | (HMAC) in Encrypt-then-MAC mode. Each page has an independent, pseudorandom IV, 52 | which is regenerated every time the page is encrypted, and an authentication 53 | tag, which is verified before the page is decrypted. The codec requires 32 bytes 54 | per page to store this information. 55 | 56 | The key format is "aes-hmac::", where is a 57 | comma-separated list of codec options described below, and is the 58 | key from which separate encryption and authentication keys are derived. 59 | 60 | SECURITY WARNING: The master key is called a "key" and not a "password" for a 61 | reason. It is not passed through pbkdf2, bcrypt, scrypt, or any other key 62 | stretching function. The application is expected to ensure that this key is 63 | sufficiently resistant to brute-force attacks. Ideally, it should be obtained 64 | from a cryptographically secure pseudorandom number generator (CSPRNG), such as 65 | the one provided by the crypto/rand package. 66 | 67 | The encryption and authentication keys are derived from the master key using the 68 | HMAC-based Key Derivation Function (HKDF), as described in RFC 5869. The salt is 69 | the codec name ("aes-hmac") extended with NULLs to HashLen bytes, and info is 70 | the codec configuration string (e.g. "aes-128-ctr,hmac-sha1-128"). This is done 71 | to obtain two keys of the required lengths, which are also bound to the codec 72 | configuration. 73 | 74 | The default configuration is AES-128-CTR cipher and HMAC-SHA1-128 authentication 75 | (HMAC output is truncated to 128 bits). The following options may be used to 76 | change the defaults: 77 | 78 | 192 79 | AES-192 block cipher. 80 | 256 81 | AES-256 block cipher. 82 | ofb 83 | Output feedback mode of operation. 84 | sha256 85 | SHA-256 hash function used by HKDF and HMAC. 86 | 87 | For example, "aes-hmac:256,ofb,sha256:" will use the AES-256-OFB 88 | cipher and HMAC-SHA256-128 authentication. 89 | 90 | HEXDUMP 91 | 92 | The hexdump codec logs all method calls and dumps the page content for each 93 | encode/decode operation to a file. It is intended to be used as an aid when 94 | writing your own codecs. 95 | 96 | The key format is "hexdump::", where is a 97 | comma-separated list of codec options described below, and is the output 98 | destination. The default destination is stderr. Dash ("-") means stdout. For 99 | obvious reasons, this codec cannot be used with an encrypted database except to 100 | see the first Codec.Decode call for page 1. 101 | 102 | The following options are supported: 103 | 104 | quiet 105 | Do not output a hex dump of each page. 106 | reserve=N 107 | Reserve N bytes in each page. The default is -1, which means don't 108 | change the current reserve value. 109 | */ 110 | package codec 111 | -------------------------------------------------------------------------------- /sqlite3/codec/hexdump.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package codec 6 | 7 | import ( 8 | "encoding/hex" 9 | "fmt" 10 | "os" 11 | "strconv" 12 | 13 | . "github.com/mxk/go-sqlite/sqlite3" 14 | ) 15 | 16 | type hexDump struct { 17 | key []byte 18 | out *os.File 19 | quiet bool 20 | res int 21 | } 22 | 23 | func newHexDump(ctx *CodecCtx, key []byte) (Codec, *Error) { 24 | _, opts, tail := parseKey(key) 25 | c := &hexDump{key, os.Stderr, false, -1} 26 | 27 | // Set options 28 | for k, v := range opts { 29 | switch k { 30 | case "quiet": 31 | c.quiet = true 32 | case "reserve": 33 | if n, err := strconv.ParseUint(v, 10, 8); err == nil { 34 | c.res = int(n) 35 | } 36 | default: 37 | return nil, NewError(MISUSE, "invalid codec option: "+k) 38 | } 39 | } 40 | 41 | // Open output file 42 | switch file := string(tail); file { 43 | case "": 44 | case "-": 45 | c.out = os.Stdout 46 | default: 47 | var err error 48 | c.out, err = os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) 49 | if err != nil { 50 | return nil, NewError(ERROR, err.Error()) 51 | } 52 | } 53 | 54 | fmt.Fprintf(c.out, "Init (\n"+ 55 | " Path=%s\n"+ 56 | " Name=%s\n"+ 57 | " PageSize=%d\n"+ 58 | " Reserve=%d\n"+ 59 | " Fixed=%t\n"+ 60 | ")\n", 61 | ctx.Path, ctx.Name, ctx.PageSize, ctx.Reserve, ctx.Fixed) 62 | return c, nil 63 | } 64 | 65 | func (c *hexDump) Reserve() int { 66 | fmt.Fprintf(c.out, "Reserve\n") 67 | return c.res 68 | } 69 | 70 | func (c *hexDump) Resize(pageSize, reserve int) { 71 | fmt.Fprintf(c.out, "Resize (pageSize=%d, reserve=%d)\n", pageSize, reserve) 72 | } 73 | 74 | func (c *hexDump) Encode(page []byte, pageNum uint32, op int) ([]byte, *Error) { 75 | fmt.Fprintf(c.out, "Encode (pageNum=%d, op=%d)\n", pageNum, op) 76 | c.dump(page) 77 | return page, nil 78 | } 79 | 80 | func (c *hexDump) Decode(page []byte, pageNum uint32, op int) *Error { 81 | fmt.Fprintf(c.out, "Decode (pageNum=%d, op=%d)\n", pageNum, op) 82 | c.dump(page) 83 | return nil 84 | } 85 | 86 | func (c *hexDump) Key() []byte { 87 | fmt.Fprintf(c.out, "Key\n") 88 | return c.key 89 | } 90 | 91 | func (c *hexDump) Free() { 92 | fmt.Fprintf(c.out, "Free\n") 93 | if c.out != os.Stdout && c.out != os.Stderr { 94 | c.out.Close() 95 | } 96 | } 97 | 98 | func (c *hexDump) dump(b []byte) { 99 | if !c.quiet { 100 | hd := hex.Dumper(c.out) 101 | hd.Write(b) 102 | hd.Close() 103 | c.out.Write([]byte("\n")) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /sqlite3/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #include "sqlite3.h" 9 | */ 10 | import "C" 11 | 12 | // Fundamental SQLite data types. These are returned by Stmt.DataTypes method. 13 | // [http://www.sqlite.org/c3ref/c_blob.html] 14 | const ( 15 | INTEGER = C.SQLITE_INTEGER // 1 16 | FLOAT = C.SQLITE_FLOAT // 2 17 | TEXT = C.SQLITE_TEXT // 3 18 | BLOB = C.SQLITE_BLOB // 4 19 | NULL = C.SQLITE_NULL // 5 20 | ) 21 | 22 | // General result codes returned by the SQLite API. When converted to an error, 23 | // OK and ROW become nil, and DONE becomes either nil or io.EOF, depending on 24 | // the context in which the statement is executed. All other codes are returned 25 | // via the Error struct. 26 | // [http://www.sqlite.org/c3ref/c_abort.html] 27 | const ( 28 | OK = C.SQLITE_OK // 0 = Successful result 29 | ERROR = C.SQLITE_ERROR // 1 = SQL error or missing database 30 | INTERNAL = C.SQLITE_INTERNAL // 2 = Internal logic error in SQLite 31 | PERM = C.SQLITE_PERM // 3 = Access permission denied 32 | ABORT = C.SQLITE_ABORT // 4 = Callback routine requested an abort 33 | BUSY = C.SQLITE_BUSY // 5 = The database file is locked 34 | LOCKED = C.SQLITE_LOCKED // 6 = A table in the database is locked 35 | NOMEM = C.SQLITE_NOMEM // 7 = A malloc() failed 36 | READONLY = C.SQLITE_READONLY // 8 = Attempt to write a readonly database 37 | INTERRUPT = C.SQLITE_INTERRUPT // 9 = Operation terminated by sqlite3_interrupt() 38 | IOERR = C.SQLITE_IOERR // 10 = Some kind of disk I/O error occurred 39 | CORRUPT = C.SQLITE_CORRUPT // 11 = The database disk image is malformed 40 | NOTFOUND = C.SQLITE_NOTFOUND // 12 = Unknown opcode in sqlite3_file_control() 41 | FULL = C.SQLITE_FULL // 13 = Insertion failed because database is full 42 | CANTOPEN = C.SQLITE_CANTOPEN // 14 = Unable to open the database file 43 | PROTOCOL = C.SQLITE_PROTOCOL // 15 = Database lock protocol error 44 | EMPTY = C.SQLITE_EMPTY // 16 = Database is empty 45 | SCHEMA = C.SQLITE_SCHEMA // 17 = The database schema changed 46 | TOOBIG = C.SQLITE_TOOBIG // 18 = String or BLOB exceeds size limit 47 | CONSTRAINT = C.SQLITE_CONSTRAINT // 19 = Abort due to constraint violation 48 | MISMATCH = C.SQLITE_MISMATCH // 20 = Data type mismatch 49 | MISUSE = C.SQLITE_MISUSE // 21 = Library used incorrectly 50 | NOLFS = C.SQLITE_NOLFS // 22 = Uses OS features not supported on host 51 | AUTH = C.SQLITE_AUTH // 23 = Authorization denied 52 | FORMAT = C.SQLITE_FORMAT // 24 = Auxiliary database format error 53 | RANGE = C.SQLITE_RANGE // 25 = 2nd parameter to sqlite3_bind out of range 54 | NOTADB = C.SQLITE_NOTADB // 26 = File opened that is not a database file 55 | NOTICE = C.SQLITE_NOTICE // 27 = Notifications from sqlite3_log() 56 | WARNING = C.SQLITE_WARNING // 28 = Warnings from sqlite3_log() 57 | ROW = C.SQLITE_ROW // 100 = sqlite3_step() has another row ready 58 | DONE = C.SQLITE_DONE // 101 = sqlite3_step() has finished executing 59 | ) 60 | 61 | // Extended result codes returned by the SQLite API. Extended result codes are 62 | // enabled by default for all new Conn objects. Use Error.Code()&0xFF to convert 63 | // an extended code to a general one. 64 | // [http://www.sqlite.org/c3ref/c_abort_rollback.html] 65 | const ( 66 | IOERR_READ = C.SQLITE_IOERR_READ // (SQLITE_IOERR | (1<<8)) 67 | IOERR_SHORT_READ = C.SQLITE_IOERR_SHORT_READ // (SQLITE_IOERR | (2<<8)) 68 | IOERR_WRITE = C.SQLITE_IOERR_WRITE // (SQLITE_IOERR | (3<<8)) 69 | IOERR_FSYNC = C.SQLITE_IOERR_FSYNC // (SQLITE_IOERR | (4<<8)) 70 | IOERR_DIR_FSYNC = C.SQLITE_IOERR_DIR_FSYNC // (SQLITE_IOERR | (5<<8)) 71 | IOERR_TRUNCATE = C.SQLITE_IOERR_TRUNCATE // (SQLITE_IOERR | (6<<8)) 72 | IOERR_FSTAT = C.SQLITE_IOERR_FSTAT // (SQLITE_IOERR | (7<<8)) 73 | IOERR_UNLOCK = C.SQLITE_IOERR_UNLOCK // (SQLITE_IOERR | (8<<8)) 74 | IOERR_RDLOCK = C.SQLITE_IOERR_RDLOCK // (SQLITE_IOERR | (9<<8)) 75 | IOERR_DELETE = C.SQLITE_IOERR_DELETE // (SQLITE_IOERR | (10<<8)) 76 | IOERR_BLOCKED = C.SQLITE_IOERR_BLOCKED // (SQLITE_IOERR | (11<<8)) 77 | IOERR_NOMEM = C.SQLITE_IOERR_NOMEM // (SQLITE_IOERR | (12<<8)) 78 | IOERR_ACCESS = C.SQLITE_IOERR_ACCESS // (SQLITE_IOERR | (13<<8)) 79 | IOERR_CHECKRESERVEDLOCK = C.SQLITE_IOERR_CHECKRESERVEDLOCK // (SQLITE_IOERR | (14<<8)) 80 | IOERR_LOCK = C.SQLITE_IOERR_LOCK // (SQLITE_IOERR | (15<<8)) 81 | IOERR_CLOSE = C.SQLITE_IOERR_CLOSE // (SQLITE_IOERR | (16<<8)) 82 | IOERR_DIR_CLOSE = C.SQLITE_IOERR_DIR_CLOSE // (SQLITE_IOERR | (17<<8)) 83 | IOERR_SHMOPEN = C.SQLITE_IOERR_SHMOPEN // (SQLITE_IOERR | (18<<8)) 84 | IOERR_SHMSIZE = C.SQLITE_IOERR_SHMSIZE // (SQLITE_IOERR | (19<<8)) 85 | IOERR_SHMLOCK = C.SQLITE_IOERR_SHMLOCK // (SQLITE_IOERR | (20<<8)) 86 | IOERR_SHMMAP = C.SQLITE_IOERR_SHMMAP // (SQLITE_IOERR | (21<<8)) 87 | IOERR_SEEK = C.SQLITE_IOERR_SEEK // (SQLITE_IOERR | (22<<8)) 88 | IOERR_DELETE_NOENT = C.SQLITE_IOERR_DELETE_NOENT // (SQLITE_IOERR | (23<<8)) 89 | IOERR_MMAP = C.SQLITE_IOERR_MMAP // (SQLITE_IOERR | (24<<8)) 90 | IOERR_GETTEMPPATH = C.SQLITE_IOERR_GETTEMPPATH // (SQLITE_IOERR | (25<<8)) 91 | IOERR_CONVPATH = C.SQLITE_IOERR_CONVPATH // (SQLITE_IOERR | (26<<8)) 92 | LOCKED_SHAREDCACHE = C.SQLITE_LOCKED_SHAREDCACHE // (SQLITE_LOCKED | (1<<8)) 93 | BUSY_RECOVERY = C.SQLITE_BUSY_RECOVERY // (SQLITE_BUSY | (1<<8)) 94 | BUSY_SNAPSHOT = C.SQLITE_BUSY_SNAPSHOT // (SQLITE_BUSY | (2<<8)) 95 | CANTOPEN_NOTEMPDIR = C.SQLITE_CANTOPEN_NOTEMPDIR // (SQLITE_CANTOPEN | (1<<8)) 96 | CANTOPEN_ISDIR = C.SQLITE_CANTOPEN_ISDIR // (SQLITE_CANTOPEN | (2<<8)) 97 | CANTOPEN_FULLPATH = C.SQLITE_CANTOPEN_FULLPATH // (SQLITE_CANTOPEN | (3<<8)) 98 | CANTOPEN_CONVPATH = C.SQLITE_CANTOPEN_CONVPATH // (SQLITE_CANTOPEN | (4<<8)) 99 | CORRUPT_VTAB = C.SQLITE_CORRUPT_VTAB // (SQLITE_CORRUPT | (1<<8)) 100 | READONLY_RECOVERY = C.SQLITE_READONLY_RECOVERY // (SQLITE_READONLY | (1<<8)) 101 | READONLY_CANTLOCK = C.SQLITE_READONLY_CANTLOCK // (SQLITE_READONLY | (2<<8)) 102 | READONLY_ROLLBACK = C.SQLITE_READONLY_ROLLBACK // (SQLITE_READONLY | (3<<8)) 103 | READONLY_DBMOVED = C.SQLITE_READONLY_DBMOVED // (SQLITE_READONLY | (4<<8)) 104 | ABORT_ROLLBACK = C.SQLITE_ABORT_ROLLBACK // (SQLITE_ABORT | (2<<8)) 105 | CONSTRAINT_CHECK = C.SQLITE_CONSTRAINT_CHECK // (SQLITE_CONSTRAINT | (1<<8)) 106 | CONSTRAINT_COMMITHOOK = C.SQLITE_CONSTRAINT_COMMITHOOK // (SQLITE_CONSTRAINT | (2<<8)) 107 | CONSTRAINT_FOREIGNKEY = C.SQLITE_CONSTRAINT_FOREIGNKEY // (SQLITE_CONSTRAINT | (3<<8)) 108 | CONSTRAINT_FUNCTION = C.SQLITE_CONSTRAINT_FUNCTION // (SQLITE_CONSTRAINT | (4<<8)) 109 | CONSTRAINT_NOTNULL = C.SQLITE_CONSTRAINT_NOTNULL // (SQLITE_CONSTRAINT | (5<<8)) 110 | CONSTRAINT_PRIMARYKEY = C.SQLITE_CONSTRAINT_PRIMARYKEY // (SQLITE_CONSTRAINT | (6<<8)) 111 | CONSTRAINT_TRIGGER = C.SQLITE_CONSTRAINT_TRIGGER // (SQLITE_CONSTRAINT | (7<<8)) 112 | CONSTRAINT_UNIQUE = C.SQLITE_CONSTRAINT_UNIQUE // (SQLITE_CONSTRAINT | (8<<8)) 113 | CONSTRAINT_VTAB = C.SQLITE_CONSTRAINT_VTAB // (SQLITE_CONSTRAINT | (9<<8)) 114 | CONSTRAINT_ROWID = C.SQLITE_CONSTRAINT_ROWID // (SQLITE_CONSTRAINT |(10<<8)) 115 | NOTICE_RECOVER_WAL = C.SQLITE_NOTICE_RECOVER_WAL // (SQLITE_NOTICE | (1<<8)) 116 | NOTICE_RECOVER_ROLLBACK = C.SQLITE_NOTICE_RECOVER_ROLLBACK // (SQLITE_NOTICE | (2<<8)) 117 | WARNING_AUTOINDEX = C.SQLITE_WARNING_AUTOINDEX // (SQLITE_WARNING | (1<<8)) 118 | ) 119 | 120 | // Codes used by SQLite to indicate the operation type when invoking authorizer 121 | // and row update callbacks. 122 | // [http://www.sqlite.org/c3ref/c_alter_table.html] 123 | const ( 124 | CREATE_INDEX = C.SQLITE_CREATE_INDEX // 1 125 | CREATE_TABLE = C.SQLITE_CREATE_TABLE // 2 126 | CREATE_TEMP_INDEX = C.SQLITE_CREATE_TEMP_INDEX // 3 127 | CREATE_TEMP_TABLE = C.SQLITE_CREATE_TEMP_TABLE // 4 128 | CREATE_TEMP_TRIGGER = C.SQLITE_CREATE_TEMP_TRIGGER // 5 129 | CREATE_TEMP_VIEW = C.SQLITE_CREATE_TEMP_VIEW // 6 130 | CREATE_TRIGGER = C.SQLITE_CREATE_TRIGGER // 7 131 | CREATE_VIEW = C.SQLITE_CREATE_VIEW // 8 132 | DELETE = C.SQLITE_DELETE // 9 133 | DROP_INDEX = C.SQLITE_DROP_INDEX // 10 134 | DROP_TABLE = C.SQLITE_DROP_TABLE // 11 135 | DROP_TEMP_INDEX = C.SQLITE_DROP_TEMP_INDEX // 12 136 | DROP_TEMP_TABLE = C.SQLITE_DROP_TEMP_TABLE // 13 137 | DROP_TEMP_TRIGGER = C.SQLITE_DROP_TEMP_TRIGGER // 14 138 | DROP_TEMP_VIEW = C.SQLITE_DROP_TEMP_VIEW // 15 139 | DROP_TRIGGER = C.SQLITE_DROP_TRIGGER // 16 140 | DROP_VIEW = C.SQLITE_DROP_VIEW // 17 141 | INSERT = C.SQLITE_INSERT // 18 142 | PRAGMA = C.SQLITE_PRAGMA // 19 143 | READ = C.SQLITE_READ // 20 144 | SELECT = C.SQLITE_SELECT // 21 145 | TRANSACTION = C.SQLITE_TRANSACTION // 22 146 | UPDATE = C.SQLITE_UPDATE // 23 147 | ATTACH = C.SQLITE_ATTACH // 24 148 | DETACH = C.SQLITE_DETACH // 25 149 | ALTER_TABLE = C.SQLITE_ALTER_TABLE // 26 150 | REINDEX = C.SQLITE_REINDEX // 27 151 | ANALYZE = C.SQLITE_ANALYZE // 28 152 | CREATE_VTABLE = C.SQLITE_CREATE_VTABLE // 29 153 | DROP_VTABLE = C.SQLITE_DROP_VTABLE // 30 154 | FUNCTION = C.SQLITE_FUNCTION // 31 155 | SAVEPOINT = C.SQLITE_SAVEPOINT // 32 156 | RECURSIVE = C.SQLITE_RECURSIVE // 33 157 | ) 158 | 159 | // Core SQLite performance counters that can be queried with Status. 160 | // [http://www.sqlite.org/c3ref/c_status_malloc_count.html] 161 | const ( 162 | STATUS_MEMORY_USED = C.SQLITE_STATUS_MEMORY_USED // 0 163 | STATUS_PAGECACHE_USED = C.SQLITE_STATUS_PAGECACHE_USED // 1 164 | STATUS_PAGECACHE_OVERFLOW = C.SQLITE_STATUS_PAGECACHE_OVERFLOW // 2 165 | STATUS_SCRATCH_USED = C.SQLITE_STATUS_SCRATCH_USED // 3 166 | STATUS_SCRATCH_OVERFLOW = C.SQLITE_STATUS_SCRATCH_OVERFLOW // 4 167 | STATUS_MALLOC_SIZE = C.SQLITE_STATUS_MALLOC_SIZE // 5 168 | STATUS_PARSER_STACK = C.SQLITE_STATUS_PARSER_STACK // 6 169 | STATUS_PAGECACHE_SIZE = C.SQLITE_STATUS_PAGECACHE_SIZE // 7 170 | STATUS_SCRATCH_SIZE = C.SQLITE_STATUS_SCRATCH_SIZE // 8 171 | STATUS_MALLOC_COUNT = C.SQLITE_STATUS_MALLOC_COUNT // 9 172 | ) 173 | 174 | // Connection performance counters that can be queried with Conn.Status. 175 | // [http://www.sqlite.org/c3ref/c_dbstatus_options.html] 176 | const ( 177 | DBSTATUS_LOOKASIDE_USED = C.SQLITE_DBSTATUS_LOOKASIDE_USED // 0 178 | DBSTATUS_CACHE_USED = C.SQLITE_DBSTATUS_CACHE_USED // 1 179 | DBSTATUS_SCHEMA_USED = C.SQLITE_DBSTATUS_SCHEMA_USED // 2 180 | DBSTATUS_STMT_USED = C.SQLITE_DBSTATUS_STMT_USED // 3 181 | DBSTATUS_LOOKASIDE_HIT = C.SQLITE_DBSTATUS_LOOKASIDE_HIT // 4 182 | DBSTATUS_LOOKASIDE_MISS_SIZE = C.SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE // 5 183 | DBSTATUS_LOOKASIDE_MISS_FULL = C.SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL // 6 184 | DBSTATUS_CACHE_HIT = C.SQLITE_DBSTATUS_CACHE_HIT // 7 185 | DBSTATUS_CACHE_MISS = C.SQLITE_DBSTATUS_CACHE_MISS // 8 186 | DBSTATUS_CACHE_WRITE = C.SQLITE_DBSTATUS_CACHE_WRITE // 9 187 | DBSTATUS_DEFERRED_FKS = C.SQLITE_DBSTATUS_DEFERRED_FKS // 10 188 | ) 189 | 190 | // Statement performance counters that can be queried with Stmt.Status. 191 | // [http://www.sqlite.org/c3ref/c_stmtstatus_counter.html] 192 | const ( 193 | STMTSTATUS_FULLSCAN_STEP = C.SQLITE_STMTSTATUS_FULLSCAN_STEP // 1 194 | STMTSTATUS_SORT = C.SQLITE_STMTSTATUS_SORT // 2 195 | STMTSTATUS_AUTOINDEX = C.SQLITE_STMTSTATUS_AUTOINDEX // 3 196 | STMTSTATUS_VM_STEP = C.SQLITE_STMTSTATUS_VM_STEP // 4 197 | ) 198 | 199 | // Per-connection limits that can be queried and changed with Conn.Limit. 200 | // [http://www.sqlite.org/c3ref/c_limit_attached.html] 201 | const ( 202 | LIMIT_LENGTH = C.SQLITE_LIMIT_LENGTH // 0 203 | LIMIT_SQL_LENGTH = C.SQLITE_LIMIT_SQL_LENGTH // 1 204 | LIMIT_COLUMN = C.SQLITE_LIMIT_COLUMN // 2 205 | LIMIT_EXPR_DEPTH = C.SQLITE_LIMIT_EXPR_DEPTH // 3 206 | LIMIT_COMPOUND_SELECT = C.SQLITE_LIMIT_COMPOUND_SELECT // 4 207 | LIMIT_VDBE_OP = C.SQLITE_LIMIT_VDBE_OP // 5 208 | LIMIT_FUNCTION_ARG = C.SQLITE_LIMIT_FUNCTION_ARG // 6 209 | LIMIT_ATTACHED = C.SQLITE_LIMIT_ATTACHED // 7 210 | LIMIT_LIKE_PATTERN_LENGTH = C.SQLITE_LIMIT_LIKE_PATTERN_LENGTH // 8 211 | LIMIT_VARIABLE_NUMBER = C.SQLITE_LIMIT_VARIABLE_NUMBER // 9 212 | LIMIT_TRIGGER_DEPTH = C.SQLITE_LIMIT_TRIGGER_DEPTH // 10 213 | ) 214 | -------------------------------------------------------------------------------- /sqlite3/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package sqlite3 provides an interface to SQLite version 3 databases. 7 | 8 | Database connections are created either by using this package directly or with 9 | the "sqlite3" database/sql driver. The direct interface, which is described 10 | below, exposes SQLite-specific features, such as incremental I/O and online 11 | backups. The driver is recommended when your application has to support multiple 12 | database engines. 13 | 14 | Installation 15 | 16 | Minimum requirements are Go 1.1+ with CGO enabled and GCC/MinGW C compiler. The 17 | SQLite amalgamation version 3.8.5 (2014-06-04) is compiled as part of the 18 | package (see http://www.sqlite.org/amalgamation.html). Compilation options are 19 | defined at the top of sqlite3.go (#cgo CFLAGS). Dynamic linking with a shared 20 | SQLite library is not supported. 21 | 22 | Windows users should install mingw-w64 (http://mingw-w64.sourceforge.net/), 23 | TDM64-GCC (http://tdm-gcc.tdragon.net/), or another MinGW distribution, and make 24 | sure that gcc.exe is available from the %PATH%. MSYS is not required. 25 | 26 | Run 'go get github.com/mxk/go-sqlite/sqlite3' to download, build, and install 27 | the package. 28 | 29 | Concurrency 30 | 31 | A single connection instance and all of its derived objects (prepared 32 | statements, backup operations, etc.) may NOT be used concurrently from multiple 33 | goroutines without external synchronization. The only exception is 34 | Conn.Interrupt(), which may be called from another goroutine to abort a 35 | long-running operation. It is safe to use separate connection instances 36 | concurrently, even if they are accessing the same database file. For example: 37 | 38 | // ERROR (without any extra synchronization) 39 | c, _ := sqlite3.Open("sqlite.db") 40 | go use(c) 41 | go use(c) 42 | 43 | // OK 44 | c1, _ := sqlite3.Open("sqlite.db") 45 | c2, _ := sqlite3.Open("sqlite.db") 46 | go use(c1) 47 | go use(c2) 48 | 49 | Maps 50 | 51 | Use NamedArgs map to bind values to named statement parameters (see 52 | http://www.sqlite.org/lang_expr.html#varparam). Use RowMap to retrieve the 53 | current row as a map of column/value pairs. Here is a short example with the 54 | error-handling code omitted for brevity: 55 | 56 | c, _ := sqlite3.Open(":memory:") 57 | c.Exec("CREATE TABLE x(a, b, c)") 58 | 59 | args := sqlite3.NamedArgs{"$a": 1, "$b": "demo"} 60 | c.Exec("INSERT INTO x VALUES($a, $b, $c)", args) // $c will be NULL 61 | 62 | sql := "SELECT rowid, * FROM x" 63 | row := make(sqlite3.RowMap) 64 | for s, err := c.Query(sql); err == nil; err = s.Next() { 65 | var rowid int64 66 | s.Scan(&rowid, row) // Assigns 1st column to rowid, the rest to row 67 | fmt.Println(rowid, row) // Prints "1 map[a:1 b:demo c:]" 68 | } 69 | 70 | Data Types 71 | 72 | See http://www.sqlite.org/datatype3.html for a description of the SQLite data 73 | type system. The following Go data types are supported as arguments to prepared 74 | statements and may be used in NamedArgs: 75 | 76 | Go Type SQLite Type Notes 77 | --------- ----------- ---------------------------------------------------- 78 | NULL Unbound parameters are NULL by default. 79 | int INTEGER 80 | int64 INTEGER 81 | float64 FLOAT 82 | bool INTEGER Converted as false = 0, true = 1. 83 | string TEXT SQLite makes a private copy when the value is bound. 84 | []byte BLOB SQLite makes a private copy when the value is bound. 85 | time.Time INTEGER Converted by calling Unix(). 86 | RawString TEXT SQLite uses the value directly without copying. The 87 | caller must keep a reference to the value for the 88 | duration of the query to prevent garbage collection. 89 | RawBytes BLOB Same as RawString. The value must not be modified 90 | for the duration of the query. 91 | ZeroBlob BLOB Allocates a zero-filled BLOB of the specified length 92 | (e.g. ZeroBlob(4096) allocates 4KB). 93 | 94 | Note that the table above describes how the value is bound to the statement. The 95 | final storage class is determined according to the column affinity rules. 96 | 97 | See http://www.sqlite.org/c3ref/column_blob.html for a description of how column 98 | values are retrieved from the results of a query. The following static Go data 99 | types are supported for retrieving column values: 100 | 101 | Go Type Req. Type Notes 102 | ---------- --------- --------------------------------------------------- 103 | *int INTEGER 104 | *int64 INTEGER 105 | *float64 FLOAT 106 | *bool INTEGER Converted as 0 = false, otherwise true. 107 | *string TEXT The caller receives a copy of the value. 108 | *[]byte BLOB The caller receives a copy of the value. 109 | *time.Time INTEGER Converted by calling time.Unix(). Text values are not 110 | supported, but the conversion can be performed with 111 | the date and time SQL functions. 112 | *RawString TEXT The value is used directly without copying and 113 | remains valid until the next Stmt method call. 114 | *RawBytes BLOB Same as *RawString. The value must not be modified. 115 | Re-slicing is ok, but be careful with append(). 116 | io.Writer BLOB The value is written out directly into the writer. 117 | 118 | For *interface{} and RowMap arguments, the Go data type is dynamically selected 119 | based on the SQLite storage class and column declaration prefix: 120 | 121 | SQLite Type Col. Decl. Go Type Notes 122 | ----------- ---------- --------- ---------------------------------------- 123 | NULL 124 | INTEGER "DATE..." time.Time Converted by calling time.Unix(). 125 | INTEGER "TIME..." time.Time Converted by calling time.Unix(). 126 | INTEGER "BOOL..." bool Converted as 0 = false, otherwise true. 127 | INTEGER int64 128 | FLOAT float64 129 | TEXT string 130 | BLOB []byte 131 | 132 | Database Names 133 | 134 | Methods that require a database name as one of the arguments (e.g. Conn.Path()) 135 | expect the symbolic name by which the database is known to the connection, not a 136 | path to a file. Valid database names are "main", "temp", or a name specified 137 | after the AS clause in an ATTACH statement. 138 | 139 | Callbacks 140 | 141 | SQLite can execute callbacks for various internal events. The package provides 142 | types and methods for registering callback handlers. Unless stated otherwise in 143 | SQLite documentation, callback handlers are not reentrant and must not do 144 | anything to modify the associated database connection. This includes 145 | preparing/running any other SQL statements. The safest bet is to avoid all 146 | interactions with Conn, Stmt, and other related objects within the handler. 147 | 148 | Codecs and Encryption 149 | 150 | SQLite has an undocumented codec API, which operates between the pager and VFS 151 | layers, and is used by the SQLite Encryption Extension (SEE) to encrypt database 152 | and journal contents. Consider purchasing a SEE license if you require 153 | production-quality encryption support (http://www.hwaci.com/sw/sqlite/see.html). 154 | 155 | This package has an experimental API (read: unstable, may eat your data) for 156 | writing codecs in Go. The "codec" subpackage provides additional documentation 157 | and several existing codec implementations. 158 | 159 | Codecs are registered via the RegisterCodec function for a specific key prefix. 160 | For example, the "aes-hmac" codec is initialized when a key in the format 161 | "aes-hmac:<...>" is provided to an attached database. The key format after the 162 | first colon is codec-specific. See CodecFunc for more information. 163 | 164 | The codec API has several limitations. Codecs cannot be used for in-memory or 165 | temporary databases. Once a database is created, the page size and the amount of 166 | reserved space at the end of each page cannot be changed (i.e. "PRAGMA 167 | page_size=N; VACUUM;" will not work). Online backups will fail unless the 168 | destination database has the same page size and reserve values. Bytes 16 through 169 | 23 of page 1 (the database header, see http://www.sqlite.org/fileformat2.html) 170 | cannot be altered, so it is always possible to identify encrypted SQLite 171 | databases. 172 | 173 | The rekey function is currently not implemented. The key can only be changed via 174 | the backup API or by dumping and restoring the database contents. 175 | */ 176 | package sqlite3 177 | -------------------------------------------------------------------------------- /sqlite3/driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | import "C" 8 | 9 | import ( 10 | "database/sql" 11 | "database/sql/driver" 12 | "io" 13 | "reflect" 14 | "time" 15 | "unsafe" 16 | ) 17 | 18 | // Driver implements the interface required by database/sql. 19 | type Driver string 20 | 21 | func register(name string) { 22 | defer func() { recover() }() 23 | sql.Register(name, Driver(name)) 24 | } 25 | 26 | func (Driver) Open(name string) (driver.Conn, error) { 27 | c, err := Open(name) 28 | if err != nil { 29 | return nil, err 30 | } 31 | c.BusyTimeout(5 * time.Second) 32 | return &conn{c}, nil 33 | } 34 | 35 | // conn implements driver.Conn. 36 | type conn struct { 37 | *Conn 38 | } 39 | 40 | func (c *conn) Prepare(query string) (driver.Stmt, error) { 41 | if c.Conn.db == nil { 42 | return nil, driver.ErrBadConn 43 | } 44 | s, err := c.Conn.Prepare(query) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return &stmt{s, false}, nil 49 | } 50 | 51 | func (c *conn) Begin() (driver.Tx, error) { 52 | if c.Conn.db == nil { 53 | return nil, driver.ErrBadConn 54 | } 55 | if err := c.Conn.Begin(); err != nil { 56 | return nil, err 57 | } 58 | return c.Conn, nil 59 | } 60 | 61 | func (c *conn) Exec(query string, args []driver.Value) (driver.Result, error) { 62 | if c.Conn.db == nil { 63 | return nil, driver.ErrBadConn 64 | } 65 | if err := c.Conn.Exec(query, vtoi(args)...); err != nil { 66 | return nil, err 67 | } 68 | // TODO: Do the driver.Result values need to be cached? 69 | return result{c.Conn}, nil 70 | } 71 | 72 | // stmt implements driver.Stmt. 73 | type stmt struct { 74 | *Stmt 75 | closed bool 76 | } 77 | 78 | func (s *stmt) Close() error { 79 | if !s.closed { 80 | s.closed = true 81 | if !s.Stmt.Busy() { 82 | return s.Stmt.Close() 83 | } 84 | } 85 | return nil 86 | } 87 | 88 | func (s *stmt) NumInput() int { 89 | return s.Stmt.NumParams() 90 | } 91 | 92 | func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { 93 | if err := s.Stmt.Exec(vtoi(args)...); err != nil { 94 | return nil, err 95 | } 96 | return result{s.Stmt.Conn()}, nil 97 | } 98 | 99 | func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { 100 | if err := s.Stmt.Query(vtoi(args)...); err != nil && err != io.EOF { 101 | return nil, err 102 | } 103 | return &rows{s, true}, nil 104 | } 105 | 106 | // result implements driver.Result. 107 | type result struct { 108 | *Conn 109 | } 110 | 111 | func (r result) LastInsertId() (int64, error) { 112 | return int64(r.Conn.LastInsertId()), nil 113 | } 114 | 115 | func (r result) RowsAffected() (int64, error) { 116 | return int64(r.Conn.RowsAffected()), nil 117 | } 118 | 119 | // rows implements driver.Rows. 120 | type rows struct { 121 | *stmt 122 | first bool 123 | } 124 | 125 | func (r *rows) Close() error { 126 | if r.stmt.closed { 127 | return r.stmt.Stmt.Close() 128 | } 129 | r.stmt.Stmt.Reset() 130 | return nil 131 | } 132 | 133 | func (r *rows) Next(dest []driver.Value) error { 134 | if r.first { 135 | r.first = false 136 | if !r.stmt.Stmt.Busy() { 137 | return io.EOF 138 | } 139 | } else if err := r.stmt.Stmt.Next(); err != nil { 140 | return err 141 | } 142 | for i := range dest { 143 | v := (*interface{})(&dest[i]) 144 | err := r.stmt.Stmt.scanDynamic(C.int(i), v, true) 145 | if err != nil { 146 | return err 147 | } 148 | } 149 | return nil 150 | } 151 | 152 | // vtoi converts []driver.Value to []interface{} without copying the contents. 153 | func vtoi(v []driver.Value) (i []interface{}) { 154 | if len(v) > 0 { 155 | h := (*reflect.SliceHeader)(unsafe.Pointer(&i)) 156 | h.Data = uintptr(unsafe.Pointer(&v[0])) 157 | h.Len = len(v) 158 | h.Cap = cap(v) 159 | } 160 | return 161 | } 162 | -------------------------------------------------------------------------------- /sqlite3/io.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #include "sqlite3.h" 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "io" 14 | "runtime" 15 | ) 16 | 17 | // ErrBlobFull is returned by BlobIO.Write when there isn't enough space left to 18 | // write the provided bytes. 19 | var ErrBlobFull = &Error{ERROR, "incremental write failed, no space left"} 20 | 21 | // BlobIO is a handle to a single BLOB (binary large object) or TEXT value 22 | // opened for incremental I/O. This allows the value to be treated as a file for 23 | // reading and writing. The value length cannot be changed using this API; use 24 | // an UPDATE statement for that. The recommended way of allocating space for a 25 | // BLOB is to use the ZeroBlob type or the zeroblob() SQL function. 26 | // [http://www.sqlite.org/c3ref/blob.html] 27 | type BlobIO struct { 28 | conn *Conn 29 | blob *C.sqlite3_blob 30 | 31 | row int64 // ROWID of the row containing the BLOB/TEXT value 32 | len int // Value length in bytes 33 | off int // Current read/write offset 34 | } 35 | 36 | // newBlobIO initializes an incremental I/O operation. 37 | func newBlobIO(c *Conn, db, tbl, col string, row int64, rw bool) (*BlobIO, error) { 38 | db += "\x00" 39 | tbl += "\x00" 40 | col += "\x00" 41 | 42 | var blob *C.sqlite3_blob 43 | rc := C.sqlite3_blob_open(c.db, cStr(db), cStr(tbl), cStr(col), 44 | C.sqlite3_int64(row), cBool(rw), &blob) 45 | if rc != OK { 46 | return nil, libErr(rc, c.db) 47 | } 48 | 49 | b := &BlobIO{ 50 | conn: c, 51 | blob: blob, 52 | row: row, 53 | len: int(C.sqlite3_blob_bytes(blob)), 54 | } 55 | runtime.SetFinalizer(b, (*BlobIO).Close) 56 | return b, nil 57 | } 58 | 59 | // Close releases all resources associated with the incremental I/O operation. 60 | // It is important to check the error returned by this method, since disk I/O 61 | // and other types of errors may not be reported until the changes are actually 62 | // committed to the database. 63 | // [http://www.sqlite.org/c3ref/blob_close.html] 64 | func (b *BlobIO) Close() error { 65 | if blob := b.blob; blob != nil { 66 | b.blob = nil 67 | b.len = 0 68 | b.off = 0 69 | runtime.SetFinalizer(b, nil) 70 | if rc := C.sqlite3_blob_close(blob); rc != OK { 71 | return libErr(rc, b.conn.db) 72 | } 73 | } 74 | return nil 75 | } 76 | 77 | // Conn returns the connection that that created this incremental I/O operation. 78 | func (b *BlobIO) Conn() *Conn { 79 | return b.conn 80 | } 81 | 82 | // Row returns the ROWID of the row containing the BLOB/TEXT value. 83 | func (b *BlobIO) Row() int64 { 84 | return b.row 85 | } 86 | 87 | // Len returns the length of the BLOB/TEXT value in bytes. It is not possible to 88 | // read/write/seek beyond this length. The length changes to 0 if the I/O handle 89 | // expires due to an update of any column in the same row. This condition is 90 | // indicated by an ABORT error code returned from Read or Write. An expired 91 | // handle is closed automatically and cannot be reopened. Any writes that 92 | // occurred before the abort are not rolled back. 93 | // [http://www.sqlite.org/c3ref/blob_bytes.html] 94 | func (b *BlobIO) Len() int { 95 | return b.len 96 | } 97 | 98 | // Read implements the io.Reader interface. 99 | // [http://www.sqlite.org/c3ref/blob_read.html] 100 | func (b *BlobIO) Read(p []byte) (n int, err error) { 101 | if b.blob == nil { 102 | return 0, ErrBadIO 103 | } 104 | if b.off >= b.len { 105 | return 0, io.EOF 106 | } 107 | if n = b.len - b.off; len(p) < n { 108 | n = len(p) 109 | } 110 | rc := C.sqlite3_blob_read(b.blob, cBytes(p), C.int(n), C.int(b.off)) 111 | return b.io(rc, n) 112 | } 113 | 114 | // Write implements the io.Writer interface. The number of bytes written is 115 | // always either 0 or len(p). ErrBlobFull is returned if there isn't enough 116 | // space left to write all of p. 117 | // [http://www.sqlite.org/c3ref/blob_write.html] 118 | func (b *BlobIO) Write(p []byte) (n int, err error) { 119 | if b.blob == nil { 120 | return 0, ErrBadIO 121 | } 122 | if n = len(p); b.off+n > b.len { 123 | // Doesn't make sense to do a partial write. Better to return quickly 124 | // and let the caller reallocate the BLOB. 125 | return 0, ErrBlobFull 126 | } 127 | rc := C.sqlite3_blob_write(b.blob, cBytes(p), C.int(n), C.int(b.off)) 128 | return b.io(rc, n) 129 | } 130 | 131 | // Seek implements the io.Seeker interface. 132 | func (b *BlobIO) Seek(offset int64, whence int) (ret int64, err error) { 133 | if b.blob == nil { 134 | return 0, ErrBadIO 135 | } 136 | switch whence { 137 | case 0: 138 | case 1: 139 | offset += int64(b.off) 140 | case 2: 141 | offset += int64(b.len) 142 | default: 143 | return 0, pkgErr(MISUSE, "invalid whence for BlobIO.Seek (%d)", whence) 144 | } 145 | if offset < 0 || offset > int64(b.len) { 146 | return 0, pkgErr(MISUSE, "invalid offset for BlobIO.Seek (%d)", offset) 147 | } 148 | b.off = int(offset) 149 | return offset, nil 150 | } 151 | 152 | // Reopen closes the current value and opens another one in the same column, 153 | // specified by its ROWID. If an error is encountered, the I/O handle becomes 154 | // unusable and is automatically closed. 155 | // [http://www.sqlite.org/c3ref/blob_reopen.html] 156 | func (b *BlobIO) Reopen(row int64) error { 157 | if b.blob == nil { 158 | return ErrBadIO 159 | } 160 | if rc := C.sqlite3_blob_reopen(b.blob, C.sqlite3_int64(row)); rc != OK { 161 | err := libErr(rc, b.conn.db) 162 | b.Close() 163 | return err 164 | } 165 | b.row = row 166 | b.len = int(C.sqlite3_blob_bytes(b.blob)) 167 | b.off = 0 168 | return nil 169 | } 170 | 171 | // io handles the completion of a single Read/Write call. 172 | func (b *BlobIO) io(rc C.int, n int) (int, error) { 173 | if rc == OK { 174 | b.off += n 175 | return n, nil 176 | } 177 | err := libErr(rc, b.conn.db) 178 | if rc == ABORT { 179 | b.Close() 180 | } 181 | return 0, err 182 | } 183 | -------------------------------------------------------------------------------- /sqlite3/lib/codec.c: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #if defined(SQLITE_AMALGAMATION) && defined(SQLITE_HAS_CODEC) 6 | 7 | #include "codec.h" 8 | 9 | // codec.go exports. 10 | int go_codec_init(const CodecCtx*,void**,char**); 11 | int go_codec_reserve(void*); 12 | void go_codec_resize(void*,int,int); 13 | void *go_codec_exec(void*,void*,u32,int); 14 | void go_codec_get_key(void*,void**,int*); 15 | void go_codec_free(void*); 16 | 17 | // sqlite3_key sets the codec key for the main database. 18 | SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) { 19 | return sqlite3_key_v2(db, 0, pKey, nKey); 20 | } 21 | 22 | // sqlite3_key_v2 sets the codec key for the specified database. 23 | SQLITE_API int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { 24 | int iDb = 0; 25 | int rc; 26 | sqlite3_mutex_enter(db->mutex); 27 | if (zDb && zDb[0]) { 28 | iDb = sqlite3FindDbName(db, zDb); 29 | } 30 | if (iDb < 0) { 31 | rc = SQLITE_ERROR; 32 | sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); 33 | } else { 34 | rc = sqlite3CodecAttach(db, iDb, pKey, nKey); 35 | } 36 | rc = sqlite3ApiExit(db, rc); 37 | sqlite3_mutex_leave(db->mutex); 38 | return rc; 39 | } 40 | 41 | // sqlite3_rekey changes the codec key for the main database. 42 | SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { 43 | return sqlite3_rekey_v2(db, 0, pKey, nKey); 44 | } 45 | 46 | // sqlite3_rekey_v2 changes the codec key for the specified database. 47 | SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { 48 | int iDb = 0; 49 | int rc; 50 | sqlite3_mutex_enter(db->mutex); 51 | 52 | rc = SQLITE_ERROR; 53 | sqlite3Error(db, SQLITE_ERROR, "rekey is not implemented"); 54 | 55 | rc = sqlite3ApiExit(db, rc); 56 | sqlite3_mutex_leave(db->mutex); 57 | return rc; 58 | } 59 | 60 | // sqlite3_activate_see isn't used by Go codecs, but it needs to be linked in. 61 | SQLITE_API void sqlite3_activate_see(const char *zPassPhrase) {} 62 | 63 | // sqlite3CodecAttach initializes the codec, reserves space at the end of each 64 | // page, and attaches the codec to the specified database. 65 | int sqlite3CodecAttach(sqlite3 *db, int iDb, const void *pKey, int nKey) { 66 | Btree *pBt = db->aDb[iDb].pBt; 67 | Pager *pPager = sqlite3BtreePager(pBt); 68 | CodecCtx ctx; 69 | void *pCodec = 0; 70 | char *zErrMsg = 0; 71 | int rc; 72 | 73 | // An empty KEY clause in an ATTACH statement disables the codec and SQLite 74 | // doesn't support codecs for in-memory databases. 75 | if (nKey <= 0 || pPager->memDb) return SQLITE_OK; 76 | 77 | ctx.db = db; 78 | ctx.zPath = sqlite3BtreeGetFilename(pBt); 79 | ctx.zName = db->aDb[iDb].zName; 80 | ctx.nBuf = sqlite3BtreeGetPageSize(pBt); 81 | ctx.nRes = sqlite3BtreeGetReserve(pBt); 82 | ctx.pKey = pKey; 83 | ctx.nKey = nKey; 84 | 85 | sqlite3BtreeEnter(pBt); 86 | ctx.fixed = (pBt->pBt->btsFlags & BTS_PAGESIZE_FIXED) != 0; 87 | sqlite3BtreeLeave(pBt); 88 | 89 | if ((rc=go_codec_init(&ctx, &pCodec, &zErrMsg)) != SQLITE_OK) { 90 | sqlite3Error(db, rc, (zErrMsg ? "%s" : 0), zErrMsg); 91 | free(zErrMsg); 92 | } else if (pCodec) { 93 | int nRes = go_codec_reserve(pCodec); 94 | if (nRes != ctx.nRes && nRes >= 0) { 95 | rc = sqlite3BtreeSetPageSize(pBt, -1, nRes, 0); 96 | } 97 | if (rc != SQLITE_OK) { 98 | go_codec_free(pCodec); 99 | sqlite3Error(db, rc, "unable to reserve page space for the codec"); 100 | } else { 101 | sqlite3PagerSetCodec(pPager, go_codec_exec, go_codec_resize, go_codec_free, pCodec); 102 | } 103 | } 104 | return rc; 105 | } 106 | 107 | // sqlite3CodecGetKey returns the codec key for the specified database. 108 | void sqlite3CodecGetKey(sqlite3 *db, int iDb, void **pKey, int *nKey) { 109 | void *pCodec = sqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[iDb].pBt)); 110 | *pKey = 0; 111 | *nKey = 0; 112 | if (pCodec) { 113 | go_codec_get_key(pCodec, pKey, nKey); 114 | } 115 | } 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /sqlite3/lib/codec.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #ifndef _CODEC_H_ 6 | #define _CODEC_H_ 7 | 8 | // Codec initialization context. 9 | typedef struct CodecCtx { 10 | sqlite3 *db; 11 | const char *zPath; 12 | const char *zName; 13 | int nBuf; 14 | int nRes; 15 | int fixed; 16 | const void *pKey; 17 | int nKey; 18 | } CodecCtx; 19 | 20 | // SQLite codec hooks. 21 | int sqlite3CodecAttach(sqlite3*,int,const void*,int); 22 | void sqlite3CodecGetKey(sqlite3*,int,void**,int*); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sqlite3/sqlite3.c: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #include "lib/sqlite3.c" 6 | #include "lib/codec.c" 7 | -------------------------------------------------------------------------------- /sqlite3/sqlite3.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | // SQLite compilation options. 9 | // [http://www.sqlite.org/compile.html] 10 | // [http://www.sqlite.org/footprint.html] 11 | #cgo CFLAGS: -std=gnu99 12 | #cgo CFLAGS: -Os 13 | #cgo CFLAGS: -DNDEBUG=1 14 | #cgo CFLAGS: -DSQLITE_CORE=1 15 | #cgo CFLAGS: -DSQLITE_THREADSAFE=2 16 | #cgo CFLAGS: -DSQLITE_TEMP_STORE=2 17 | #cgo CFLAGS: -DSQLITE_USE_URI=1 18 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 19 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS4=1 20 | #cgo CFLAGS: -DSQLITE_ENABLE_RTREE=1 21 | #cgo CFLAGS: -DSQLITE_ENABLE_STAT3=1 22 | #cgo CFLAGS: -DSQLITE_SOUNDEX=1 23 | #cgo CFLAGS: -DSQLITE_OMIT_AUTHORIZATION=1 24 | #cgo CFLAGS: -DSQLITE_OMIT_AUTOINIT=1 25 | #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION=1 26 | #cgo CFLAGS: -DSQLITE_OMIT_TRACE=1 27 | #cgo CFLAGS: -DSQLITE_OMIT_UTF16=1 28 | #cgo CFLAGS: -DSQLITE_HAS_CODEC=1 29 | 30 | // Fix for BusyTimeout on *nix systems. 31 | #cgo !windows CFLAGS: -DHAVE_USLEEP=1 32 | 33 | // Fix "_localtime32(0): not defined" linker error. 34 | #cgo windows,386 CFLAGS: -D_localtime32=localtime 35 | 36 | #include "sqlite3.h" 37 | 38 | // cgo doesn't handle variadic functions. 39 | static void set_temp_dir(const char *path) { 40 | sqlite3_temp_directory = sqlite3_mprintf("%s", path); 41 | } 42 | 43 | // cgo doesn't handle SQLITE_{STATIC,TRANSIENT} pointer constants. 44 | static int bind_text(sqlite3_stmt *s, int i, const char *p, int n, int copy) { 45 | if (n > 0) { 46 | return sqlite3_bind_text(s, i, p, n, 47 | (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); 48 | } 49 | return sqlite3_bind_text(s, i, "", 0, SQLITE_STATIC); 50 | } 51 | static int bind_blob(sqlite3_stmt *s, int i, const void *p, int n, int copy) { 52 | if (n > 0) { 53 | return sqlite3_bind_blob(s, i, p, n, 54 | (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); 55 | } 56 | return sqlite3_bind_zeroblob(s, i, 0); 57 | } 58 | 59 | // Faster retrieval of column data types (1 cgo call instead of n). 60 | static void column_types(sqlite3_stmt *s, unsigned char p[], int n) { 61 | int i = 0; 62 | for (; i < n; ++i, ++p) { 63 | *p = sqlite3_column_type(s, i); 64 | } 65 | } 66 | 67 | // Wrappers for sqlite3_key_v2 and sqlite3_rekey_v2 that allow codec support to 68 | // be disabled. 69 | static int codec_key(sqlite3 *db, const char *name, const void *p, int n) { 70 | #ifdef SQLITE_HAS_CODEC 71 | return sqlite3_key_v2(db, name, (n > 0 ? p : 0), n); 72 | #else 73 | return -1; 74 | #endif 75 | } 76 | static int codec_rekey(sqlite3 *db, const char *name, const void *p, int n) { 77 | #ifdef SQLITE_HAS_CODEC 78 | return sqlite3_rekey_v2(db, name, (n > 0 ? p : 0), n); 79 | #else 80 | return -1; 81 | #endif 82 | } 83 | 84 | // Macro for creating callback setter functions. 85 | #define SET(x) \ 86 | static void set_##x(sqlite3 *db, void *conn, int enable) { \ 87 | (enable ? sqlite3_##x(db, go_##x, conn) : sqlite3_##x(db, 0, 0)); \ 88 | } 89 | 90 | // util.go exports. 91 | int go_busy_handler(void*,int); 92 | int go_commit_hook(void*); 93 | void go_rollback_hook(void*); 94 | void go_update_hook(void*,int,const char*,const char*,sqlite3_int64); 95 | 96 | SET(busy_handler) 97 | SET(commit_hook) 98 | SET(rollback_hook) 99 | SET(update_hook) 100 | */ 101 | import "C" 102 | 103 | import ( 104 | "io" 105 | "os" 106 | "runtime" 107 | "strings" 108 | "time" 109 | "unsafe" 110 | ) 111 | 112 | // initErr indicates a SQLite initialization error, which disables this package. 113 | var initErr error 114 | 115 | func init() { 116 | // Initialize SQLite (required with SQLITE_OMIT_AUTOINIT). 117 | // [http://www.sqlite.org/c3ref/initialize.html] 118 | if rc := C.sqlite3_initialize(); rc != OK { 119 | initErr = libErr(rc, nil) 120 | return 121 | } 122 | 123 | // Use the same temporary directory as Go. 124 | // [http://www.sqlite.org/c3ref/temp_directory.html] 125 | tmp := os.TempDir() + "\x00" 126 | C.set_temp_dir(cStr(tmp)) 127 | 128 | // Register database/sql driver. 129 | register("sqlite3") 130 | } 131 | 132 | // Conn is a connection handle, which may have multiple databases attached to it 133 | // by using the ATTACH SQL statement. 134 | // [http://www.sqlite.org/c3ref/sqlite3.html] 135 | type Conn struct { 136 | db *C.sqlite3 137 | 138 | // Callback handlers executed by the exported go_* functions. 139 | busy BusyFunc 140 | commit CommitFunc 141 | rollback RollbackFunc 142 | update UpdateFunc 143 | } 144 | 145 | // Open creates a new connection to a SQLite database. The name can be 1) a path 146 | // to a file, which is created if it does not exist, 2) a URI using the syntax 147 | // described at http://www.sqlite.org/uri.html, 3) the string ":memory:", which 148 | // creates a temporary in-memory database, or 4) an empty string, which creates 149 | // a temporary on-disk database (deleted when closed) in the directory returned 150 | // by os.TempDir(). 151 | // [http://www.sqlite.org/c3ref/open.html] 152 | func Open(name string) (*Conn, error) { 153 | if initErr != nil { 154 | return nil, initErr 155 | } 156 | name += "\x00" 157 | 158 | var db *C.sqlite3 159 | rc := C.sqlite3_open_v2(cStr(name), &db, 160 | C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE, nil) 161 | if rc != OK { 162 | err := libErr(rc, db) 163 | C.sqlite3_close(db) 164 | return nil, err 165 | } 166 | c := &Conn{db: db} 167 | C.sqlite3_extended_result_codes(db, 1) 168 | runtime.SetFinalizer(c, (*Conn).Close) 169 | return c, nil 170 | } 171 | 172 | // Close releases all resources associated with the connection. If any prepared 173 | // statements, incremental I/O operations, or backup operations are still 174 | // active, the connection becomes an unusable "zombie" and is closed after all 175 | // remaining statements and operations are destroyed. A BUSY error code is 176 | // returned if the connection is left in this "zombie" status, which may 177 | // indicate a programming error where some previously allocated resource is not 178 | // properly released. 179 | // [http://www.sqlite.org/c3ref/close.html] 180 | func (c *Conn) Close() error { 181 | if db := c.db; db != nil { 182 | c.db = nil 183 | runtime.SetFinalizer(c, nil) 184 | if rc := C.sqlite3_close(db); rc != OK { 185 | err := libErr(rc, db) 186 | if rc == BUSY { 187 | C.sqlite3_close_v2(db) 188 | } 189 | return err 190 | } 191 | *c = Conn{} // Clear callback handlers only if db was closed 192 | } 193 | return nil 194 | } 195 | 196 | // Prepare compiles the first statement in sql. Any remaining text after the 197 | // first statement is saved in Stmt.Tail. 198 | // [http://www.sqlite.org/c3ref/prepare.html] 199 | func (c *Conn) Prepare(sql string) (*Stmt, error) { 200 | if c.db == nil { 201 | return nil, ErrBadConn 202 | } 203 | return newStmt(c, sql) 204 | } 205 | 206 | // Exec is a convenience method for executing one or more statements in sql. 207 | // Arguments may be specified either as a list of unnamed interface{} values or 208 | // as a single NamedArgs map. In unnamed mode, each statement consumes the 209 | // required number of values from args. For example: 210 | // 211 | // c.Exec("UPDATE x SET a=?; UPDATE x SET b=?", 1, 2) // is executed as: 212 | // // UPDATE x SET a=1 213 | // // UPDATE x SET b=2 214 | // 215 | // With NamedArgs, the entire map is passed to every statement in sql and 216 | // unreferenced names are ignored. The following example is identical to the 217 | // previous one: 218 | // 219 | // args := NamedArgs{"$a": 1, "$b": 2} 220 | // c.Exec("UPDATE x SET a=$a; UPDATE x SET b=$b", args) 221 | // 222 | // Without any extra arguments, the statements in sql are executed by a single 223 | // call to sqlite3_exec. 224 | // [http://www.sqlite.org/c3ref/exec.html] 225 | func (c *Conn) Exec(sql string, args ...interface{}) error { 226 | if c.db == nil { 227 | return ErrBadConn 228 | } 229 | 230 | // Fast path via sqlite3_exec, which doesn't support parameter binding 231 | if len(args) == 0 { 232 | sql += "\x00" 233 | return c.exec(cStr(sql)) 234 | } 235 | 236 | // Slow path via Prepare -> Exec -> Close 237 | unnamed := namedArgs(args) == nil 238 | execNext := func() error { 239 | s, err := newStmt(c, sql) 240 | if err != nil { 241 | return err 242 | } 243 | defer s.Close() 244 | 245 | sql = s.Tail 246 | if s.stmt == nil { 247 | return nil // Comment or whitespace 248 | } 249 | if s.nVars == 0 { 250 | return s.exec(nil) 251 | } 252 | sArgs := args 253 | if unnamed { 254 | if s.nVars < len(sArgs) { 255 | sArgs = sArgs[:s.nVars] 256 | } 257 | args = args[len(sArgs):] 258 | } 259 | return s.exec(sArgs) 260 | } 261 | for sql != "" { 262 | if err := execNext(); err != nil { 263 | return err 264 | } 265 | } 266 | if unnamed && len(args) != 0 { 267 | return pkgErr(MISUSE, "%d unconsumed argument(s)", len(args)) 268 | } 269 | return nil 270 | } 271 | 272 | // Query is a convenience method for executing the first query in sql. It 273 | // returns either a prepared statement ready for scanning or an error, which 274 | // will be io.EOF if the query did not return any rows. 275 | func (c *Conn) Query(sql string, args ...interface{}) (*Stmt, error) { 276 | if c.db == nil { 277 | return nil, ErrBadConn 278 | } 279 | s, err := newStmt(c, sql) 280 | if err == nil { 281 | if err = s.Query(args...); err == nil { 282 | return s, nil 283 | } 284 | s.Close() 285 | } 286 | return nil, err 287 | } 288 | 289 | // Begin starts a new deferred transaction. Use c.Exec("BEGIN...") to start an 290 | // immediate or an exclusive transaction. 291 | // [http://www.sqlite.org/lang_transaction.html] 292 | func (c *Conn) Begin() error { 293 | if c.db == nil { 294 | return ErrBadConn 295 | } 296 | return c.exec(cStr("BEGIN\x00")) 297 | } 298 | 299 | // Commit saves all changes made within a transaction to the database. 300 | func (c *Conn) Commit() error { 301 | if c.db == nil { 302 | return ErrBadConn 303 | } 304 | return c.exec(cStr("COMMIT\x00")) 305 | } 306 | 307 | // Rollback aborts the current transaction without saving any changes. 308 | func (c *Conn) Rollback() error { 309 | if c.db == nil { 310 | return ErrBadConn 311 | } 312 | return c.exec(cStr("ROLLBACK\x00")) 313 | } 314 | 315 | // Interrupt causes any pending database operation to abort and return at its 316 | // earliest opportunity. It is safe to call this method from a goroutine 317 | // different from the one that is currently running the database operation, but 318 | // it is not safe to call this method on a connection that might close before 319 | // the call returns. 320 | // [http://www.sqlite.org/c3ref/interrupt.html] 321 | func (c *Conn) Interrupt() { 322 | if db := c.db; db != nil { 323 | C.sqlite3_interrupt(db) 324 | } 325 | } 326 | 327 | // AutoCommit returns true if the database connection is in auto-commit mode 328 | // (i.e. outside of an explicit transaction started by BEGIN). 329 | // [http://www.sqlite.org/c3ref/get_autocommit.html] 330 | func (c *Conn) AutoCommit() bool { 331 | if c.db == nil { 332 | return false 333 | } 334 | return C.sqlite3_get_autocommit(c.db) != 0 335 | } 336 | 337 | // LastInsertId returns the ROWID of the most recent successful INSERT 338 | // statement. 339 | // [http://www.sqlite.org/c3ref/last_insert_rowid.html] 340 | func (c *Conn) LastInsertId() int64 { 341 | if c.db == nil { 342 | return 0 343 | } 344 | return int64(C.sqlite3_last_insert_rowid(c.db)) 345 | } 346 | 347 | // RowsAffected returns the number of rows that were changed, inserted, or 348 | // deleted by the most recent statement. Auxiliary changes caused by triggers or 349 | // foreign key actions are not counted. 350 | // [http://www.sqlite.org/c3ref/changes.html] 351 | func (c *Conn) RowsAffected() int { 352 | if c.db == nil { 353 | return 0 354 | } 355 | return int(C.sqlite3_changes(c.db)) 356 | } 357 | 358 | // TotalRowsAffected returns the number of rows that were changed, inserted, or 359 | // deleted since the database connection was opened, including changes caused by 360 | // trigger and foreign key actions. 361 | // [http://www.sqlite.org/c3ref/total_changes.html] 362 | func (c *Conn) TotalRowsAffected() int { 363 | if c.db == nil { 364 | return 0 365 | } 366 | return int(C.sqlite3_total_changes(c.db)) 367 | } 368 | 369 | // Backup starts an online database backup of c.srcName into dst.dstName. 370 | // Connections c and dst must be distinct. All existing contents of the 371 | // destination database are overwritten. 372 | // 373 | // A read lock is acquired on the source database only while it is being read 374 | // during a call to Backup.Step. The source connection may be used for other 375 | // purposes between these calls. The destination connection must not be used for 376 | // anything until the backup is closed. 377 | // [http://www.sqlite.org/backup.html] 378 | func (c *Conn) Backup(srcName string, dst *Conn, dstName string) (*Backup, error) { 379 | if c.db == nil || c == dst || dst == nil || dst.db == nil { 380 | return nil, ErrBadConn 381 | } 382 | return newBackup(c, srcName, dst, dstName) 383 | } 384 | 385 | // BlobIO opens a BLOB or TEXT value for incremental I/O, allowing the value to 386 | // be treated as a file for reading and/or writing. The value is located as if 387 | // by the following query: 388 | // 389 | // SELECT col FROM db.tbl WHERE rowid=row 390 | // 391 | // If rw is true, the value is opened with read-write access, otherwise it is 392 | // read-only. It is not possible to open a column that is part of an index or 393 | // primary key for writing. If foreign key constraints are enabled, it is not 394 | // possible to open a column that is part of a child key for writing. 395 | // [http://www.sqlite.org/c3ref/blob_open.html] 396 | func (c *Conn) BlobIO(db, tbl, col string, row int64, rw bool) (*BlobIO, error) { 397 | if c.db == nil { 398 | return nil, ErrBadConn 399 | } 400 | return newBlobIO(c, db, tbl, col, row, rw) 401 | } 402 | 403 | // BusyTimeout enables the built-in busy handler, which retries the table 404 | // locking operation for the specified duration before aborting. It returns the 405 | // callback function that was previously registered with Conn.BusyFunc, if any. 406 | // The busy handler is disabled if d is negative or zero. 407 | // [http://www.sqlite.org/c3ref/busy_timeout.html] 408 | func (c *Conn) BusyTimeout(d time.Duration) (prev BusyFunc) { 409 | if c.db != nil { 410 | // BUG(mxk): The SQL statement "PRAGMA busy_timeout = n" does not clear 411 | // the BusyFunc registered with the connection (if there is one). This 412 | // causes the next call to Conn.BusyTimeout or Conn.BusyFunc to return a 413 | // previous handler that wasn't actually being used. This doesn't affect 414 | // the operation of SQLite in any way. Use Conn.BusyTimeout instead of 415 | // the PRAGMA to avoid this problem if the return value is important. 416 | prev, c.busy = c.busy, nil 417 | C.sqlite3_busy_timeout(c.db, C.int(d/time.Millisecond)) 418 | } 419 | return 420 | } 421 | 422 | // BusyFunc registers a function that is invoked by SQLite when it is unable to 423 | // acquire a lock on a table. It returns the previous busy handler, if any. The 424 | // function f should return true to make another lock acquisition attempt, or 425 | // false to let the operation fail with BUSY or IOERR_BLOCKED error code. 426 | // [http://www.sqlite.org/c3ref/busy_handler.html] 427 | func (c *Conn) BusyFunc(f BusyFunc) (prev BusyFunc) { 428 | if c.db != nil { 429 | prev, c.busy = c.busy, f 430 | C.set_busy_handler(c.db, unsafe.Pointer(c), cBool(f != nil)) 431 | } 432 | return 433 | } 434 | 435 | // CommitFunc registers a function that is invoked by SQLite before a 436 | // transaction is committed. It returns the previous commit handler, if any. If 437 | // the function f returns true, the transaction is rolled back instead, causing 438 | // the rollback handler to be invoked, if one is registered. 439 | // [http://www.sqlite.org/c3ref/commit_hook.html] 440 | func (c *Conn) CommitFunc(f CommitFunc) (prev CommitFunc) { 441 | if c.db != nil { 442 | prev, c.commit = c.commit, f 443 | C.set_commit_hook(c.db, unsafe.Pointer(c), cBool(f != nil)) 444 | } 445 | return 446 | } 447 | 448 | // RollbackFunc registers a function that is invoked by SQLite when a 449 | // transaction is rolled back. It returns the previous rollback handler, if any. 450 | // [http://www.sqlite.org/c3ref/commit_hook.html] 451 | func (c *Conn) RollbackFunc(f RollbackFunc) (prev RollbackFunc) { 452 | if c.db != nil { 453 | prev, c.rollback = c.rollback, f 454 | C.set_rollback_hook(c.db, unsafe.Pointer(c), cBool(f != nil)) 455 | } 456 | return 457 | } 458 | 459 | // UpdateFunc registers a function that is invoked by SQLite when a row is 460 | // updated, inserted, or deleted. It returns the previous update handler, if 461 | // any. 462 | // [http://www.sqlite.org/c3ref/update_hook.html] 463 | func (c *Conn) UpdateFunc(f UpdateFunc) (prev UpdateFunc) { 464 | if c.db != nil { 465 | prev, c.update = c.update, f 466 | C.set_update_hook(c.db, unsafe.Pointer(c), cBool(f != nil)) 467 | } 468 | return 469 | } 470 | 471 | // Key provides a codec key to an attached database. This method should be 472 | // called right after opening the connection. 473 | func (c *Conn) Key(db string, key []byte) error { 474 | if c.db == nil { 475 | return ErrBadConn 476 | } 477 | db += "\x00" 478 | rc := C.codec_key(c.db, cStr(db), cBytes(key), C.int(len(key))) 479 | if rc != OK { 480 | if rc == -1 { 481 | return pkgErr(ERROR, "codec support is disabled") 482 | } 483 | return libErr(rc, c.db) 484 | } 485 | return nil 486 | } 487 | 488 | // Rekey changes the codec key for an attached database. This is not currently 489 | // implemented for Go codecs. 490 | func (c *Conn) Rekey(db string, key []byte) error { 491 | if c.db == nil { 492 | return ErrBadConn 493 | } 494 | db += "\x00" 495 | rc := C.codec_rekey(c.db, cStr(db), cBytes(key), C.int(len(key))) 496 | if rc != OK { 497 | if rc == -1 { 498 | return pkgErr(ERROR, "codec support is disabled") 499 | } 500 | return libErr(rc, c.db) 501 | } 502 | return nil 503 | } 504 | 505 | // Path returns the full file path of an attached database. An empty string is 506 | // returned for temporary databases. 507 | // [http://www.sqlite.org/c3ref/db_filename.html] 508 | func (c *Conn) Path(db string) string { 509 | if c.db != nil { 510 | db += "\x00" 511 | if path := C.sqlite3_db_filename(c.db, cStr(db)); path != nil { 512 | return C.GoString(path) 513 | } 514 | } 515 | return "" 516 | } 517 | 518 | // Status returns the current and peak values of a connection performance 519 | // counter, specified by one of the DBSTATUS constants. If reset is true, the 520 | // peak value is reset back down to the current value after retrieval. 521 | // [http://www.sqlite.org/c3ref/db_status.html] 522 | func (c *Conn) Status(op int, reset bool) (cur, peak int, err error) { 523 | if c.db == nil { 524 | return 0, 0, ErrBadConn 525 | } 526 | var cCur, cPeak C.int 527 | rc := C.sqlite3_db_status(c.db, C.int(op), &cCur, &cPeak, cBool(reset)) 528 | if rc != OK { 529 | return 0, 0, pkgErr(MISUSE, "invalid connection status op (%d)", op) 530 | } 531 | return int(cCur), int(cPeak), nil 532 | } 533 | 534 | // Limit changes a per-connection resource usage or performance limit, specified 535 | // by one of the LIMIT constants, returning its previous value. If the new value 536 | // is negative, the limit is left unchanged and its current value is returned. 537 | // [http://www.sqlite.org/c3ref/limit.html] 538 | func (c *Conn) Limit(id, value int) (prev int) { 539 | if c.db != nil { 540 | prev = int(C.sqlite3_limit(c.db, C.int(id), C.int(value))) 541 | } 542 | return 543 | } 544 | 545 | // exec calls sqlite3_exec on sql, which must be a null-terminated C string. 546 | func (c *Conn) exec(sql *C.char) error { 547 | if rc := C.sqlite3_exec(c.db, sql, nil, nil, nil); rc != OK { 548 | return libErr(rc, c.db) 549 | } 550 | return nil 551 | } 552 | 553 | // Stmt is a prepared statement handle. 554 | // 555 | // SQLite automatically recompiles prepared statements when the database schema 556 | // changes. A query like "SELECT * FROM x" may return a different number of 557 | // columns from one execution to the next if the table is altered. The 558 | // recompilation, if required, only happens at the start of execution (during a 559 | // call to Exec or Query). Statements that are already running (Busy() == true) 560 | // are not recompiled. Thus, the safest way of obtaining column information is 561 | // to call Exec or Query first, followed by NumColumns, Columns, DeclTypes, etc. 562 | // [http://www.sqlite.org/c3ref/stmt.html] 563 | type Stmt struct { 564 | Tail string // Uncompiled portion of the SQL string passed to Conn.Prepare 565 | 566 | conn *Conn 567 | stmt *C.sqlite3_stmt 568 | 569 | text string // SQL text used to create this statement (minus the Tail) 570 | nVars int // Number of bound parameters (or maximum ?NNN value) 571 | nCols int // Number of columns in each row (for the current run) 572 | haveRow bool // Flag indicating row availability 573 | 574 | varNames []string // Names of bound parameters 575 | colNames []string // Names of columns in the result set 576 | colDecls []string // Column type declarations in upper case 577 | colTypes []uint8 // Data type codes for all columns in the current row 578 | } 579 | 580 | // newStmt creates a new prepared statement. 581 | func newStmt(c *Conn, sql string) (*Stmt, error) { 582 | zSql := sql + "\x00" 583 | 584 | var stmt *C.sqlite3_stmt 585 | var tail *C.char 586 | rc := C.sqlite3_prepare_v2(c.db, cStr(zSql), -1, &stmt, &tail) 587 | if rc != OK { 588 | return nil, libErr(rc, c.db) 589 | } 590 | 591 | // stmt will be nil if sql contained only comments or whitespace. s.Tail may 592 | // be useful to the caller, so s is still returned without an error. 593 | s := &Stmt{conn: c, stmt: stmt} 594 | if stmt != nil { 595 | if s.nVars = int(C.sqlite3_bind_parameter_count(stmt)); s.nVars == 0 { 596 | s.varNames = unnamedVars 597 | } 598 | s.nCols = int(C.sqlite3_column_count(stmt)) 599 | runtime.SetFinalizer(s, (*Stmt).Close) 600 | } 601 | if tail != nil { 602 | if n := cStrOffset(zSql, tail); n < len(sql) { 603 | sql, s.Tail = sql[:n], sql[n:] 604 | } 605 | } 606 | s.text = sql 607 | return s, nil 608 | } 609 | 610 | // Close releases all resources associated with the prepared statement. This 611 | // method can be called at any point in the statement's life cycle. 612 | // [http://www.sqlite.org/c3ref/finalize.html] 613 | func (s *Stmt) Close() error { 614 | if stmt := s.stmt; stmt != nil { 615 | *s = Stmt{Tail: s.Tail, conn: s.conn, text: s.text} 616 | runtime.SetFinalizer(s, nil) 617 | if rc := C.sqlite3_finalize(stmt); rc != OK { 618 | return libErr(rc, s.conn.db) 619 | } 620 | } 621 | return nil 622 | } 623 | 624 | // Conn returns the connection that that created this prepared statement. 625 | func (s *Stmt) Conn() *Conn { 626 | return s.conn 627 | } 628 | 629 | // Valid returns true if the prepared statement can be executed by calling Exec 630 | // or Query. A new prepared statement may not be valid if the SQL string 631 | // contained nothing but comments or whitespace. 632 | func (s *Stmt) Valid() bool { 633 | return s.stmt != nil 634 | } 635 | 636 | // Busy returns true if the prepared statement is in the middle of execution 637 | // with a row available for scanning. It is not necessary to reset a busy 638 | // statement before making another call to Exec or Query. 639 | func (s *Stmt) Busy() bool { 640 | return s.haveRow 641 | } 642 | 643 | // ReadOnly returns true if the prepared statement makes no direct changes to 644 | // the content of the database file. 645 | // [http://www.sqlite.org/c3ref/stmt_readonly.html] 646 | func (s *Stmt) ReadOnly() bool { 647 | return s.stmt == nil || C.sqlite3_stmt_readonly(s.stmt) != 0 648 | } 649 | 650 | // String returns the SQL text that was used to create this prepared statement. 651 | // [http://www.sqlite.org/c3ref/sql.html] 652 | func (s *Stmt) String() string { 653 | return s.text 654 | } 655 | 656 | // NumParams returns the number of bound parameters in the prepared statement. 657 | // This is also the number of arguments required for calling Exec or Query 658 | // without a NamedArgs map. 659 | // [http://www.sqlite.org/c3ref/bind_parameter_count.html] 660 | func (s *Stmt) NumParams() int { 661 | return s.nVars 662 | } 663 | 664 | // NumColumns returns the number of columns produced by the prepared statement. 665 | // [http://www.sqlite.org/c3ref/column_count.html] 666 | func (s *Stmt) NumColumns() int { 667 | return s.nCols 668 | } 669 | 670 | // unnamedVars is assigned to Stmt.varNames if the prepared statement does not 671 | // use named parameters. It just causes s.varNames == nil to evaluate to false. 672 | var unnamedVars = make([]string, 0, 1) 673 | 674 | // Params returns the names of bound parameters in the prepared statement. Nil 675 | // is returned if the statement does not use named parameters. 676 | // [http://www.sqlite.org/c3ref/bind_parameter_name.html] 677 | func (s *Stmt) Params() []string { 678 | if s.varNames == nil { 679 | var names []string 680 | for i := 0; i < s.nVars; i++ { 681 | name := C.sqlite3_bind_parameter_name(s.stmt, C.int(i+1)) 682 | if name == nil { 683 | names = unnamedVars 684 | break 685 | } 686 | if names == nil { 687 | names = make([]string, s.nVars) 688 | } 689 | names[i] = C.GoString(name) 690 | } 691 | s.varNames = names 692 | } 693 | if len(s.varNames) == 0 { 694 | return nil // unnamedVars -> nil 695 | } 696 | return s.varNames 697 | } 698 | 699 | // Columns returns the names of columns produced by the prepared statement. 700 | // [http://www.sqlite.org/c3ref/column_name.html] 701 | func (s *Stmt) Columns() []string { 702 | if len(s.colNames) != s.nCols { 703 | names := resize(s.colNames, s.nCols) 704 | for i, old := range names { 705 | new := goStr(C.sqlite3_column_name(s.stmt, C.int(i))) 706 | if old != new { 707 | names[i] = raw(new).Copy() 708 | } 709 | } 710 | s.colNames = names 711 | } 712 | return s.colNames 713 | } 714 | 715 | // DeclTypes returns the type declarations of columns produced by the prepared 716 | // statement. The type declarations are normalized to upper case. 717 | // [http://www.sqlite.org/c3ref/column_decltype.html] 718 | func (s *Stmt) DeclTypes() []string { 719 | if len(s.colDecls) != s.nCols { 720 | decls := resize(s.colDecls, s.nCols) 721 | for i, old := range decls { 722 | new := goStr(C.sqlite3_column_decltype(s.stmt, C.int(i))) 723 | if !strings.EqualFold(old, new) { 724 | norm := strings.ToUpper(new) 725 | if cStr(new) == cStr(norm) { 726 | norm = raw(norm).Copy() // ToUpper didn't reallocate 727 | } 728 | decls[i] = norm 729 | } 730 | } 731 | s.colDecls = decls 732 | } 733 | return s.colDecls 734 | } 735 | 736 | // DataTypes returns the data type codes of columns in the current row. Possible 737 | // data types are INTEGER, FLOAT, TEXT, BLOB, and NULL. These represent the 738 | // actual storage classes used by SQLite to store each value before any 739 | // conversion. The returned slice should not be modified. 740 | // [http://www.sqlite.org/c3ref/column_blob.html] 741 | func (s *Stmt) DataTypes() []uint8 { 742 | if len(s.colTypes) == 0 { 743 | if !s.haveRow { 744 | return nil 745 | } 746 | s.colType(0) 747 | } 748 | return s.colTypes 749 | } 750 | 751 | // Exec executes and resets the prepared statement. No rows are returned. 752 | // [http://www.sqlite.org/c3ref/step.html] 753 | func (s *Stmt) Exec(args ...interface{}) error { 754 | if s.stmt == nil { 755 | return ErrBadStmt 756 | } 757 | err := s.exec(args) 758 | if s.haveRow { 759 | s.Reset() 760 | } 761 | return err 762 | } 763 | 764 | // Query executes the prepared statement and makes the first returned row 765 | // available for scanning. io.EOF is returned and the statement is reset if the 766 | // query does not return any rows. 767 | func (s *Stmt) Query(args ...interface{}) error { 768 | if s.stmt == nil { 769 | return ErrBadStmt 770 | } 771 | err := s.exec(args) 772 | if !s.haveRow && err == nil { 773 | return io.EOF 774 | } 775 | return err 776 | } 777 | 778 | // Scan retrieves data from the current row, storing successive column values 779 | // into successive arguments. If the last argument is an instance of RowMap, 780 | // then all remaining column/value pairs are assigned into the map. The same row 781 | // may be scanned multiple times. Nil arguments are silently skipped. 782 | // [http://www.sqlite.org/c3ref/column_blob.html] 783 | func (s *Stmt) Scan(dst ...interface{}) error { 784 | if !s.haveRow { 785 | return io.EOF 786 | } 787 | n := len(dst) 788 | if n == 0 { 789 | return nil 790 | } 791 | if n > s.nCols { 792 | return pkgErr(MISUSE, "cannot assign %d value(s) from %d column(s)", 793 | n, s.nCols) 794 | } 795 | rowMap, _ := dst[n-1].(RowMap) 796 | if rowMap != nil { 797 | n-- 798 | } 799 | for i, v := range dst[:n] { 800 | if v != nil { 801 | if err := s.scan(C.int(i), v); err != nil { 802 | return err 803 | } 804 | } 805 | } 806 | if rowMap != nil { 807 | var v interface{} 808 | for i, col := range s.Columns()[n:] { 809 | if err := s.scanDynamic(C.int(n+i), &v, false); err != nil { 810 | return err 811 | } 812 | rowMap[col] = v 813 | } 814 | } 815 | return nil 816 | } 817 | 818 | // Next makes the next row available for scanning. io.EOF is returned and the 819 | // statement is reset if no more rows are available. 820 | func (s *Stmt) Next() error { 821 | if s.haveRow { 822 | if err := s.step(); err != nil { 823 | return err 824 | } 825 | if s.haveRow { 826 | return nil 827 | } 828 | } 829 | return io.EOF 830 | } 831 | 832 | // Reset returns the prepared statement to its initial state, ready to be 833 | // re-executed. This should be done when the remaining rows returned by a query 834 | // are not needed, which releases some resources that would otherwise persist 835 | // until the next call to Exec or Query. 836 | // [http://www.sqlite.org/c3ref/reset.html] 837 | func (s *Stmt) Reset() { 838 | if s.haveRow { 839 | s.haveRow = false 840 | C.sqlite3_reset(s.stmt) 841 | if s.nVars > 0 { 842 | C.sqlite3_clear_bindings(s.stmt) 843 | } 844 | } 845 | } 846 | 847 | // Status returns the current value of a statement performance counter, 848 | // specified by one of the STMTSTATUS constants. If reset is true, the value is 849 | // reset back down to 0 after retrieval. 850 | // [http://www.sqlite.org/c3ref/stmt_status.html] 851 | func (s *Stmt) Status(op int, reset bool) int { 852 | if s.stmt == nil { 853 | return 0 854 | } 855 | return int(C.sqlite3_stmt_status(s.stmt, C.int(op), cBool(reset))) 856 | } 857 | 858 | // exec resets the prepared statement, binds new parameter values, and executes 859 | // the first step. 860 | func (s *Stmt) exec(args []interface{}) (err error) { 861 | if s.haveRow { 862 | s.Reset() 863 | } 864 | if named := namedArgs(args); named != nil { 865 | err = s.bindNamed(named) 866 | } else { 867 | err = s.bindUnnamed(args) 868 | } 869 | if err == nil { 870 | err = s.step() 871 | if s.nCols > 0 { 872 | // If the statement was recompiled (v2 interface, no indication), 873 | // then column counts, names, and declarations may have changed and 874 | // need to be reloaded. 875 | s.nCols = int(C.sqlite3_column_count(s.stmt)) 876 | s.colNames = s.colNames[:0] 877 | s.colDecls = s.colDecls[:0] 878 | } 879 | } else if s.nVars > 0 { 880 | C.sqlite3_clear_bindings(s.stmt) 881 | } 882 | return 883 | } 884 | 885 | // bindNamed binds statement parameters using the name/value pairs in args. 886 | func (s *Stmt) bindNamed(args NamedArgs) error { 887 | if s.nVars > 0 { 888 | names := s.Params() 889 | if names == nil { 890 | return pkgErr(MISUSE, "statement does not accept named arguments") 891 | } 892 | for i, name := range names { 893 | if err := s.bind(C.int(i+1), args[name], name); err != nil { 894 | return err 895 | } 896 | } 897 | } 898 | return nil 899 | } 900 | 901 | // bindUnnamed binds statement parameters using successive values in args. 902 | func (s *Stmt) bindUnnamed(args []interface{}) error { 903 | if len(args) != s.nVars { 904 | return pkgErr(MISUSE, "statement requires %d argument(s), %d given", 905 | s.nVars, len(args)) 906 | } 907 | for i, v := range args { 908 | if err := s.bind(C.int(i+1), v, ""); err != nil { 909 | return err 910 | } 911 | } 912 | return nil 913 | } 914 | 915 | // bind binds statement parameter i (starting at 1) to the value v. The 916 | // parameter name is only used for error reporting. 917 | func (s *Stmt) bind(i C.int, v interface{}, name string) error { 918 | if v == nil { 919 | return nil // Unbound parameters are NULL by default 920 | } 921 | var rc C.int 922 | switch v := v.(type) { 923 | case int: 924 | rc = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(v)) 925 | case int64: 926 | rc = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(v)) 927 | case float64: 928 | rc = C.sqlite3_bind_double(s.stmt, i, C.double(v)) 929 | case bool: 930 | rc = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(cBool(v))) 931 | case string: 932 | rc = C.bind_text(s.stmt, i, cStr(v), C.int(len(v)), 1) 933 | case []byte: 934 | rc = C.bind_blob(s.stmt, i, cBytes(v), C.int(len(v)), 1) 935 | case time.Time: 936 | rc = C.sqlite3_bind_int64(s.stmt, i, C.sqlite3_int64(v.Unix())) 937 | case RawString: 938 | rc = C.bind_text(s.stmt, i, cStr(string(v)), C.int(len(v)), 0) 939 | case RawBytes: 940 | rc = C.bind_blob(s.stmt, i, cBytes(v), C.int(len(v)), 0) 941 | case ZeroBlob: 942 | rc = C.sqlite3_bind_zeroblob(s.stmt, i, C.int(v)) 943 | default: 944 | if name != "" { 945 | return pkgErr(MISUSE, "unsupported type for %s (%T)", name, v) 946 | } 947 | return pkgErr(MISUSE, "unsupported type at index %d (%T)", int(i-1), v) 948 | } 949 | if rc != OK { 950 | return libErr(rc, s.conn.db) 951 | } 952 | return nil 953 | } 954 | 955 | // step evaluates the next step in the statement's program, automatically 956 | // resetting the statement if the result is anything other than SQLITE_ROW. 957 | func (s *Stmt) step() error { 958 | s.colTypes = s.colTypes[:0] 959 | s.haveRow = C.sqlite3_step(s.stmt) == ROW 960 | if !s.haveRow { 961 | // If step returned DONE, reset returns OK. Otherwise, reset returns the 962 | // same error code as step (v2 interface). 963 | rc := C.sqlite3_reset(s.stmt) 964 | if s.nVars > 0 { 965 | C.sqlite3_clear_bindings(s.stmt) 966 | } 967 | if rc != OK { 968 | return libErr(rc, s.conn.db) 969 | } 970 | } 971 | return nil 972 | } 973 | 974 | // colType returns the data type code of column i in the current row (one of 975 | // INTEGER, FLOAT, TEXT, BLOB, or NULL). The value becomes undefined after a 976 | // type conversion, so this method must be called for column i to cache the 977 | // original value before using any other sqlite3_column_* functions. 978 | func (s *Stmt) colType(i C.int) byte { 979 | if len(s.colTypes) == 0 { 980 | n := s.nCols 981 | if cap(s.colTypes) < n { 982 | s.colTypes = make([]uint8, n) 983 | } else { 984 | s.colTypes = s.colTypes[:n] 985 | } 986 | C.column_types(s.stmt, (*C.uchar)(cBytes(s.colTypes)), C.int(n)) 987 | } 988 | return s.colTypes[i] 989 | } 990 | 991 | // scan scans the value of column i (starting at 0) into v. 992 | func (s *Stmt) scan(i C.int, v interface{}) error { 993 | if typ := s.colType(i); typ == NULL { 994 | return s.scanZero(i, v) 995 | } 996 | switch v := v.(type) { 997 | case *interface{}: 998 | return s.scanDynamic(i, v, false) 999 | case *int: 1000 | *v = int(C.sqlite3_column_int64(s.stmt, i)) 1001 | case *int64: 1002 | *v = int64(C.sqlite3_column_int64(s.stmt, i)) 1003 | case *float64: 1004 | *v = float64(C.sqlite3_column_double(s.stmt, i)) 1005 | case *bool: 1006 | *v = C.sqlite3_column_int64(s.stmt, i) != 0 1007 | case *string: 1008 | *v = text(s.stmt, i, true) 1009 | case *[]byte: 1010 | *v = blob(s.stmt, i, true) 1011 | case *time.Time: 1012 | *v = time.Unix(int64(C.sqlite3_column_int64(s.stmt, i)), 0) 1013 | case *RawString: 1014 | *v = RawString(text(s.stmt, i, false)) 1015 | case *RawBytes: 1016 | *v = RawBytes(blob(s.stmt, i, false)) 1017 | case io.Writer: 1018 | if _, err := v.Write(blob(s.stmt, i, false)); err != nil { 1019 | return err 1020 | } 1021 | default: 1022 | return pkgErr(MISUSE, "unscannable type for column %d (%T)", int(i), v) 1023 | } 1024 | // BUG(mxk): If a SQLite memory allocation fails while scanning column 1025 | // values, the error is not reported until the next call to Stmt.Next or 1026 | // Stmt.Close. This behavior may change in the future to check for and 1027 | // return the error immediately from Stmt.Scan. 1028 | return nil 1029 | } 1030 | 1031 | // scanZero assigns the zero value to v when the associated column is NULL. 1032 | func (s *Stmt) scanZero(i C.int, v interface{}) error { 1033 | switch v := v.(type) { 1034 | case *interface{}: 1035 | *v = nil 1036 | case *int: 1037 | *v = 0 1038 | case *int64: 1039 | *v = 0 1040 | case *float64: 1041 | *v = 0.0 1042 | case *bool: 1043 | *v = false 1044 | case *string: 1045 | *v = "" 1046 | case *[]byte: 1047 | *v = nil 1048 | case *time.Time: 1049 | *v = time.Time{} 1050 | case *RawString: 1051 | *v = "" 1052 | case *RawBytes: 1053 | *v = nil 1054 | case io.Writer: 1055 | default: 1056 | return pkgErr(MISUSE, "unscannable type for column %d (%T)", int(i), v) 1057 | } 1058 | return nil 1059 | } 1060 | 1061 | // scanDynamic scans the value of column i (starting at 0) into v, using the 1062 | // column's data type and declaration to select an appropriate representation. 1063 | // If driverValue is true, the range of possible representations is restricted 1064 | // to those allowed by driver.Value. 1065 | func (s *Stmt) scanDynamic(i C.int, v *interface{}, driverValue bool) error { 1066 | switch typ := s.colType(i); typ { 1067 | case INTEGER: 1068 | n := int64(C.sqlite3_column_int64(s.stmt, i)) 1069 | *v = n 1070 | if decl := s.DeclTypes()[i]; len(decl) >= 4 { 1071 | switch decl[:4] { 1072 | case "DATE", "TIME": 1073 | *v = time.Unix(n, 0) 1074 | case "BOOL": 1075 | *v = n != 0 1076 | } 1077 | } 1078 | case FLOAT: 1079 | *v = float64(C.sqlite3_column_double(s.stmt, i)) 1080 | case TEXT: 1081 | if driverValue { 1082 | *v = []byte(text(s.stmt, i, false)) 1083 | } else { 1084 | *v = text(s.stmt, i, true) 1085 | } 1086 | case BLOB: 1087 | *v = blob(s.stmt, i, true) 1088 | case NULL: 1089 | *v = nil 1090 | default: 1091 | *v = nil 1092 | return pkgErr(ERROR, "unknown column type (%d)", typ) 1093 | } 1094 | return nil 1095 | } 1096 | 1097 | // namedArgs checks if args contains named parameter values, and if so, returns 1098 | // the NamedArgs map. 1099 | func namedArgs(args []interface{}) (named NamedArgs) { 1100 | if len(args) == 1 { 1101 | named, _ = args[0].(NamedArgs) 1102 | } 1103 | return 1104 | } 1105 | 1106 | // resize changes len(s) to n, reallocating s if needed. 1107 | func resize(s []string, n int) []string { 1108 | if n <= cap(s) { 1109 | return s[:n] 1110 | } 1111 | tmp := make([]string, n) 1112 | copy(tmp, s[:cap(s)]) 1113 | return tmp 1114 | } 1115 | 1116 | // text returns the value of column i as a UTF-8 string. If copy is false, the 1117 | // string will point to memory allocated by SQLite. 1118 | func text(stmt *C.sqlite3_stmt, i C.int, copy bool) string { 1119 | p := (*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, i))) 1120 | if n := C.sqlite3_column_bytes(stmt, i); n > 0 { 1121 | if copy { 1122 | return C.GoStringN(p, n) 1123 | } 1124 | return goStrN(p, n) 1125 | } 1126 | return "" 1127 | } 1128 | 1129 | // blob returns the value of column i as a []byte. If copy is false, the []byte 1130 | // will point to memory allocated by SQLite. 1131 | func blob(stmt *C.sqlite3_stmt, i C.int, copy bool) []byte { 1132 | if p := C.sqlite3_column_blob(stmt, i); p != nil { 1133 | n := C.sqlite3_column_bytes(stmt, i) 1134 | if copy { 1135 | return C.GoBytes(p, n) 1136 | } 1137 | return goBytes(p, n) 1138 | } 1139 | return nil 1140 | } 1141 | -------------------------------------------------------------------------------- /sqlite3/sqlite3.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #include "lib/sqlite3.h" 6 | #include "lib/codec.h" 7 | -------------------------------------------------------------------------------- /sqlite3/sqlite3_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3_test 6 | 7 | import ( 8 | "bytes" 9 | "database/sql" 10 | "flag" 11 | "fmt" 12 | "io" 13 | "io/ioutil" 14 | "math" 15 | "os" 16 | "reflect" 17 | "runtime" 18 | "strings" 19 | "testing" 20 | "time" 21 | "unsafe" 22 | 23 | . "github.com/mxk/go-sqlite/sqlite3" 24 | _ "github.com/mxk/go-sqlite/sqlite3/codec" 25 | ) 26 | 27 | var key = flag.String("key", "", "codec key to use for all tests") 28 | 29 | // skip, when set to true, causes all remaining tests to be skipped. 30 | var skip = false 31 | 32 | type T struct{ *testing.T } 33 | 34 | func begin(t *testing.T) T { 35 | if skip { 36 | t.SkipNow() 37 | } 38 | return T{t} 39 | } 40 | 41 | func (t T) skipRestIfFailed() { 42 | skip = skip || t.Failed() 43 | } 44 | 45 | func (t T) open(name string) *Conn { 46 | codec := false 47 | if *key != "" && name == ":memory:" { 48 | name = t.tmpFile() 49 | codec = true 50 | } 51 | c, err := Open(name) 52 | if c == nil || err != nil { 53 | t.Fatalf(cl("Open(%q) unexpected error: %v"), name, err) 54 | } 55 | if codec { 56 | if err = c.Key("main", []byte(*key)); err != nil { 57 | t.Fatalf(cl("Key() unexpected error: %v"), err) 58 | } 59 | } 60 | return c 61 | } 62 | 63 | func (t T) close(c io.Closer) { 64 | if c != nil { 65 | if db, _ := c.(*Conn); db != nil { 66 | if path := db.Path("main"); path != "" { 67 | defer os.Remove(path) 68 | } 69 | } 70 | if err := c.Close(); err != nil { 71 | if !t.Failed() { 72 | t.Fatalf(cl("(%T).Close() unexpected error: %v"), c, err) 73 | } 74 | t.FailNow() 75 | } 76 | } 77 | } 78 | 79 | func (t T) prepare(c *Conn, sql string) *Stmt { 80 | s, err := c.Prepare(sql) 81 | if s == nil || err != nil { 82 | t.Fatalf(cl("c.Prepare(%q) unexpected error: %v"), sql, err) 83 | } 84 | return s 85 | } 86 | 87 | func (t T) query(cs interface{}, args ...interface{}) (s *Stmt) { 88 | var sql string 89 | var err error 90 | if c, ok := cs.(*Conn); ok { 91 | sql = args[0].(string) 92 | s, err = c.Query(sql, args[1:]...) 93 | } else { 94 | s = cs.(*Stmt) 95 | sql = s.String() 96 | err = s.Query(args...) 97 | } 98 | if s == nil || err != nil { 99 | t.Fatalf(cl("(%T).Query(%q) unexpected error: %v"), cs, sql, err) 100 | } 101 | return 102 | } 103 | 104 | func (t T) exec(cs interface{}, args ...interface{}) { 105 | var sql string 106 | var err error 107 | if c, ok := cs.(*Conn); ok { 108 | sql = args[0].(string) 109 | err = c.Exec(sql, args[1:]...) 110 | } else { 111 | s := cs.(*Stmt) 112 | sql = s.String() 113 | err = s.Exec(args...) 114 | } 115 | if err != nil { 116 | t.Fatalf(cl("(%T).Exec(%q) unexpected error: %v"), cs, sql, err) 117 | } 118 | } 119 | 120 | func (t T) scan(s *Stmt, dst ...interface{}) { 121 | if err := s.Scan(dst...); err != nil { 122 | t.Fatalf(cl("s.Scan() unexpected error: %v"), err) 123 | } 124 | } 125 | 126 | func (t T) next(s *Stmt, want error) { 127 | if have := s.Next(); have != want { 128 | if want == nil { 129 | t.Fatalf(cl("s.Next() unexpected error: %v"), have) 130 | } else { 131 | t.Fatalf(cl("s.Next() expected %v; got %v"), want, have) 132 | } 133 | } 134 | } 135 | 136 | func (t T) tmpFile() string { 137 | f, err := ioutil.TempFile("", "go-sqlite.db.") 138 | if err != nil { 139 | t.Fatalf(cl("tmpFile() unexpected error: %v"), err) 140 | } 141 | defer f.Close() 142 | return f.Name() 143 | } 144 | 145 | func (t T) errCode(have error, want int) { 146 | if e, ok := have.(*Error); !ok || e.Code() != want { 147 | t.Fatalf(cl("errCode() expected error code [%d]; got %v"), want, have) 148 | } 149 | } 150 | 151 | func cl(s string) string { 152 | _, thisFile, _, _ := runtime.Caller(1) 153 | _, testFile, line, ok := runtime.Caller(2) 154 | if ok && thisFile == testFile { 155 | return fmt.Sprintf("%d: %s", line, s) 156 | } 157 | return s 158 | } 159 | 160 | func sHdr(s string) *reflect.StringHeader { 161 | return (*reflect.StringHeader)(unsafe.Pointer(&s)) 162 | } 163 | 164 | func bHdr(b []byte) *reflect.SliceHeader { 165 | return (*reflect.SliceHeader)(unsafe.Pointer(&b)) 166 | } 167 | 168 | func TestLib(T *testing.T) { 169 | t := begin(T) 170 | defer t.skipRestIfFailed() 171 | 172 | if v, min := VersionNum(), 3007017; v < min { 173 | t.Errorf("VersionNum() expected >= %d; got %d", min, v) 174 | } 175 | if SingleThread() { 176 | t.Errorf("SingleThread() expected false") 177 | } 178 | 179 | sql := "CREATE TABLE x(a)" 180 | if Complete(sql) { 181 | t.Errorf("Complete(%q) expected false", sql) 182 | } 183 | if sql += ";"; !Complete(sql) { 184 | t.Errorf("Complete(%q) expected true", sql) 185 | } 186 | } 187 | 188 | func TestCreate(T *testing.T) { 189 | t := begin(T) 190 | defer t.skipRestIfFailed() 191 | 192 | checkPath := func(c *Conn, name, want string) { 193 | if have := c.Path(name); have != want { 194 | t.Fatalf(cl("c.Path() expected %q; got %q"), want, have) 195 | } 196 | } 197 | sql := "CREATE TABLE x(a); INSERT INTO x VALUES(1);" 198 | tmp := t.tmpFile() 199 | 200 | // File 201 | os.Remove(tmp) 202 | c := t.open(tmp) 203 | defer t.close(c) 204 | checkPath(c, "main", tmp) 205 | t.exec(c, sql) 206 | if err := c.Close(); err != nil { 207 | t.Fatalf("c.Close() unexpected error: %v", err) 208 | } 209 | if err := c.Exec(sql); err != ErrBadConn { 210 | t.Fatalf("c.Exec() expected %v; got %v", ErrBadConn, err) 211 | } 212 | 213 | // URI (existing) 214 | uri := strings.NewReplacer("?", "%3f", "#", "%23").Replace(tmp) 215 | if runtime.GOOS == "windows" { 216 | uri = "/" + strings.Replace(uri, "\\", "/", -1) 217 | } 218 | c = t.open("file:" + uri) 219 | defer t.close(c) 220 | checkPath(c, "main", tmp) 221 | t.exec(c, "INSERT INTO x VALUES(2)") 222 | 223 | // Temporary (in-memory) 224 | if *key == "" { 225 | c = t.open(":memory:") 226 | defer t.close(c) 227 | checkPath(c, "main", "") 228 | t.exec(c, sql) 229 | } 230 | 231 | // Temporary (file) 232 | c = t.open("") 233 | defer t.close(c) 234 | checkPath(c, "main", "") 235 | t.exec(c, sql) 236 | } 237 | 238 | func TestQuery(T *testing.T) { 239 | t := begin(T) 240 | defer t.skipRestIfFailed() 241 | 242 | sql := ` 243 | CREATE TABLE x(a, b, c, d, e); 244 | INSERT INTO x VALUES(NULL, 123, 1.23, 'TEXT', x'424C4F42'); 245 | ` 246 | type row struct { 247 | a interface{} 248 | b int 249 | c float64 250 | d string 251 | e []byte 252 | } 253 | want := &row{nil, 123, 1.23, "TEXT", []byte("BLOB")} 254 | have := &row{} 255 | 256 | c := t.open(":memory:") 257 | defer t.close(c) 258 | t.exec(c, sql) 259 | 260 | s := t.query(c, "SELECT * FROM x") 261 | defer t.close(s) 262 | t.scan(s, &have.a, &have.b, &have.c, &have.d, &have.e) 263 | if !reflect.DeepEqual(have, want) { 264 | t.Errorf("s.Scan() expected %v; got %v", want, have) 265 | } 266 | 267 | t.next(s, io.EOF) 268 | t.close(s) 269 | if err := s.Query(); err != ErrBadStmt { 270 | t.Errorf("s.Query() expected %v; got %v", ErrBadStmt, err) 271 | } 272 | } 273 | 274 | func TestScan(T *testing.T) { 275 | t := begin(T) 276 | defer t.skipRestIfFailed() 277 | 278 | type types struct { 279 | v interface{} 280 | int int 281 | int64 int64 282 | float64 float64 283 | bool bool 284 | string string 285 | bytes []byte 286 | Time time.Time 287 | RawString RawString 288 | RawBytes RawBytes 289 | Writer io.Writer 290 | } 291 | scan := func(s *Stmt, dst ...interface{}) { 292 | t.query(s) // Re-query to avoid interference from type conversion 293 | t.scan(s, dst...) 294 | } 295 | skipCols := make([]interface{}, 0, 16) 296 | scanNext := func(s *Stmt, have, want *types) { 297 | scan(s, append(skipCols, &have.v)...) 298 | scan(s, append(skipCols, &have.int)...) 299 | scan(s, append(skipCols, &have.int64)...) 300 | scan(s, append(skipCols, &have.float64)...) 301 | scan(s, append(skipCols, &have.bool)...) 302 | scan(s, append(skipCols, &have.string)...) 303 | scan(s, append(skipCols, &have.bytes)...) 304 | scan(s, append(skipCols, &have.Time)...) 305 | scan(s, append(skipCols, have.Writer)...) 306 | 307 | // RawString must be copied, RawBytes (last access) can be used directly 308 | scan(s, append(skipCols, &have.RawString)...) 309 | have.RawString = RawString(have.RawString.Copy()) 310 | scan(s, append(skipCols, &have.RawBytes)...) 311 | 312 | if !reflect.DeepEqual(have, want) { 313 | t.Fatalf(cl("scanNext() expected\n%#v; got\n%#v"), want, have) 314 | } 315 | skipCols = append(skipCols, nil) 316 | } 317 | 318 | c := t.open(":memory:") 319 | defer t.close(c) 320 | t.exec(c, ` 321 | CREATE TABLE x(a, b, c, d, e, f, g, h, i); 322 | INSERT INTO x VALUES(NULL, '', x'', 0, 0.0, 4.2, 42, '42', x'3432'); 323 | `) 324 | s := t.query(c, "SELECT * FROM x") 325 | defer t.close(s) 326 | 327 | // Verify data types 328 | wantT := []uint8{NULL, TEXT, BLOB, INTEGER, FLOAT, FLOAT, INTEGER, TEXT, BLOB} 329 | if haveT := s.DataTypes(); !reflect.DeepEqual(haveT, wantT) { 330 | t.Fatalf(cl("s.DataTypes() expected %v; got %v"), wantT, haveT) 331 | } 332 | 333 | // NULL 334 | have := &types{Writer: new(bytes.Buffer)} 335 | want := &types{Writer: new(bytes.Buffer)} 336 | scanNext(s, have, want) 337 | 338 | // '' 339 | want.v = "" 340 | want.Time = time.Unix(0, 0) 341 | scanNext(s, have, want) 342 | 343 | // x'' 344 | want.v = []byte(nil) 345 | scanNext(s, have, want) 346 | 347 | // 0 348 | want.v = int64(0) 349 | want.string = "0" 350 | want.bytes = []byte("0") 351 | want.RawString = RawString("0") 352 | want.RawBytes = RawBytes("0") 353 | want.Writer.Write([]byte("0")) 354 | scanNext(s, have, want) 355 | 356 | // 0.0 357 | want.v = 0.0 358 | want.string = "0.0" 359 | want.bytes = []byte("0.0") 360 | want.RawString = RawString("0.0") 361 | want.RawBytes = RawBytes("0.0") 362 | want.Writer.Write([]byte("0.0")) 363 | scanNext(s, have, want) 364 | 365 | // 4.2 366 | want.v = 4.2 367 | want.int = 4 368 | want.int64 = 4 369 | want.float64 = 4.2 370 | want.bool = true 371 | want.string = "4.2" 372 | want.bytes = []byte("4.2") 373 | want.Time = time.Unix(4, 0) 374 | want.RawString = RawString("4.2") 375 | want.RawBytes = RawBytes("4.2") 376 | want.Writer.Write([]byte("4.2")) 377 | scanNext(s, have, want) 378 | 379 | // 42 380 | want.v = int64(42) 381 | want.int = 42 382 | want.int64 = 42 383 | want.float64 = 42 384 | want.string = "42" 385 | want.bytes = []byte("42") 386 | want.Time = time.Unix(42, 0) 387 | want.RawString = RawString("42") 388 | want.RawBytes = RawBytes("42") 389 | want.Writer.Write([]byte("42")) 390 | scanNext(s, have, want) 391 | 392 | // '42' 393 | want.v = "42" 394 | want.Writer.Write([]byte("42")) 395 | scanNext(s, have, want) 396 | 397 | // x'3432' 398 | want.v = []byte("42") 399 | want.Writer.Write([]byte("42")) 400 | scanNext(s, have, want) 401 | 402 | // Zero destinations 403 | t.scan(s) 404 | 405 | // Unsupported type 406 | var f32 float32 407 | t.errCode(s.Scan(&f32), MISUSE) 408 | 409 | // EOF 410 | t.next(s, io.EOF) 411 | if err := s.Scan(); err != io.EOF { 412 | t.Fatalf("s.Scan() expected EOF; got %v", err) 413 | } 414 | } 415 | 416 | func TestScanDynamic(T *testing.T) { 417 | t := begin(T) 418 | defer t.skipRestIfFailed() 419 | 420 | type row struct { 421 | a, b, c, d interface{} 422 | m RowMap 423 | } 424 | scanNext := func(s *Stmt, have, want *row) { 425 | switch len(want.m) { 426 | case 0: 427 | t.scan(s, &have.a, &have.b, &have.c, &have.d) 428 | case 1: 429 | t.scan(s, &have.a, &have.b, &have.c, have.m) 430 | case 2: 431 | t.scan(s, &have.a, &have.b, have.m) 432 | case 3: 433 | t.scan(s, &have.a, have.m) 434 | case 4: 435 | t.scan(s, have.m) 436 | } 437 | if !reflect.DeepEqual(have, want) { 438 | t.Fatalf(cl("scanNext() expected\n%#v; got\n%#v"), want, have) 439 | } 440 | if err := s.Next(); err == io.EOF { 441 | t.query(s) 442 | } else if err != nil { 443 | t.Fatalf(cl("s.Next() unexpected error: %v"), err) 444 | } 445 | } 446 | 447 | c := t.open(":memory:") 448 | defer t.close(c) 449 | t.exec(c, ` 450 | -- Affinity: NONE, NUMERIC, NUMERIC, NUMERIC 451 | CREATE TABLE x(a, b DATE, c time, d BOOLEAN); 452 | INSERT INTO x VALUES(NULL, NULL, NULL, NULL); 453 | INSERT INTO x VALUES('', '', '', ''); 454 | INSERT INTO x VALUES(x'', x'', x'', x''); 455 | INSERT INTO x VALUES(0, 0, 0, 0); 456 | INSERT INTO x VALUES(0.0, 0.0, 0.0, 0.0); 457 | INSERT INTO x VALUES(4.2, 4.2, 4.2, 4.2); 458 | INSERT INTO x VALUES(42, 42, 42, 42); 459 | INSERT INTO x VALUES('42', '42', '42', '42'); 460 | INSERT INTO x VALUES(x'3432', x'3432', x'3432', x'3432'); 461 | `) 462 | s := t.query(c, "SELECT * FROM x ORDER BY rowid") 463 | defer t.close(s) 464 | 465 | // NULL 466 | have, want := &row{}, &row{} 467 | scanNext(s, have, want) 468 | 469 | // '' 470 | want = &row{"", "", "", "", nil} 471 | scanNext(s, have, want) 472 | 473 | // x'' 474 | want = &row{[]byte(nil), []byte(nil), []byte(nil), []byte(nil), nil} 475 | scanNext(s, have, want) 476 | 477 | // 0 478 | t0 := time.Unix(0, 0) 479 | want = &row{int64(0), t0, t0, false, nil} 480 | scanNext(s, have, want) 481 | 482 | // 0.0 483 | want = &row{0.0, t0, t0, false, nil} 484 | scanNext(s, have, want) 485 | 486 | // 4.2 487 | want = &row{4.2, 4.2, 4.2, 4.2, nil} 488 | scanNext(s, have, want) 489 | 490 | // 42 491 | t42 := time.Unix(42, 0) 492 | want = &row{int64(42), t42, t42, true, nil} 493 | scanNext(s, have, want) 494 | 495 | // '42' 496 | want = &row{"42", t42, t42, true, nil} 497 | scanNext(s, have, want) 498 | 499 | // x'3432' 500 | want = &row{[]byte("42"), []byte("42"), []byte("42"), []byte("42"), nil} 501 | scanNext(s, have, want) 502 | 503 | // NULL (reset) 504 | have = &row{m: RowMap{}} 505 | want = &row{m: RowMap{"a": nil, "b": nil, "c": nil, "d": nil}} 506 | scanNext(s, have, want) 507 | 508 | // '' 509 | have = &row{m: RowMap{}} 510 | want = &row{m: RowMap{"a": "", "b": "", "c": "", "d": ""}} 511 | scanNext(s, have, want) 512 | 513 | // x'' 514 | t.next(s, nil) 515 | 516 | // 0 517 | have = &row{m: RowMap{}} 518 | want = &row{m: RowMap{"a": int64(0), "b": t0, "c": t0, "d": false}} 519 | scanNext(s, have, want) 520 | 521 | // 0.0 522 | have = &row{m: RowMap{}} 523 | want = &row{a: 0.0, m: RowMap{"b": t0, "c": t0, "d": false}} 524 | scanNext(s, have, want) 525 | 526 | // 4.2 527 | have = &row{m: RowMap{}} 528 | want = &row{a: 4.2, b: 4.2, m: RowMap{"c": 4.2, "d": 4.2}} 529 | scanNext(s, have, want) 530 | 531 | // 42 532 | have = &row{m: RowMap{}} 533 | want = &row{a: int64(42), b: t42, c: t42, m: RowMap{"d": true}} 534 | scanNext(s, have, want) 535 | 536 | // Too many destinations 537 | t.errCode(s.Scan(&have.a, &have.b, &have.c, &have.d, &have.m), MISUSE) 538 | } 539 | 540 | func TestState(T *testing.T) { 541 | t := begin(T) 542 | defer t.skipRestIfFailed() 543 | 544 | type connState struct { 545 | AutoCommit bool 546 | LastInsertId int64 547 | RowsAffected int 548 | TotalRowsAffected int 549 | } 550 | checkConn := func(c *Conn, want *connState) { 551 | have := &connState{ 552 | c.AutoCommit(), 553 | c.LastInsertId(), 554 | c.RowsAffected(), 555 | c.TotalRowsAffected(), 556 | } 557 | if !reflect.DeepEqual(have, want) { 558 | t.Fatalf(cl("checkConn() expected\n%#v; got\n%#v"), want, have) 559 | } 560 | } 561 | 562 | c := t.open(":memory:") 563 | defer t.close(c) 564 | checkConn(c, &connState{true, 0, 0, 0}) 565 | 566 | t.exec(c, "BEGIN") 567 | checkConn(c, &connState{false, 0, 0, 0}) 568 | 569 | t.exec(c, "ROLLBACK") 570 | checkConn(c, &connState{true, 0, 0, 0}) 571 | 572 | t.exec(c, "CREATE TABLE x(a, b INTEGER, c text)") 573 | checkConn(c, &connState{true, 0, 0, 0}) 574 | 575 | t.exec(c, "INSERT INTO x VALUES(NULL, 42, 42)") 576 | checkConn(c, &connState{true, 1, 1, 1}) 577 | 578 | t.exec(c, "INSERT INTO x VALUES(-42, 4.2, x'42')") 579 | checkConn(c, &connState{true, 2, 1, 2}) 580 | 581 | type stmtState struct { 582 | Conn *Conn 583 | Valid bool 584 | Busy bool 585 | ReadOnly bool 586 | NumParams int 587 | NumColumns int 588 | Params []string 589 | Columns []string 590 | DeclTypes []string 591 | DataTypes []uint8 592 | } 593 | checkStmt := func(s *Stmt, want *stmtState) { 594 | have := &stmtState{ 595 | s.Conn(), 596 | s.Valid(), 597 | s.Busy(), 598 | s.ReadOnly(), 599 | s.NumParams(), 600 | s.NumColumns(), 601 | s.Params(), 602 | s.Columns(), 603 | s.DeclTypes(), 604 | s.DataTypes(), 605 | } 606 | if !reflect.DeepEqual(have, want) { 607 | t.Fatalf(cl("checkStmt() expected\n%#v; got\n%#v"), want, have) 608 | } 609 | } 610 | closed := &stmtState{Conn: c, ReadOnly: true} 611 | 612 | // SELECT 613 | s := t.prepare(c, "SELECT * FROM x ORDER BY rowid") 614 | defer t.close(s) 615 | want := &stmtState{ 616 | Conn: c, 617 | Valid: true, 618 | ReadOnly: true, 619 | NumColumns: 3, 620 | Columns: []string{"a", "b", "c"}, 621 | DeclTypes: []string{"", "INTEGER", "TEXT"}, 622 | } 623 | checkStmt(s, want) 624 | 625 | t.query(s) 626 | want.Busy = true 627 | want.DataTypes = []uint8{NULL, INTEGER, TEXT} 628 | checkStmt(s, want) 629 | 630 | t.query(s) 631 | var _a, _b, _c []byte 632 | t.scan(s, &_a, &_b, &_c) // This scan must not change DataTypes 633 | checkStmt(s, want) 634 | 635 | t.next(s, nil) 636 | want.DataTypes = []uint8{INTEGER, FLOAT, BLOB} 637 | checkStmt(s, want) 638 | 639 | t.next(s, io.EOF) 640 | want.Busy = false 641 | want.DataTypes = nil 642 | checkStmt(s, want) 643 | 644 | t.close(s) 645 | checkStmt(s, closed) 646 | 647 | // INSERT (unnamed parameters) 648 | s = t.prepare(c, "INSERT INTO x VALUES(?, ?, ?)") 649 | defer t.close(s) 650 | want = &stmtState{ 651 | Conn: c, 652 | Valid: true, 653 | NumParams: 3, 654 | } 655 | checkStmt(s, want) 656 | 657 | t.exec(s, nil, nil, nil) 658 | checkStmt(s, want) 659 | 660 | t.close(s) 661 | checkStmt(s, closed) 662 | 663 | // INSERT (named parameters) 664 | s = t.prepare(c, "INSERT INTO x VALUES(:a, @B, $c)") 665 | defer t.close(s) 666 | want = &stmtState{ 667 | Conn: c, 668 | Valid: true, 669 | NumParams: 3, 670 | Params: []string{":a", "@B", "$c"}, 671 | } 672 | checkStmt(s, want) 673 | 674 | // Comment 675 | s = t.prepare(c, "-- This is a comment") 676 | checkStmt(s, closed) 677 | } 678 | 679 | func TestTail(T *testing.T) { 680 | t := begin(T) 681 | defer t.skipRestIfFailed() 682 | 683 | c := t.open(":memory:") 684 | defer t.close(c) 685 | 686 | check := func(sql, tail string) { 687 | s := t.prepare(c, sql) 688 | defer t.close(s) 689 | head := sql[:len(sql)-len(tail)] 690 | tail = sql[len(head):] 691 | 692 | // s.String() must be a prefix of sql 693 | if s.String() != head { 694 | t.Errorf(cl("s.String() expected %q; got %q"), head, s.String()) 695 | } else if sHdr(s.String()).Data != sHdr(sql).Data { 696 | t.Errorf(cl("s.String() isn't a pointer into sql")) 697 | } 698 | 699 | // s.Tail must be a suffix of sql or "" 700 | if s.Tail != tail { 701 | t.Errorf(cl("s.Tail expected %q; got %q"), tail, s.Tail) 702 | } else if tail == "" && sHdr(s.Tail).Data == sHdr(tail).Data { 703 | t.Errorf(cl("s.Tail is a pointer into sql")) 704 | } else if tail != "" && sHdr(s.Tail).Data != sHdr(tail).Data { 705 | t.Errorf(cl("s.Tail isn't a pointer into sql")) 706 | } 707 | } 708 | head := "CREATE TABLE x(a);" 709 | tail := " -- comment" 710 | 711 | check("", "") 712 | check(head, "") 713 | check(head+tail, tail) 714 | check(tail, "") 715 | } 716 | 717 | func TestParams(T *testing.T) { 718 | t := begin(T) 719 | defer t.skipRestIfFailed() 720 | 721 | c := t.open(":memory:") 722 | defer t.close(c) 723 | t.exec(c, "CREATE TABLE x(a, b, c, d)") 724 | 725 | dt := func(v interface{}) uint8 { 726 | switch v.(type) { 727 | case int64: 728 | return INTEGER 729 | case float64: 730 | return FLOAT 731 | case string: 732 | return TEXT 733 | case []byte: 734 | return BLOB 735 | } 736 | return NULL 737 | } 738 | verify := func(_a, _b, _c, _d interface{}) { 739 | s := t.query(c, "SELECT * FROM x ORDER BY rowid LIMIT 1") 740 | defer t.close(s) 741 | 742 | wantT := []uint8{dt(_a), dt(_b), dt(_c), dt(_d)} 743 | if haveT := s.DataTypes(); !reflect.DeepEqual(haveT, wantT) { 744 | t.Fatalf(cl("s.DataTypes() expected %v; got %v"), wantT, haveT) 745 | } 746 | 747 | type row struct{ a, b, c, d interface{} } 748 | want, have := &row{_a, _b, _c, _d}, &row{} 749 | t.scan(s, &have.a, &have.b, &have.c, &have.d) 750 | if !reflect.DeepEqual(have, want) { 751 | t.Fatalf(cl("verify() expected\n%#v; got\n%#v"), want, have) 752 | } 753 | t.exec(c, "DELETE FROM x WHERE rowid=(SELECT min(rowid) FROM x)") 754 | } 755 | 756 | // Unnamed 757 | sql := "INSERT INTO x VALUES(?, ?, ?, ?)" 758 | s := t.prepare(c, sql) 759 | defer t.close(s) 760 | 761 | t.exec(s, nil, nil, nil, nil) 762 | verify(nil, nil, nil, nil) 763 | 764 | t.exec(s, int(0), int(1), int64(math.MinInt64), int64(math.MaxInt64)) 765 | verify(int64(0), int64(1), int64(math.MinInt64), int64(math.MaxInt64)) 766 | 767 | t.exec(s, 0.0, 1.0, math.SmallestNonzeroFloat64, math.MaxFloat64) 768 | verify(0.0, 1.0, math.SmallestNonzeroFloat64, math.MaxFloat64) 769 | 770 | t.exec(s, false, true, "", "x\x00y") 771 | verify(int64(0), int64(1), "", "x\x00y") 772 | 773 | t.exec(s, []byte(nil), []byte{}, []byte{0}, []byte("1")) 774 | verify([]byte(nil), []byte(nil), []byte{0}, []byte("1")) 775 | 776 | t.exec(s, time.Unix(0, 0), time.Unix(1, 0), RawString(""), RawString("x")) 777 | verify(int64(0), int64(1), "", "x") 778 | 779 | t.exec(s, RawBytes(""), RawBytes("x"), ZeroBlob(0), ZeroBlob(2)) 780 | verify([]byte(nil), []byte("x"), []byte(nil), []byte{0, 0}) 781 | 782 | // Issue 1: string/[]byte zero values are not NULLs 783 | var s1, s2 string 784 | var b1, b2 []byte 785 | *sHdr(s1) = reflect.StringHeader{} 786 | *sHdr(s2) = reflect.StringHeader{Data: 1} 787 | *bHdr(b1) = reflect.SliceHeader{} 788 | *bHdr(b2) = reflect.SliceHeader{Data: 1} 789 | t.exec(s, s1, s2, b1, b2) 790 | verify("", "", []byte(nil), []byte(nil)) 791 | 792 | // Invalid 793 | t.errCode(s.Exec(), MISUSE) 794 | t.errCode(s.Exec(0, 0, 0), MISUSE) 795 | t.errCode(s.Exec(0, 0, 0, 0, 0), MISUSE) 796 | t.errCode(s.Exec(NamedArgs{}), MISUSE) 797 | 798 | // Named 799 | s = t.prepare(c, "INSERT INTO x VALUES(:a, @B, :a, $d)") 800 | defer t.close(s) 801 | 802 | t.exec(s, NamedArgs{}) 803 | verify(nil, nil, nil, nil) 804 | 805 | t.exec(s, 0, 1, 2) 806 | verify(int64(0), int64(1), int64(0), int64(2)) 807 | 808 | t.exec(s, NamedArgs{":a": "a", "@B": "b", "$d": "d", "$c": nil}) 809 | verify("a", "b", "a", "d") 810 | 811 | t.exec(s, NamedArgs{"@B": RawString("hello"), "$d": RawBytes("world")}) 812 | verify(nil, "hello", nil, []byte("world")) 813 | 814 | // Invalid 815 | t.errCode(s.Exec(), MISUSE) 816 | t.errCode(s.Exec(0, 0), MISUSE) 817 | t.errCode(s.Exec(0, 0, 0, 0), MISUSE) 818 | t.errCode(s.Exec(NamedArgs(nil)), MISUSE) 819 | t.errCode(s.Exec(0, NamedArgs{}), MISUSE) 820 | t.errCode(s.Exec(0, 0, NamedArgs{}), MISUSE) 821 | 822 | // Conn.Query 823 | if s, err := c.Query(sql, 1, 2, 3, 4); s != nil || err != io.EOF { 824 | t.Fatalf("c.Query(%q) expected , EOF; got %v, %v", sql, s, err) 825 | } 826 | verify(int64(1), int64(2), int64(3), int64(4)) 827 | 828 | // Conn.Exec 829 | t.exec(c, ` 830 | INSERT INTO x VALUES(?, ?, NULL, NULL); 831 | INSERT INTO x VALUES(NULL, NULL, ?, ?); 832 | `, 1, 2, 3, 4) 833 | verify(int64(1), int64(2), nil, nil) 834 | verify(nil, nil, int64(3), int64(4)) 835 | 836 | t.exec(c, ` 837 | INSERT INTO x VALUES($a, $b, NULL, NULL); 838 | INSERT INTO x VALUES($a, $a, $c, $d); 839 | `, NamedArgs{"$a": "a", "$b": "b", "$c": "c", "$d": "d"}) 840 | verify("a", "b", nil, nil) 841 | verify("a", "a", "c", "d") 842 | 843 | t.errCode(c.Exec(sql, 0, 0, 0), MISUSE) 844 | t.errCode(c.Exec(sql, 0, 0, 0, 0, 0), MISUSE) 845 | } 846 | 847 | func TestTx(T *testing.T) { 848 | t := begin(T) 849 | defer t.skipRestIfFailed() 850 | 851 | c := t.open(":memory:") 852 | defer t.close(c) 853 | t.exec(c, "CREATE TABLE x(a)") 854 | 855 | // Begin/Commit 856 | if err := c.Begin(); err != nil { 857 | t.Fatalf("c.Begin() unexpected error: %v", err) 858 | } 859 | t.exec(c, "INSERT INTO x VALUES(1)") 860 | t.exec(c, "INSERT INTO x VALUES(2)") 861 | if err := c.Commit(); err != nil { 862 | t.Fatalf("c.Commit() unexpected error: %v", err) 863 | } 864 | 865 | // Begin/Rollback 866 | if err := c.Begin(); err != nil { 867 | t.Fatalf("c.Begin() unexpected error: %v", err) 868 | } 869 | t.exec(c, "INSERT INTO x VALUES(3)") 870 | t.exec(c, "INSERT INTO x VALUES(4)") 871 | if err := c.Rollback(); err != nil { 872 | t.Fatalf("c.Rollback() unexpected error: %v", err) 873 | } 874 | 875 | // Verify 876 | s := t.query(c, "SELECT * FROM x ORDER BY rowid") 877 | defer t.close(s) 878 | var i int 879 | if t.scan(s, &i); i != 1 { 880 | t.Fatalf("s.Scan() expected 1; got %d", i) 881 | } 882 | t.next(s, nil) 883 | if t.scan(s, &i); i != 2 { 884 | t.Fatalf("s.Scan() expected 2; got %d", i) 885 | } 886 | t.next(s, io.EOF) 887 | } 888 | 889 | func TestIO(T *testing.T) { 890 | t := begin(T) 891 | 892 | c := t.open(":memory:") 893 | defer t.close(c) 894 | t.exec(c, "CREATE TABLE x(a)") 895 | t.exec(c, "INSERT INTO x VALUES(?)", ZeroBlob(8)) 896 | t.exec(c, "INSERT INTO x VALUES(?)", "hello, world") 897 | 898 | // Open 899 | b, err := c.BlobIO("main", "x", "a", 1, true) 900 | if b == nil || err != nil { 901 | t.Fatalf("c.BlobIO() unexpected error: %v", err) 902 | } 903 | defer t.close(b) 904 | 905 | // State 906 | if b.Conn() != c { 907 | t.Fatalf("b.Conn() expected %p; got %p", c, b.Conn()) 908 | } 909 | if b.Row() != 1 { 910 | t.Fatalf("b.Row() expected 1; got %d", b.Row()) 911 | } 912 | if b.Len() != 8 { 913 | t.Fatalf("b.Len() expected 8; got %d", b.Len()) 914 | } 915 | 916 | // Write 917 | in := []byte("1234567") 918 | if n, err := b.Write(in); n != 7 || err != nil { 919 | t.Fatalf("b.Write(%q) expected 7, ; got %d, %v", in, n, err) 920 | } 921 | in = []byte("89") 922 | if n, err := b.Write(in); n != 0 || err != ErrBlobFull { 923 | t.Fatalf("b.Write(%q) expected 0, ErrBlobFull; got %d, %v", in, n, err) 924 | } 925 | 926 | // Reopen 927 | if err := b.Reopen(2); err != nil { 928 | t.Fatalf("b.Reopen(2) unexpected error: %v", err) 929 | } 930 | if b.Row() != 2 { 931 | t.Fatalf("b.Row() expected 2; got %d", b.Row()) 932 | } 933 | if b.Len() != 12 { 934 | t.Fatalf("b.Len() expected 12; got %d", b.Len()) 935 | } 936 | 937 | // Read 938 | for i := 0; i < 2; i++ { 939 | out := make([]byte, 13) 940 | if n, err := b.Read(out); n != 12 || err != nil { 941 | t.Fatalf("b.Read() #%d expected 12, ; got %d, %v", i, n, err) 942 | } 943 | have := string(out) 944 | if want := "hello, world\x00"; have != want { 945 | t.Fatalf("b.Read() #%d expected %q; got %q", i, have, want) 946 | } 947 | if p, err := b.Seek(0, 0); p != 0 || err != nil { 948 | t.Fatalf("b.Seek() #%d expected 0, ; got %d, %v", i, p, err) 949 | } 950 | } 951 | 952 | // Close 953 | t.close(b) 954 | if err := b.Reopen(1); err != ErrBadIO { 955 | t.Fatalf("b.Reopen(1) expected %v; got %v", ErrBadIO, err) 956 | } 957 | 958 | // Verify 959 | s := t.query(c, "SELECT * FROM x ORDER BY rowid") 960 | defer t.close(s) 961 | var have string 962 | t.scan(s, &have) 963 | if want := "1234567\x00"; have != want { 964 | t.Fatalf("s.Scan() expected %q; got %q", want, have) 965 | } 966 | t.next(s, nil) 967 | t.scan(s, &have) 968 | if want := "hello, world"; have != want { 969 | t.Fatalf("s.Scan() expected %q; got %q", want, have) 970 | } 971 | t.next(s, io.EOF) 972 | } 973 | 974 | func TestBackup(T *testing.T) { 975 | t := begin(T) 976 | 977 | c1, c2 := t.open(":memory:"), t.open(":memory:") 978 | defer t.close(c1) 979 | defer t.close(c2) 980 | t.exec(c1, "CREATE TABLE x(a)") 981 | t.exec(c1, "INSERT INTO x VALUES(?)", "1234567\x00") 982 | t.exec(c1, "INSERT INTO x VALUES(?)", "hello, world") 983 | 984 | // Backup 985 | b, err := c1.Backup("main", c2, "main") 986 | if b == nil || err != nil { 987 | t.Fatalf("b.Backup() unexpected error: %v", err) 988 | } 989 | defer t.close(b) 990 | if pr, pt := b.Progress(); pr != 0 || pt != 0 { 991 | t.Fatalf("b.Progress() expected 0, 0; got %d, %d", pr, pt) 992 | } 993 | if err = b.Step(1); err != nil { 994 | t.Fatalf("b.Step(1) expected ; got %v", err) 995 | } 996 | if pr, pt := b.Progress(); pr != 1 || pt != 2 { 997 | t.Fatalf("b.Progress() expected 1, 2; got %d, %d", pr, pt) 998 | } 999 | if err = b.Step(-1); err != io.EOF { 1000 | t.Fatalf("b.Step(-1) expected EOF; got %v", err) 1001 | } 1002 | 1003 | // Close 1004 | t.close(b) 1005 | if err = b.Step(-1); err != ErrBadBackup { 1006 | t.Fatalf("b.Step(-1) expected %v; got %v", ErrBadBackup, err) 1007 | } 1008 | 1009 | // Verify 1010 | s := t.query(c2, "SELECT * FROM x ORDER BY rowid") 1011 | defer t.close(s) 1012 | var have string 1013 | t.scan(s, &have) 1014 | if want := "1234567\x00"; have != want { 1015 | t.Fatalf("s.Scan() expected %q; got %q", want, have) 1016 | } 1017 | t.next(s, nil) 1018 | t.scan(s, &have) 1019 | if want := "hello, world"; have != want { 1020 | t.Fatalf("s.Scan() expected %q; got %q", want, have) 1021 | } 1022 | t.next(s, io.EOF) 1023 | } 1024 | 1025 | func TestBusyHandler(T *testing.T) { 1026 | t := begin(T) 1027 | 1028 | tmp := t.tmpFile() 1029 | c1 := t.open(tmp) 1030 | defer t.close(c1) 1031 | c2 := t.open(tmp) 1032 | defer t.close(c2) 1033 | t.exec(c1, "CREATE TABLE x(a); BEGIN; INSERT INTO x VALUES(1);") 1034 | 1035 | try := func(sql string, want, terr time.Duration) { 1036 | start := time.Now() 1037 | err := c2.Exec(sql) 1038 | have := time.Since(start) 1039 | if have < want-terr || want+terr < have { 1040 | t.Fatalf(cl("c2.Exec(%q) timeout expected %v; got %v"), sql, want, have) 1041 | } 1042 | t.errCode(err, BUSY) 1043 | } 1044 | want := 100 * time.Millisecond 1045 | terr := 50 * time.Millisecond 1046 | 1047 | // Default 1048 | try("INSERT INTO x VALUES(2)", 0, terr/2) 1049 | 1050 | // Built-in 1051 | if prev := c2.BusyTimeout(want); prev != nil { 1052 | t.Fatalf("c2.BusyTimeout() expected ; got %v", prev) 1053 | } 1054 | try("INSERT INTO x VALUES(3)", want, terr) 1055 | 1056 | // Custom 1057 | calls := 0 1058 | handler := func(count int) (retry bool) { 1059 | calls++ 1060 | time.Sleep(10 * time.Millisecond) 1061 | return calls == count+1 && calls < 10 1062 | } 1063 | if prev := c2.BusyFunc(handler); prev != nil { 1064 | t.Fatalf("c2.BusyFunc() expected ; got %v", prev) 1065 | } 1066 | try("INSERT INTO x VALUES(4)", want, terr) 1067 | if calls != 10 { 1068 | t.Fatalf("calls expected 10; got %d", calls) 1069 | } 1070 | 1071 | // Disable 1072 | if prev := c2.BusyTimeout(0); prev == nil { 1073 | t.Fatalf("c2.BusyTimeout() expected %v; got %v", handler, prev) 1074 | } 1075 | try("INSERT INTO x VALUES(5)", 0, terr/2) 1076 | } 1077 | 1078 | func TestTxHandler(T *testing.T) { 1079 | t := begin(T) 1080 | defer t.skipRestIfFailed() 1081 | 1082 | c := t.open(":memory:") 1083 | defer t.close(c) 1084 | t.exec(c, "CREATE TABLE x(a)") 1085 | 1086 | commit := 0 1087 | rollback := 0 1088 | c.CommitFunc(func() (abort bool) { commit++; return commit >= 2 }) 1089 | c.RollbackFunc(func() { rollback++ }) 1090 | 1091 | // Allow 1092 | c.Begin() 1093 | t.exec(c, "INSERT INTO x VALUES(1)") 1094 | t.exec(c, "INSERT INTO x VALUES(2)") 1095 | if err := c.Commit(); err != nil { 1096 | t.Fatalf("c.Commit() unexpected error: %v", err) 1097 | } 1098 | 1099 | // Deny 1100 | c.Begin() 1101 | t.exec(c, "INSERT INTO x VALUES(3)") 1102 | t.exec(c, "INSERT INTO x VALUES(4)") 1103 | t.errCode(c.Commit(), CONSTRAINT_COMMITHOOK) 1104 | 1105 | // Verify 1106 | if commit != 2 || rollback != 1 { 1107 | t.Fatalf("commit/rollback expected 2/1; got %d/%d", commit, rollback) 1108 | } 1109 | s := t.query(c, "SELECT * FROM x ORDER BY rowid") 1110 | defer t.close(s) 1111 | var i int 1112 | if t.scan(s, &i); i != 1 { 1113 | t.Fatalf("s.Scan() expected 1; got %d", i) 1114 | } 1115 | t.next(s, nil) 1116 | if t.scan(s, &i); i != 2 { 1117 | t.Fatalf("s.Scan() expected 2; got %d", i) 1118 | } 1119 | t.next(s, io.EOF) 1120 | } 1121 | 1122 | func TestUpdateHandler(T *testing.T) { 1123 | t := begin(T) 1124 | defer t.skipRestIfFailed() 1125 | 1126 | c := t.open(":memory:") 1127 | defer t.close(c) 1128 | t.exec(c, "CREATE TABLE x(a)") 1129 | 1130 | type update struct { 1131 | op int 1132 | db, tbl string 1133 | row int64 1134 | } 1135 | var have *update 1136 | verify := func(want *update) { 1137 | if !reflect.DeepEqual(have, want) { 1138 | t.Fatalf(cl("verify() expected %v; got %v"), want, have) 1139 | } 1140 | } 1141 | c.UpdateFunc(func(op int, db, tbl RawString, row int64) { 1142 | have = &update{op, db.Copy(), tbl.Copy(), row} 1143 | }) 1144 | 1145 | t.exec(c, "INSERT INTO x VALUES(1)") 1146 | verify(&update{INSERT, "main", "x", 1}) 1147 | 1148 | t.exec(c, "INSERT INTO x VALUES(2)") 1149 | verify(&update{INSERT, "main", "x", 2}) 1150 | 1151 | t.exec(c, "UPDATE x SET a=3 WHERE rowid=1") 1152 | verify(&update{UPDATE, "main", "x", 1}) 1153 | 1154 | t.exec(c, "DELETE FROM x WHERE rowid=2") 1155 | verify(&update{DELETE, "main", "x", 2}) 1156 | } 1157 | 1158 | func TestSchema(T *testing.T) { 1159 | t := begin(T) 1160 | 1161 | c := t.open(":memory:") 1162 | defer t.close(c) 1163 | t.exec(c, "CREATE TABLE x(a int)") 1164 | t.exec(c, "INSERT INTO x VALUES(1)") 1165 | t.exec(c, "INSERT INTO x VALUES(2)") 1166 | 1167 | checkCols := func(s *Stmt, want ...string) { 1168 | if have := s.NumColumns(); have != len(want) { 1169 | t.Fatalf(cl("s.NumColumns() expected %d; got %d"), len(want), have) 1170 | } 1171 | if have := s.Columns(); !reflect.DeepEqual(have, want) { 1172 | t.Fatalf(cl("s.Columns() expected %v; got %v"), want, have) 1173 | } 1174 | } 1175 | checkDecls := func(s *Stmt, want ...string) { 1176 | if have := s.DeclTypes(); !reflect.DeepEqual(have, want) { 1177 | t.Fatalf(cl("s.DeclTypes() expected %v; got %v"), want, have) 1178 | } 1179 | } 1180 | checkRow := func(s *Stmt, want RowMap) { 1181 | have := RowMap{} 1182 | if t.scan(s, have); !reflect.DeepEqual(have, want) { 1183 | t.Fatalf(cl("s.Scan() expected %v; got %v"), want, have) 1184 | } 1185 | } 1186 | s := t.query(c, "SELECT * FROM x ORDER BY rowid") 1187 | defer t.close(s) 1188 | 1189 | checkCols(s, "a") 1190 | checkDecls(s, "INT") 1191 | checkRow(s, RowMap{"a": int64(1)}) 1192 | 1193 | // Schema changes do not affect running statements 1194 | t.exec(c, "ALTER TABLE x ADD b text") 1195 | t.next(s, nil) 1196 | 1197 | checkCols(s, "a") 1198 | checkDecls(s, "INT") 1199 | checkRow(s, RowMap{"a": int64(2)}) 1200 | t.next(s, io.EOF) 1201 | 1202 | checkCols(s, "a") 1203 | checkDecls(s, "INT") 1204 | t.query(s) 1205 | 1206 | checkCols(s, "a", "b") 1207 | checkDecls(s, "INT", "TEXT") 1208 | checkRow(s, RowMap{"a": int64(1), "b": nil}) 1209 | t.next(s, nil) 1210 | 1211 | checkCols(s, "a", "b") 1212 | checkDecls(s, "INT", "TEXT") 1213 | checkRow(s, RowMap{"a": int64(2), "b": nil}) 1214 | t.next(s, io.EOF) 1215 | } 1216 | 1217 | func TestDriver(T *testing.T) { 1218 | t := begin(T) 1219 | 1220 | c, err := sql.Open("sqlite3", ":memory:") 1221 | if c == nil || err != nil { 1222 | t.Fatalf("sql.Open() unexpected error: %v", err) 1223 | } 1224 | defer t.close(c) 1225 | 1226 | // Setup 1227 | sql := "CREATE TABLE x(a, b, c)" 1228 | r, err := c.Exec(sql) 1229 | if r == nil || err != nil { 1230 | t.Fatalf("c.Exec(%q) unexpected error: %v", sql, err) 1231 | } 1232 | if id, err := r.LastInsertId(); id != 0 || err != nil { 1233 | t.Fatalf("r.LastInsertId() expected 0, ; got %d, %v", id, err) 1234 | } 1235 | if n, err := r.RowsAffected(); n != 0 || err != nil { 1236 | t.Fatalf("r.RowsAffected() expected 0, ; got %d, %v", n, err) 1237 | } 1238 | 1239 | // Prepare 1240 | sql = "INSERT INTO x VALUES(?, ?, ?)" 1241 | s, err := c.Prepare(sql) 1242 | if err != nil { 1243 | t.Fatalf("c.Prepare(%q) unexpected error: %v", sql, err) 1244 | } 1245 | defer t.close(s) 1246 | 1247 | // Multiple inserts 1248 | r, err = s.Exec(1, 2.2, "test") 1249 | if err != nil { 1250 | t.Fatalf("s.Exec(%q) unexpected error: %v", sql, err) 1251 | } 1252 | if id, err := r.LastInsertId(); id != 1 || err != nil { 1253 | t.Fatalf("r.LastInsertId() expected 1, ; got %d, %v", id, err) 1254 | } 1255 | if n, err := r.RowsAffected(); n != 1 || err != nil { 1256 | t.Fatalf("r.RowsAffected() expected 1, ; got %d, %v", n, err) 1257 | } 1258 | 1259 | r, err = s.Exec(3, []byte{4}, nil) 1260 | if err != nil { 1261 | t.Fatalf("s.Exec(%q) unexpected error: %v", sql, err) 1262 | } 1263 | if id, err := r.LastInsertId(); id != 2 || err != nil { 1264 | t.Fatalf("r.LastInsertId() expected 1, ; got %d, %v", id, err) 1265 | } 1266 | if n, err := r.RowsAffected(); n != 1 || err != nil { 1267 | t.Fatalf("r.RowsAffected() expected 1, ; got %d, %v", n, err) 1268 | } 1269 | 1270 | // Select all rows 1271 | sql = "SELECT rowid, * FROM x ORDER BY rowid" 1272 | rows, err := c.Query(sql) 1273 | if rows == nil || err != nil { 1274 | t.Fatalf("c.Query() unexpected error: %v", err) 1275 | } 1276 | defer t.close(rows) 1277 | 1278 | // Row information 1279 | want := []string{"rowid", "a", "b", "c"} 1280 | if have, err := rows.Columns(); !reflect.DeepEqual(have, want) { 1281 | t.Fatalf("rows.Columns() expected %v, ; got %v, %v", want, have, err) 1282 | } 1283 | 1284 | // Verify 1285 | table := [][]interface{}{ 1286 | {int64(1), int64(1), float64(2.2), []byte("test")}, 1287 | {int64(2), int64(3), []byte{4}, nil}, 1288 | } 1289 | for i, want := range table { 1290 | if !rows.Next() { 1291 | t.Fatalf("rows.Next(%d) expected true", i) 1292 | } 1293 | have := make([]interface{}, 4) 1294 | if err := rows.Scan(&have[0], &have[1], &have[2], &have[3]); err != nil { 1295 | t.Fatalf("rows.Scan() unexpected error: %v", err) 1296 | } 1297 | if !reflect.DeepEqual(have, want) { 1298 | t.Fatalf("rows.Scan() expected %v; got %v", want, have) 1299 | } 1300 | } 1301 | if rows.Next() { 1302 | t.Fatalf("rows.Next() expected false") 1303 | } 1304 | if err := rows.Err(); err != nil { 1305 | t.Fatalf("rows.Err() unexpected error: %v", err) 1306 | } 1307 | } 1308 | -------------------------------------------------------------------------------- /sqlite3/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go-SQLite Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #include "sqlite3.h" 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "bytes" 14 | "fmt" 15 | "reflect" 16 | "unsafe" 17 | ) 18 | 19 | // NamedArgs is a name/value map of arguments passed to a prepared statement 20 | // that uses ?NNN, :AAA, @AAA, and/or $AAA parameter formats. Name matching is 21 | // case-sensitive and the prefix character (one of [?:@$]) must be included in 22 | // the name. Names that are missing from the map are treated as NULL. Names that 23 | // are not used in the prepared statement are ignored. 24 | // 25 | // It is not possible to mix named and anonymous ("?") parameters in the same 26 | // statement. 27 | // [http://www.sqlite.org/lang_expr.html#varparam] 28 | type NamedArgs map[string]interface{} 29 | 30 | // RowMap may be passed as the last (or only) argument to Stmt.Scan to create a 31 | // map of all remaining column/value pairs in the current row. The map is not 32 | // cleared before being populated with new column values. Assignment is 33 | // performed in left-to-right column order, and values may be overwritten if the 34 | // query returns two or more columns with identical names. 35 | type RowMap map[string]interface{} 36 | 37 | // RawString and RawBytes are special string and []byte types that may be used 38 | // for database input and output without the cost of an extra copy operation. 39 | // 40 | // When used as an argument to a statement, the contents are bound using 41 | // SQLITE_STATIC instead of SQLITE_TRANSIENT flag. This requires the contents to 42 | // remain valid and unmodified until the end of statement execution. In 43 | // particular, the caller must keep a reference to the value to prevent it from 44 | // being garbage collected. 45 | // 46 | // When used for retrieving query output, the internal string/[]byte pointer is 47 | // set to reference memory belonging to SQLite. The memory remains valid until 48 | // another method is called on the Stmt object and should not be modified. 49 | type ( 50 | RawString string 51 | RawBytes []byte 52 | ) 53 | 54 | // Copy returns a Go-managed copy of s. 55 | func (s RawString) Copy() string { 56 | if s == "" { 57 | return "" 58 | } 59 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 60 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 61 | } 62 | 63 | // Copy returns a Go-managed copy of b. 64 | func (b RawBytes) Copy() []byte { 65 | if len(b) == 0 { 66 | if b == nil { 67 | return nil 68 | } 69 | return []byte("") 70 | } 71 | h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 72 | return C.GoBytes(unsafe.Pointer(h.Data), C.int(h.Len)) 73 | } 74 | 75 | // ZeroBlob is a special argument type used to allocate a zero-filled BLOB of 76 | // the specified length. The BLOB can then be opened for incremental I/O to 77 | // efficiently transfer a large amount of data. The maximum BLOB size can be 78 | // queried with Conn.Limit(LIMIT_LENGTH, -1). 79 | type ZeroBlob int 80 | 81 | // BusyFunc is a callback function invoked by SQLite when it is unable to 82 | // acquire a lock on a table. Count is the number of times that the callback has 83 | // been invoked for this locking event so far. If the function returns false, 84 | // then the operation is aborted. Otherwise, the function should block for a 85 | // while before returning true and letting SQLite make another locking attempt. 86 | type BusyFunc func(count int) (retry bool) 87 | 88 | // CommitFunc is a callback function invoked by SQLite before a transaction is 89 | // committed. If the function returns true, the transaction is rolled back. 90 | type CommitFunc func() (abort bool) 91 | 92 | // RollbackFunc is a callback function invoked by SQLite when a transaction is 93 | // rolled back. 94 | type RollbackFunc func() 95 | 96 | // UpdateFunc is a callback function invoked by SQLite when a row is updated, 97 | // inserted, or deleted. 98 | type UpdateFunc func(op int, db, tbl RawString, row int64) 99 | 100 | // Error is returned for all SQLite API result codes other than OK, ROW, and 101 | // DONE. 102 | type Error struct { 103 | rc int 104 | msg string 105 | } 106 | 107 | // NewError creates a new Error instance using the specified SQLite result code 108 | // and error message. 109 | func NewError(rc int, msg string) *Error { 110 | return &Error{rc, msg} 111 | } 112 | 113 | // libErr reports an error originating in SQLite. The error message is obtained 114 | // from the database connection when possible, which may include some additional 115 | // information. Otherwise, the result code is translated to a generic message. 116 | func libErr(rc C.int, db *C.sqlite3) error { 117 | if db != nil && rc == C.sqlite3_errcode(db) { 118 | return &Error{int(rc), C.GoString(C.sqlite3_errmsg(db))} 119 | } 120 | return &Error{int(rc), C.GoString(C.sqlite3_errstr(rc))} 121 | } 122 | 123 | // pkgErr reports an error originating in this package. 124 | func pkgErr(rc int, msg string, v ...interface{}) error { 125 | if len(v) == 0 { 126 | return &Error{rc, msg} 127 | } 128 | return &Error{rc, fmt.Sprintf(msg, v...)} 129 | } 130 | 131 | // Code returns the SQLite extended result code. 132 | func (err *Error) Code() int { 133 | return err.rc 134 | } 135 | 136 | // Error implements the error interface. 137 | func (err *Error) Error() string { 138 | return fmt.Sprintf("sqlite3: %s [%d]", err.msg, err.rc) 139 | } 140 | 141 | // Errors returned for access attempts to closed or invalid objects. 142 | var ( 143 | ErrBadConn = &Error{MISUSE, "closed or invalid connection"} 144 | ErrBadStmt = &Error{MISUSE, "closed or invalid statement"} 145 | ErrBadIO = &Error{MISUSE, "closed or invalid incremental I/O operation"} 146 | ErrBadBackup = &Error{MISUSE, "closed or invalid backup operation"} 147 | ) 148 | 149 | // Complete returns true if sql appears to contain a complete statement that is 150 | // ready to be parsed. This does not validate the statement syntax. 151 | // [http://www.sqlite.org/c3ref/complete.html] 152 | func Complete(sql string) bool { 153 | if initErr != nil { 154 | return false 155 | } 156 | sql += "\x00" 157 | return C.sqlite3_complete(cStr(sql)) == 1 158 | } 159 | 160 | // ReleaseMemory attempts to free n bytes of heap memory by deallocating 161 | // non-essential memory held by the SQLite library. It returns the number of 162 | // bytes actually freed. 163 | // 164 | // This function is currently a no-op because SQLite is not compiled with the 165 | // SQLITE_ENABLE_MEMORY_MANAGEMENT option. 166 | // [http://www.sqlite.org/c3ref/release_memory.html] 167 | func ReleaseMemory(n int) int { 168 | if initErr != nil { 169 | return 0 170 | } 171 | return int(C.sqlite3_release_memory(C.int(n))) 172 | } 173 | 174 | // SingleThread returns true if the SQLite library was compiled with 175 | // -DSQLITE_THREADSAFE=0. In this threading mode all mutex code is omitted and 176 | // the package becomes unsafe for concurrent access, even to separate database 177 | // connections. 178 | // 179 | // The SQLite source that's part of this package is compiled with 180 | // -DSQLITE_THREADSAFE=2, so this function should always return false. It is 181 | // kept for backward compatibility when dynamic linking was supported in Go 1.0. 182 | // [http://www.sqlite.org/threadsafe.html] 183 | func SingleThread() bool { 184 | return initErr == nil && C.sqlite3_threadsafe() == 0 185 | } 186 | 187 | // SoftHeapLimit sets and/or queries the soft limit on the amount of heap memory 188 | // that may be allocated by SQLite. A negative value for n keeps the current 189 | // limit, while 0 removes the limit. The previous limit value is returned, with 190 | // negative values indicating an error. 191 | // [http://www.sqlite.org/c3ref/soft_heap_limit64.html] 192 | func SoftHeapLimit(n int64) int64 { 193 | if initErr != nil { 194 | return -1 195 | } 196 | return int64(C.sqlite3_soft_heap_limit64(C.sqlite3_int64(n))) 197 | } 198 | 199 | // SourceId returns the check-in identifier of SQLite within its configuration 200 | // management system. 201 | // [http://www.sqlite.org/c3ref/c_source_id.html] 202 | func SourceId() string { 203 | if initErr != nil { 204 | return "" 205 | } 206 | return C.GoString(C.sqlite3_sourceid()) 207 | } 208 | 209 | // Status returns the current and peak values of a core performance 210 | // counter, specified by one of the STATUS constants. If reset is true, the peak 211 | // value is reset back down to the current value after retrieval. 212 | // [http://www.sqlite.org/c3ref/status.html] 213 | func Status(op int, reset bool) (cur, peak int, err error) { 214 | if initErr != nil { 215 | return 0, 0, initErr 216 | } 217 | var cCur, cPeak C.int 218 | rc := C.sqlite3_status(C.int(op), &cCur, &cPeak, cBool(reset)) 219 | if rc != OK { 220 | return 0, 0, pkgErr(MISUSE, "invalid status op (%d)", op) 221 | } 222 | return int(cCur), int(cPeak), nil 223 | } 224 | 225 | // Version returns the SQLite version as a string in the format "X.Y.Z[.N]". 226 | // [http://www.sqlite.org/c3ref/libversion.html] 227 | func Version() string { 228 | if initErr != nil { 229 | return "" 230 | } 231 | return goStr(C.sqlite3_libversion()) 232 | } 233 | 234 | // VersionNum returns the SQLite version as an integer in the format X*1000000 + 235 | // Y*1000 + Z, where X is the major version, Y is the minor version, and Z is 236 | // the release number. 237 | func VersionNum() int { 238 | if initErr != nil { 239 | return 0 240 | } 241 | return int(C.sqlite3_libversion_number()) 242 | } 243 | 244 | // Print prints out all rows returned by a query. This function is intended as a 245 | // debugging aid and may be removed or altered in the future. Do not use it in 246 | // production applications. 247 | func Print(s *Stmt) error { 248 | if s == nil || s.NumColumns() == 0 { 249 | return nil 250 | } 251 | var err error 252 | if !s.Busy() { 253 | if err = s.Query(); err != nil { 254 | return err 255 | } 256 | } 257 | cols := s.Columns() 258 | buf := bytes.NewBuffer(make([]byte, 0, len(cols)*10)) 259 | row := make(RowMap, len(cols)) 260 | 261 | buf.WriteByte('~') 262 | for _, col := range cols { 263 | fmt.Fprintf(buf, " %s ~", col) 264 | } 265 | fmt.Println(buf) 266 | for ; err == nil; err = s.Next() { 267 | if err = s.Scan(row); err != nil { 268 | return err 269 | } 270 | buf.Reset() 271 | buf.WriteByte('|') 272 | for _, col := range cols { 273 | fmt.Fprintf(buf, " %*v |", len(col), row[col]) 274 | } 275 | fmt.Println(buf) 276 | } 277 | return err 278 | } 279 | 280 | // raw casts s to a RawString. 281 | func raw(s string) RawString { 282 | return RawString(s) 283 | } 284 | 285 | // cStr returns a pointer to the first byte in s. 286 | func cStr(s string) *C.char { 287 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 288 | return (*C.char)(unsafe.Pointer(h.Data)) 289 | } 290 | 291 | // cStrOffset returns the offset of p in s or -1 if p doesn't point into s. 292 | func cStrOffset(s string, p *C.char) int { 293 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 294 | if off := uintptr(unsafe.Pointer(p)) - h.Data; off < uintptr(h.Len) { 295 | return int(off) 296 | } 297 | return -1 298 | } 299 | 300 | // cBytes returns a pointer to the first byte in b. 301 | func cBytes(b []byte) unsafe.Pointer { 302 | return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data) 303 | } 304 | 305 | // cBool returns a C representation of a Go bool (false = 0, true = 1). 306 | func cBool(b bool) C.int { 307 | if b { 308 | return 1 309 | } 310 | return 0 311 | } 312 | 313 | // goStr returns a Go representation of a null-terminated C string. 314 | func goStr(p *C.char) (s string) { 315 | if p != nil && *p != 0 { 316 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 317 | h.Data = uintptr(unsafe.Pointer(p)) 318 | for *p != 0 { 319 | p = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 320 | } 321 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 322 | } 323 | return 324 | } 325 | 326 | // goStrN returns a Go representation of an n-byte C string. 327 | func goStrN(p *C.char, n C.int) (s string) { 328 | if n > 0 { 329 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 330 | h.Data = uintptr(unsafe.Pointer(p)) 331 | h.Len = int(n) 332 | } 333 | return 334 | } 335 | 336 | // goBytes returns a Go representation of an n-byte C array. 337 | func goBytes(p unsafe.Pointer, n C.int) (b []byte) { 338 | if n > 0 { 339 | h := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 340 | h.Data = uintptr(p) 341 | h.Len = int(n) 342 | h.Cap = int(n) 343 | } 344 | return 345 | } 346 | 347 | // bstr returns a string pointing into the byte slice b. 348 | func bstr(b []byte) (s string) { 349 | if len(b) > 0 { 350 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 351 | h.Data = uintptr(unsafe.Pointer(&b[0])) 352 | h.Len = len(b) 353 | } 354 | return 355 | } 356 | 357 | //export go_busy_handler 358 | func go_busy_handler(c unsafe.Pointer, count C.int) (retry C.int) { 359 | return cBool((*Conn)(c).busy(int(count))) 360 | } 361 | 362 | //export go_commit_hook 363 | func go_commit_hook(c unsafe.Pointer) (abort C.int) { 364 | return cBool((*Conn)(c).commit()) 365 | } 366 | 367 | //export go_rollback_hook 368 | func go_rollback_hook(c unsafe.Pointer) { 369 | (*Conn)(c).rollback() 370 | } 371 | 372 | //export go_update_hook 373 | func go_update_hook(c unsafe.Pointer, op C.int, db, tbl *C.char, row C.sqlite3_int64) { 374 | (*Conn)(c).update(int(op), raw(goStr(db)), raw(goStr(tbl)), int64(row)) 375 | } 376 | --------------------------------------------------------------------------------