mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	vendor: update sqlite to fix "database is locked" errors (#2116)
closes #2040
upstream commit: acfa601240
			
			
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							a52cd59727
						
					
				
				
					commit
					2ef33b5338
				
			
							
								
								
									
										30
									
								
								vendor/github.com/mattn/go-sqlite3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/mattn/go-sqlite3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,9 +1,10 @@
 | 
			
		||||
go-sqlite3
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
[](http://godoc.org/github.com/mattn/go-sqlite3)
 | 
			
		||||
[](https://travis-ci.org/mattn/go-sqlite3)
 | 
			
		||||
[](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
 | 
			
		||||
[](http://godoc.org/github.com/mattn/go-sqlite3)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
 | 
			
		||||
 | 
			
		||||
Description
 | 
			
		||||
-----------
 | 
			
		||||
@@ -16,11 +17,11 @@ Installation
 | 
			
		||||
This package can be installed with the go get command:
 | 
			
		||||
 | 
			
		||||
    go get github.com/mattn/go-sqlite3
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
_go-sqlite3_ is *cgo* package.
 | 
			
		||||
If you want to build your app using go-sqlite3, you need gcc.
 | 
			
		||||
However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite3`, you don't need gcc to build your app anymore.
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
Documentation
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
@@ -45,25 +46,40 @@ FAQ
 | 
			
		||||
 | 
			
		||||
   Use `go build --tags "icu"`
 | 
			
		||||
 | 
			
		||||
   Available extensions: `json1`, `fts5`, `icu`
 | 
			
		||||
 | 
			
		||||
* Can't build go-sqlite3 on windows 64bit.
 | 
			
		||||
 | 
			
		||||
    > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit. 
 | 
			
		||||
    > See: https://github.com/mattn/go-sqlite3/issues/27
 | 
			
		||||
    > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
 | 
			
		||||
    > See: [#27](https://github.com/mattn/go-sqlite3/issues/27)
 | 
			
		||||
 | 
			
		||||
* Getting insert error while query is opened.
 | 
			
		||||
 | 
			
		||||
    > You can pass some arguments into the connection string, for example, a URI.
 | 
			
		||||
    > See: https://github.com/mattn/go-sqlite3/issues/39
 | 
			
		||||
    > See: [#39](https://github.com/mattn/go-sqlite3/issues/39)
 | 
			
		||||
 | 
			
		||||
* Do you want to cross compile? mingw on Linux or Mac?
 | 
			
		||||
 | 
			
		||||
    > See: https://github.com/mattn/go-sqlite3/issues/106
 | 
			
		||||
    > See: [#106](https://github.com/mattn/go-sqlite3/issues/106)
 | 
			
		||||
    > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
 | 
			
		||||
 | 
			
		||||
* Want to get time.Time with current locale
 | 
			
		||||
 | 
			
		||||
    Use `loc=auto` in SQLite3 filename schema like `file:foo.db?loc=auto`.
 | 
			
		||||
 | 
			
		||||
* Can I use this in multiple routines concurrently?
 | 
			
		||||
 | 
			
		||||
    Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209).
 | 
			
		||||
 | 
			
		||||
* Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database?
 | 
			
		||||
 | 
			
		||||
    Each connection to :memory: opens a brand new in-memory sql database, so if
 | 
			
		||||
    the stdlib's sql engine happens to open another connection and you've only
 | 
			
		||||
    specified ":memory:", that connection will see a brand new database. A
 | 
			
		||||
    workaround is to use "file::memory:?mode=memory&cache=shared". Every
 | 
			
		||||
    connection to this string will point to the same in-memory database. See
 | 
			
		||||
    [#204](https://github.com/mattn/go-sqlite3/issues/204) for more info.
 | 
			
		||||
 | 
			
		||||
License
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/mattn/go-sqlite3/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/mattn/go-sqlite3/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,10 +19,12 @@ import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SQLiteBackup implement interface of Backup.
 | 
			
		||||
type SQLiteBackup struct {
 | 
			
		||||
	b *C.sqlite3_backup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Backup make backup from src to dest.
 | 
			
		||||
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) {
 | 
			
		||||
	destptr := C.CString(dest)
 | 
			
		||||
	defer C.free(unsafe.Pointer(destptr))
 | 
			
		||||
@@ -37,10 +39,10 @@ func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteB
 | 
			
		||||
	return nil, c.lastError()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Backs up for one step. Calls the underlying `sqlite3_backup_step` function.
 | 
			
		||||
// This function returns a boolean indicating if the backup is done and
 | 
			
		||||
// an error signalling any other error. Done is returned if the underlying C
 | 
			
		||||
// function returns SQLITE_DONE (Code 101)
 | 
			
		||||
// Step to backs up for one step. Calls the underlying `sqlite3_backup_step`
 | 
			
		||||
// function.  This function returns a boolean indicating if the backup is done
 | 
			
		||||
// and an error signalling any other error. Done is returned if the underlying
 | 
			
		||||
// C function returns SQLITE_DONE (Code 101)
 | 
			
		||||
func (b *SQLiteBackup) Step(p int) (bool, error) {
 | 
			
		||||
	ret := C.sqlite3_backup_step(b.b, C.int(p))
 | 
			
		||||
	if ret == C.SQLITE_DONE {
 | 
			
		||||
@@ -51,18 +53,22 @@ func (b *SQLiteBackup) Step(p int) (bool, error) {
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remaining return whether have the rest for backup.
 | 
			
		||||
func (b *SQLiteBackup) Remaining() int {
 | 
			
		||||
	return int(C.sqlite3_backup_remaining(b.b))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PageCount return count of pages.
 | 
			
		||||
func (b *SQLiteBackup) PageCount() int {
 | 
			
		||||
	return int(C.sqlite3_backup_pagecount(b.b))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Finish close backup.
 | 
			
		||||
func (b *SQLiteBackup) Finish() error {
 | 
			
		||||
	return b.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close close backup.
 | 
			
		||||
func (b *SQLiteBackup) Close() error {
 | 
			
		||||
	ret := C.sqlite3_backup_finish(b.b)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/callback.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/callback.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -40,8 +40,8 @@ func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export stepTrampoline
 | 
			
		||||
func stepTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
 | 
			
		||||
	args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
 | 
			
		||||
func stepTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
 | 
			
		||||
	args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
 | 
			
		||||
	ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo)
 | 
			
		||||
	ai.Step(ctx, args)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -110,5 +110,3 @@ See the documentation of RegisterFunc for more details.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
import "C"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/github.com/mattn/go-sqlite3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/mattn/go-sqlite3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,12 +7,16 @@ package sqlite3
 | 
			
		||||
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
// ErrNo inherit errno.
 | 
			
		||||
type ErrNo int
 | 
			
		||||
 | 
			
		||||
// ErrNoMask is mask code.
 | 
			
		||||
const ErrNoMask C.int = 0xff
 | 
			
		||||
 | 
			
		||||
// ErrNoExtended is extended errno.
 | 
			
		||||
type ErrNoExtended int
 | 
			
		||||
 | 
			
		||||
// Error implement sqlite error code.
 | 
			
		||||
type Error struct {
 | 
			
		||||
	Code         ErrNo         /* The error code returned by SQLite */
 | 
			
		||||
	ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */
 | 
			
		||||
@@ -52,14 +56,17 @@ var (
 | 
			
		||||
	ErrWarning    = ErrNo(28) /* Warnings from sqlite3_log() */
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Error return error message from errno.
 | 
			
		||||
func (err ErrNo) Error() string {
 | 
			
		||||
	return Error{Code: err}.Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extend return extended errno.
 | 
			
		||||
func (err ErrNo) Extend(by int) ErrNoExtended {
 | 
			
		||||
	return ErrNoExtended(int(err) | (by << 8))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error return error message that is extended code.
 | 
			
		||||
func (err ErrNoExtended) Error() string {
 | 
			
		||||
	return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error()
 | 
			
		||||
}
 | 
			
		||||
@@ -121,7 +128,7 @@ var (
 | 
			
		||||
	ErrConstraintTrigger      = ErrConstraint.Extend(7)
 | 
			
		||||
	ErrConstraintUnique       = ErrConstraint.Extend(8)
 | 
			
		||||
	ErrConstraintVTab         = ErrConstraint.Extend(9)
 | 
			
		||||
	ErrConstraintRowId        = ErrConstraint.Extend(10)
 | 
			
		||||
	ErrConstraintRowID        = ErrConstraint.Extend(10)
 | 
			
		||||
	ErrNoticeRecoverWAL       = ErrNotice.Extend(1)
 | 
			
		||||
	ErrNoticeRecoverRollback  = ErrNotice.Extend(2)
 | 
			
		||||
	ErrWarningAutoIndex       = ErrWarning.Extend(1)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14445
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14445
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										782
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										782
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										334
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										334
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,9 +7,10 @@ package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#cgo CFLAGS: -std=gnu99
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE=1
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC
 | 
			
		||||
#cgo CFLAGS: -Wno-deprecated-declarations
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
@@ -112,14 +113,17 @@ import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Timestamp formats understood by both this module and SQLite.
 | 
			
		||||
// The first format in the slice will be used when saving time values
 | 
			
		||||
// into the database. When parsing a string from a timestamp or
 | 
			
		||||
// datetime column, the formats are tried in order.
 | 
			
		||||
// SQLiteTimestampFormats is timestamp formats understood by both this module
 | 
			
		||||
// and SQLite.  The first format in the slice will be used when saving time
 | 
			
		||||
// values into the database. When parsing a string from a timestamp or datetime
 | 
			
		||||
// column, the formats are tried in order.
 | 
			
		||||
var SQLiteTimestampFormats = []string{
 | 
			
		||||
	// By default, store timestamps with whatever timezone they come with.
 | 
			
		||||
	// When parsed, they will be returned with the same timezone.
 | 
			
		||||
@@ -139,21 +143,22 @@ func init() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Version returns SQLite library version information.
 | 
			
		||||
func Version() (libVersion string, libVersionNumber int, sourceId string) {
 | 
			
		||||
func Version() (libVersion string, libVersionNumber int, sourceID string) {
 | 
			
		||||
	libVersion = C.GoString(C.sqlite3_libversion())
 | 
			
		||||
	libVersionNumber = int(C.sqlite3_libversion_number())
 | 
			
		||||
	sourceId = C.GoString(C.sqlite3_sourceid())
 | 
			
		||||
	return libVersion, libVersionNumber, sourceId
 | 
			
		||||
	sourceID = C.GoString(C.sqlite3_sourceid())
 | 
			
		||||
	return libVersion, libVersionNumber, sourceID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Driver struct.
 | 
			
		||||
// SQLiteDriver implement sql.Driver.
 | 
			
		||||
type SQLiteDriver struct {
 | 
			
		||||
	Extensions  []string
 | 
			
		||||
	ConnectHook func(*SQLiteConn) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Conn struct.
 | 
			
		||||
// SQLiteConn implement sql.Conn.
 | 
			
		||||
type SQLiteConn struct {
 | 
			
		||||
	dbMu        sync.Mutex
 | 
			
		||||
	db          *C.sqlite3
 | 
			
		||||
	loc         *time.Location
 | 
			
		||||
	txlock      string
 | 
			
		||||
@@ -161,35 +166,34 @@ type SQLiteConn struct {
 | 
			
		||||
	aggregators []*aggInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tx struct.
 | 
			
		||||
// SQLiteTx implemen sql.Tx.
 | 
			
		||||
type SQLiteTx struct {
 | 
			
		||||
	c *SQLiteConn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stmt struct.
 | 
			
		||||
// SQLiteStmt implement sql.Stmt.
 | 
			
		||||
type SQLiteStmt struct {
 | 
			
		||||
	c      *SQLiteConn
 | 
			
		||||
	s      *C.sqlite3_stmt
 | 
			
		||||
	nv     int
 | 
			
		||||
	nn     []string
 | 
			
		||||
	t      string
 | 
			
		||||
	closed bool
 | 
			
		||||
	cls    bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Result struct.
 | 
			
		||||
// SQLiteResult implement sql.Result.
 | 
			
		||||
type SQLiteResult struct {
 | 
			
		||||
	id      int64
 | 
			
		||||
	changes int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rows struct.
 | 
			
		||||
// SQLiteRows implement sql.Rows.
 | 
			
		||||
type SQLiteRows struct {
 | 
			
		||||
	s        *SQLiteStmt
 | 
			
		||||
	nc       int
 | 
			
		||||
	cols     []string
 | 
			
		||||
	decltype []string
 | 
			
		||||
	cls      bool
 | 
			
		||||
	done     chan struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type functionInfo struct {
 | 
			
		||||
@@ -295,19 +299,19 @@ func (ai *aggInfo) Done(ctx *C.sqlite3_context) {
 | 
			
		||||
 | 
			
		||||
// Commit transaction.
 | 
			
		||||
func (tx *SQLiteTx) Commit() error {
 | 
			
		||||
	_, err := tx.c.exec("COMMIT")
 | 
			
		||||
	_, err := tx.c.exec(context.Background(), "COMMIT", nil)
 | 
			
		||||
	if err != nil && err.(Error).Code == C.SQLITE_BUSY {
 | 
			
		||||
		// sqlite3 will leave the transaction open in this scenario.
 | 
			
		||||
		// However, database/sql considers the transaction complete once we
 | 
			
		||||
		// return from Commit() - we must clean up to honour its semantics.
 | 
			
		||||
		tx.c.exec("ROLLBACK")
 | 
			
		||||
		tx.c.exec(context.Background(), "ROLLBACK", nil)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rollback transaction.
 | 
			
		||||
func (tx *SQLiteTx) Rollback() error {
 | 
			
		||||
	_, err := tx.c.exec("ROLLBACK")
 | 
			
		||||
	_, err := tx.c.exec(context.Background(), "ROLLBACK", nil)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -381,34 +385,54 @@ func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) erro
 | 
			
		||||
	if pure {
 | 
			
		||||
		opts |= C.SQLITE_DETERMINISTIC
 | 
			
		||||
	}
 | 
			
		||||
	rv := C._sqlite3_create_function(c.db, cname, C.int(numArgs), C.int(opts), C.uintptr_t(newHandle(c, &fi)), (*[0]byte)(unsafe.Pointer(C.callbackTrampoline)), nil, nil)
 | 
			
		||||
	rv := sqlite3CreateFunction(c.db, cname, C.int(numArgs), C.int(opts), newHandle(c, &fi), C.callbackTrampoline, nil, nil)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
 | 
			
		||||
	return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(unsafe.Pointer(xFunc)), (*[0]byte)(unsafe.Pointer(xStep)), (*[0]byte)(unsafe.Pointer(xFinal)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AutoCommit return which currently auto commit or not.
 | 
			
		||||
func (c *SQLiteConn) AutoCommit() bool {
 | 
			
		||||
	return int(C.sqlite3_get_autocommit(c.db)) != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) lastError() Error {
 | 
			
		||||
func (c *SQLiteConn) lastError() error {
 | 
			
		||||
	return lastError(c.db)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lastError(db *C.sqlite3) error {
 | 
			
		||||
	rv := C.sqlite3_errcode(db)
 | 
			
		||||
	if rv == C.SQLITE_OK {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return Error{
 | 
			
		||||
		Code:         ErrNo(C.sqlite3_errcode(c.db)),
 | 
			
		||||
		ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)),
 | 
			
		||||
		err:          C.GoString(C.sqlite3_errmsg(c.db)),
 | 
			
		||||
		Code:         ErrNo(rv),
 | 
			
		||||
		ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(db)),
 | 
			
		||||
		err:          C.GoString(C.sqlite3_errmsg(db)),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implements Execer
 | 
			
		||||
// Exec implements Execer.
 | 
			
		||||
func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, error) {
 | 
			
		||||
	if len(args) == 0 {
 | 
			
		||||
		return c.exec(query)
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, v := range args {
 | 
			
		||||
		list[i] = namedValue{
 | 
			
		||||
			Ordinal: i + 1,
 | 
			
		||||
			Value:   v,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return c.exec(context.Background(), query, list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) exec(ctx context.Context, query string, args []namedValue) (driver.Result, error) {
 | 
			
		||||
	start := 0
 | 
			
		||||
	for {
 | 
			
		||||
		s, err := c.Prepare(query)
 | 
			
		||||
		s, err := c.prepare(ctx, query)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
@@ -416,14 +440,19 @@ func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, err
 | 
			
		||||
		if s.(*SQLiteStmt).s != nil {
 | 
			
		||||
			na := s.NumInput()
 | 
			
		||||
			if len(args) < na {
 | 
			
		||||
				return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
 | 
			
		||||
				s.Close()
 | 
			
		||||
				return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
 | 
			
		||||
			}
 | 
			
		||||
			res, err = s.Exec(args[:na])
 | 
			
		||||
			for i := 0; i < na; i++ {
 | 
			
		||||
				args[i].Ordinal -= start
 | 
			
		||||
			}
 | 
			
		||||
			res, err = s.(*SQLiteStmt).exec(ctx, args[:na])
 | 
			
		||||
			if err != nil && err != driver.ErrSkip {
 | 
			
		||||
				s.Close()
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			args = args[na:]
 | 
			
		||||
			start += na
 | 
			
		||||
		}
 | 
			
		||||
		tail := s.(*SQLiteStmt).t
 | 
			
		||||
		s.Close()
 | 
			
		||||
@@ -434,24 +463,46 @@ func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implements Queryer
 | 
			
		||||
type namedValue struct {
 | 
			
		||||
	Name    string
 | 
			
		||||
	Ordinal int
 | 
			
		||||
	Value   driver.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Query implements Queryer.
 | 
			
		||||
func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, v := range args {
 | 
			
		||||
		list[i] = namedValue{
 | 
			
		||||
			Ordinal: i + 1,
 | 
			
		||||
			Value:   v,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return c.query(context.Background(), query, list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue) (driver.Rows, error) {
 | 
			
		||||
	start := 0
 | 
			
		||||
	for {
 | 
			
		||||
		s, err := c.Prepare(query)
 | 
			
		||||
		s, err := c.prepare(ctx, query)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		s.(*SQLiteStmt).cls = true
 | 
			
		||||
		na := s.NumInput()
 | 
			
		||||
		if len(args) < na {
 | 
			
		||||
			return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
 | 
			
		||||
			return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
 | 
			
		||||
		}
 | 
			
		||||
		rows, err := s.Query(args[:na])
 | 
			
		||||
		for i := 0; i < na; i++ {
 | 
			
		||||
			args[i].Ordinal -= start
 | 
			
		||||
		}
 | 
			
		||||
		rows, err := s.(*SQLiteStmt).query(ctx, args[:na])
 | 
			
		||||
		if err != nil && err != driver.ErrSkip {
 | 
			
		||||
			s.Close()
 | 
			
		||||
			return nil, err
 | 
			
		||||
			return rows, err
 | 
			
		||||
		}
 | 
			
		||||
		args = args[na:]
 | 
			
		||||
		start += na
 | 
			
		||||
		tail := s.(*SQLiteStmt).t
 | 
			
		||||
		if tail == "" {
 | 
			
		||||
			return rows, nil
 | 
			
		||||
@@ -462,21 +513,13 @@ func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, erro
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) exec(cmd string) (driver.Result, error) {
 | 
			
		||||
	pcmd := C.CString(cmd)
 | 
			
		||||
	defer C.free(unsafe.Pointer(pcmd))
 | 
			
		||||
 | 
			
		||||
	var rowid, changes C.longlong
 | 
			
		||||
	rv := C._sqlite3_exec(c.db, pcmd, &rowid, &changes)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return nil, c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
	return &SQLiteResult{int64(rowid), int64(changes)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Begin transaction.
 | 
			
		||||
func (c *SQLiteConn) Begin() (driver.Tx, error) {
 | 
			
		||||
	if _, err := c.exec(c.txlock); err != nil {
 | 
			
		||||
	return c.begin(context.Background())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
 | 
			
		||||
	if _, err := c.exec(ctx, c.txlock, nil); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &SQLiteTx{c}, nil
 | 
			
		||||
@@ -500,6 +543,8 @@ func errorString(err Error) string {
 | 
			
		||||
//   _txlock=XXX
 | 
			
		||||
//     Specify locking behavior for transactions.  XXX can be "immediate",
 | 
			
		||||
//     "deferred", "exclusive".
 | 
			
		||||
//   _foreign_keys=X
 | 
			
		||||
//     Enable or disable enforcement of foreign keys.  X can be 1 or 0.
 | 
			
		||||
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
	if C.sqlite3_threadsafe() == 0 {
 | 
			
		||||
		return nil, errors.New("sqlite library was not compiled for thread-safe operation")
 | 
			
		||||
@@ -507,7 +552,8 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
 | 
			
		||||
	var loc *time.Location
 | 
			
		||||
	txlock := "BEGIN"
 | 
			
		||||
	busy_timeout := 5000
 | 
			
		||||
	busyTimeout := 5000
 | 
			
		||||
	foreignKeys := -1
 | 
			
		||||
	pos := strings.IndexRune(dsn, '?')
 | 
			
		||||
	if pos >= 1 {
 | 
			
		||||
		params, err := url.ParseQuery(dsn[pos+1:])
 | 
			
		||||
@@ -533,7 +579,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)
 | 
			
		||||
			}
 | 
			
		||||
			busy_timeout = int(iv)
 | 
			
		||||
			busyTimeout = int(iv)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// _txlock
 | 
			
		||||
@@ -550,6 +596,18 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// _foreign_keys
 | 
			
		||||
		if val := params.Get("_foreign_keys"); val != "" {
 | 
			
		||||
			switch val {
 | 
			
		||||
			case "1":
 | 
			
		||||
				foreignKeys = 1
 | 
			
		||||
			case "0":
 | 
			
		||||
				foreignKeys = 0
 | 
			
		||||
			default:
 | 
			
		||||
				return nil, fmt.Errorf("Invalid _foreign_keys: %v", val)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !strings.HasPrefix(dsn, "file:") {
 | 
			
		||||
			dsn = dsn[:pos]
 | 
			
		||||
		}
 | 
			
		||||
@@ -570,21 +628,45 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
		return nil, errors.New("sqlite succeeded without returning a database")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv = C.sqlite3_busy_timeout(db, C.int(busy_timeout))
 | 
			
		||||
	rv = C.sqlite3_busy_timeout(db, C.int(busyTimeout))
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		C.sqlite3_close_v2(db)
 | 
			
		||||
		return nil, Error{Code: ErrNo(rv)}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	exec := func(s string) error {
 | 
			
		||||
		cs := C.CString(s)
 | 
			
		||||
		rv := C.sqlite3_exec(db, cs, nil, nil, nil)
 | 
			
		||||
		C.free(unsafe.Pointer(cs))
 | 
			
		||||
		if rv != C.SQLITE_OK {
 | 
			
		||||
			return lastError(db)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if foreignKeys == 0 {
 | 
			
		||||
		if err := exec("PRAGMA foreign_keys = OFF;"); err != nil {
 | 
			
		||||
			C.sqlite3_close_v2(db)
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	} else if foreignKeys == 1 {
 | 
			
		||||
		if err := exec("PRAGMA foreign_keys = ON;"); err != nil {
 | 
			
		||||
			C.sqlite3_close_v2(db)
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
 | 
			
		||||
 | 
			
		||||
	if len(d.Extensions) > 0 {
 | 
			
		||||
		if err := conn.loadExtensions(d.Extensions); err != nil {
 | 
			
		||||
			conn.Close()
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if d.ConnectHook != nil {
 | 
			
		||||
		if err := d.ConnectHook(conn); err != nil {
 | 
			
		||||
			conn.Close()
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -594,18 +676,33 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
 | 
			
		||||
// Close the connection.
 | 
			
		||||
func (c *SQLiteConn) Close() error {
 | 
			
		||||
	deleteHandles(c)
 | 
			
		||||
	rv := C.sqlite3_close_v2(c.db)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
	deleteHandles(c)
 | 
			
		||||
	c.dbMu.Lock()
 | 
			
		||||
	c.db = nil
 | 
			
		||||
	c.dbMu.Unlock()
 | 
			
		||||
	runtime.SetFinalizer(c, nil)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) dbConnOpen() bool {
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	c.dbMu.Lock()
 | 
			
		||||
	defer c.dbMu.Unlock()
 | 
			
		||||
	return c.db != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Prepare the query string. Return a new statement.
 | 
			
		||||
func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
 | 
			
		||||
	return c.prepare(context.Background(), query)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, error) {
 | 
			
		||||
	pquery := C.CString(query)
 | 
			
		||||
	defer C.free(unsafe.Pointer(pquery))
 | 
			
		||||
	var s *C.sqlite3_stmt
 | 
			
		||||
@@ -618,15 +715,7 @@ func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
 | 
			
		||||
	if tail != nil && *tail != '\000' {
 | 
			
		||||
		t = strings.TrimSpace(C.GoString(tail))
 | 
			
		||||
	}
 | 
			
		||||
	nv := int(C.sqlite3_bind_parameter_count(s))
 | 
			
		||||
	var nn []string
 | 
			
		||||
	for i := 0; i < nv; i++ {
 | 
			
		||||
		pn := C.GoString(C.sqlite3_bind_parameter_name(s, C.int(i+1)))
 | 
			
		||||
		if len(pn) > 1 && pn[0] == '$' && 48 <= pn[1] && pn[1] <= 57 {
 | 
			
		||||
			nn = append(nn, C.GoString(C.sqlite3_bind_parameter_name(s, C.int(i+1))))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ss := &SQLiteStmt{c: c, s: s, nv: nv, nn: nn, t: t}
 | 
			
		||||
	ss := &SQLiteStmt{c: c, s: s, t: t}
 | 
			
		||||
	runtime.SetFinalizer(ss, (*SQLiteStmt).Close)
 | 
			
		||||
	return ss, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -637,7 +726,7 @@ func (s *SQLiteStmt) Close() error {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	s.closed = true
 | 
			
		||||
	if s.c == nil || s.c.db == nil {
 | 
			
		||||
	if !s.c.dbConnOpen() {
 | 
			
		||||
		return errors.New("sqlite statement with already closed database connection")
 | 
			
		||||
	}
 | 
			
		||||
	rv := C.sqlite3_finalize(s.s)
 | 
			
		||||
@@ -648,9 +737,9 @@ func (s *SQLiteStmt) Close() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return a number of parameters.
 | 
			
		||||
// NumInput return a number of parameters.
 | 
			
		||||
func (s *SQLiteStmt) NumInput() int {
 | 
			
		||||
	return s.nv
 | 
			
		||||
	return int(C.sqlite3_bind_parameter_count(s.s))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bindArg struct {
 | 
			
		||||
@@ -658,37 +747,30 @@ type bindArg struct {
 | 
			
		||||
	v driver.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLiteStmt) bind(args []driver.Value) error {
 | 
			
		||||
var placeHolder = []byte{0}
 | 
			
		||||
 | 
			
		||||
func (s *SQLiteStmt) bind(args []namedValue) error {
 | 
			
		||||
	rv := C.sqlite3_reset(s.s)
 | 
			
		||||
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
 | 
			
		||||
		return s.c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var vargs []bindArg
 | 
			
		||||
	narg := len(args)
 | 
			
		||||
	vargs = make([]bindArg, narg)
 | 
			
		||||
	if len(s.nn) > 0 {
 | 
			
		||||
		for i, v := range s.nn {
 | 
			
		||||
			if pi, err := strconv.Atoi(v[1:]); err == nil {
 | 
			
		||||
				vargs[i] = bindArg{pi, args[i]}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		for i, v := range args {
 | 
			
		||||
			vargs[i] = bindArg{i + 1, v}
 | 
			
		||||
	for i, v := range args {
 | 
			
		||||
		if v.Name != "" {
 | 
			
		||||
			cname := C.CString(":" + v.Name)
 | 
			
		||||
			args[i].Ordinal = int(C.sqlite3_bind_parameter_index(s.s, cname))
 | 
			
		||||
			C.free(unsafe.Pointer(cname))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, varg := range vargs {
 | 
			
		||||
		n := C.int(varg.n)
 | 
			
		||||
		v := varg.v
 | 
			
		||||
		switch v := v.(type) {
 | 
			
		||||
	for _, arg := range args {
 | 
			
		||||
		n := C.int(arg.Ordinal)
 | 
			
		||||
		switch v := arg.Value.(type) {
 | 
			
		||||
		case nil:
 | 
			
		||||
			rv = C.sqlite3_bind_null(s.s, n)
 | 
			
		||||
		case string:
 | 
			
		||||
			if len(v) == 0 {
 | 
			
		||||
				b := []byte{0}
 | 
			
		||||
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0))
 | 
			
		||||
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.int(0))
 | 
			
		||||
			} else {
 | 
			
		||||
				b := []byte(v)
 | 
			
		||||
				rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
 | 
			
		||||
@@ -705,10 +787,9 @@ func (s *SQLiteStmt) bind(args []driver.Value) error {
 | 
			
		||||
			rv = C.sqlite3_bind_double(s.s, n, C.double(v))
 | 
			
		||||
		case []byte:
 | 
			
		||||
			if len(v) == 0 {
 | 
			
		||||
				rv = C._sqlite3_bind_blob(s.s, n, nil, 0)
 | 
			
		||||
			} else {
 | 
			
		||||
				rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(len(v)))
 | 
			
		||||
				v = placeHolder
 | 
			
		||||
			}
 | 
			
		||||
			rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(len(v)))
 | 
			
		||||
		case time.Time:
 | 
			
		||||
			b := []byte(v.Format(SQLiteTimestampFormats[0]))
 | 
			
		||||
			rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
 | 
			
		||||
@@ -722,29 +803,85 @@ func (s *SQLiteStmt) bind(args []driver.Value) error {
 | 
			
		||||
 | 
			
		||||
// Query the statement with arguments. Return records.
 | 
			
		||||
func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, v := range args {
 | 
			
		||||
		list[i] = namedValue{
 | 
			
		||||
			Ordinal: i + 1,
 | 
			
		||||
			Value:   v,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return s.query(context.Background(), list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows, error) {
 | 
			
		||||
	if err := s.bind(args); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &SQLiteRows{s, int(C.sqlite3_column_count(s.s)), nil, nil, s.cls}, nil
 | 
			
		||||
 | 
			
		||||
	rows := &SQLiteRows{
 | 
			
		||||
		s:        s,
 | 
			
		||||
		nc:       int(C.sqlite3_column_count(s.s)),
 | 
			
		||||
		cols:     nil,
 | 
			
		||||
		decltype: nil,
 | 
			
		||||
		cls:      s.cls,
 | 
			
		||||
		done:     make(chan struct{}),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	go func(db *C.sqlite3) {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-ctx.Done():
 | 
			
		||||
			select {
 | 
			
		||||
			case <-rows.done:
 | 
			
		||||
			default:
 | 
			
		||||
				C.sqlite3_interrupt(db)
 | 
			
		||||
				rows.Close()
 | 
			
		||||
			}
 | 
			
		||||
		case <-rows.done:
 | 
			
		||||
		}
 | 
			
		||||
	}(s.c.db)
 | 
			
		||||
 | 
			
		||||
	return rows, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return last inserted ID.
 | 
			
		||||
// LastInsertId teturn last inserted ID.
 | 
			
		||||
func (r *SQLiteResult) LastInsertId() (int64, error) {
 | 
			
		||||
	return r.id, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return how many rows affected.
 | 
			
		||||
// RowsAffected return how many rows affected.
 | 
			
		||||
func (r *SQLiteResult) RowsAffected() (int64, error) {
 | 
			
		||||
	return r.changes, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Execute the statement with arguments. Return result object.
 | 
			
		||||
// Exec execute the statement with arguments. Return result object.
 | 
			
		||||
func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, v := range args {
 | 
			
		||||
		list[i] = namedValue{
 | 
			
		||||
			Ordinal: i + 1,
 | 
			
		||||
			Value:   v,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return s.exec(context.Background(), list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result, error) {
 | 
			
		||||
	if err := s.bind(args); err != nil {
 | 
			
		||||
		C.sqlite3_reset(s.s)
 | 
			
		||||
		C.sqlite3_clear_bindings(s.s)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	done := make(chan struct{})
 | 
			
		||||
	defer close(done)
 | 
			
		||||
	go func(db *C.sqlite3) {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-ctx.Done():
 | 
			
		||||
			C.sqlite3_interrupt(db)
 | 
			
		||||
		case <-done:
 | 
			
		||||
		}
 | 
			
		||||
	}(s.c.db)
 | 
			
		||||
 | 
			
		||||
	var rowid, changes C.longlong
 | 
			
		||||
	rv := C._sqlite3_step(s.s, &rowid, &changes)
 | 
			
		||||
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
 | 
			
		||||
@@ -753,7 +890,8 @@ func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
 | 
			
		||||
		C.sqlite3_clear_bindings(s.s)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &SQLiteResult{int64(rowid), int64(changes)}, nil
 | 
			
		||||
 | 
			
		||||
	return &SQLiteResult{id: int64(rowid), changes: int64(changes)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close the rows.
 | 
			
		||||
@@ -761,6 +899,9 @@ func (rc *SQLiteRows) Close() error {
 | 
			
		||||
	if rc.s.closed {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if rc.done != nil {
 | 
			
		||||
		close(rc.done)
 | 
			
		||||
	}
 | 
			
		||||
	if rc.cls {
 | 
			
		||||
		return rc.s.Close()
 | 
			
		||||
	}
 | 
			
		||||
@@ -771,7 +912,7 @@ func (rc *SQLiteRows) Close() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return column names.
 | 
			
		||||
// Columns return column names.
 | 
			
		||||
func (rc *SQLiteRows) Columns() []string {
 | 
			
		||||
	if rc.nc != len(rc.cols) {
 | 
			
		||||
		rc.cols = make([]string, rc.nc)
 | 
			
		||||
@@ -782,7 +923,7 @@ func (rc *SQLiteRows) Columns() []string {
 | 
			
		||||
	return rc.cols
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return column types.
 | 
			
		||||
// DeclTypes return column types.
 | 
			
		||||
func (rc *SQLiteRows) DeclTypes() []string {
 | 
			
		||||
	if rc.decltype == nil {
 | 
			
		||||
		rc.decltype = make([]string, rc.nc)
 | 
			
		||||
@@ -793,7 +934,7 @@ func (rc *SQLiteRows) DeclTypes() []string {
 | 
			
		||||
	return rc.decltype
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Move cursor to next.
 | 
			
		||||
// Next move cursor to next.
 | 
			
		||||
func (rc *SQLiteRows) Next(dest []driver.Value) error {
 | 
			
		||||
	rv := C.sqlite3_step(rc.s.s)
 | 
			
		||||
	if rv == C.SQLITE_DONE {
 | 
			
		||||
@@ -820,10 +961,11 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
 | 
			
		||||
				// large to be a reasonable timestamp in seconds.
 | 
			
		||||
				if val > 1e12 || val < -1e12 {
 | 
			
		||||
					val *= int64(time.Millisecond) // convert ms to nsec
 | 
			
		||||
					t = time.Unix(0, val)
 | 
			
		||||
				} else {
 | 
			
		||||
					val *= int64(time.Second) // convert sec to nsec
 | 
			
		||||
					t = time.Unix(val, 0)
 | 
			
		||||
				}
 | 
			
		||||
				t = time.Unix(0, val).UTC()
 | 
			
		||||
				t = t.UTC()
 | 
			
		||||
				if rc.s.c.loc != nil {
 | 
			
		||||
					t = t.In(rc.s.c.loc)
 | 
			
		||||
				}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sqlite3.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
// These wrappers are necessary because SQLITE_TRANSIENT
 | 
			
		||||
// is a pointer constant, and cgo doesn't translate them correctly.
 | 
			
		||||
 | 
			
		||||
static inline void my_result_text(sqlite3_context *ctx, char *p, int np) {
 | 
			
		||||
	sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) {
 | 
			
		||||
	sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT);
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const i64 = unsafe.Sizeof(int(0)) > 4
 | 
			
		||||
 | 
			
		||||
// SQLiteContext behave sqlite3_context
 | 
			
		||||
type SQLiteContext C.sqlite3_context
 | 
			
		||||
 | 
			
		||||
// ResultBool sets the result of an SQL function.
 | 
			
		||||
func (c *SQLiteContext) ResultBool(b bool) {
 | 
			
		||||
	if b {
 | 
			
		||||
		c.ResultInt(1)
 | 
			
		||||
	} else {
 | 
			
		||||
		c.ResultInt(0)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultBlob sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultBlob(b []byte) {
 | 
			
		||||
	if i64 && len(b) > math.MaxInt32 {
 | 
			
		||||
		C.sqlite3_result_error_toobig((*C.sqlite3_context)(c))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var p *byte
 | 
			
		||||
	if len(b) > 0 {
 | 
			
		||||
		p = &b[0]
 | 
			
		||||
	}
 | 
			
		||||
	C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultDouble sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultDouble(d float64) {
 | 
			
		||||
	C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultInt sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultInt(i int) {
 | 
			
		||||
	if i64 && (i > math.MaxInt32 || i < math.MinInt32) {
 | 
			
		||||
		C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
 | 
			
		||||
	} else {
 | 
			
		||||
		C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultInt64 sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultInt64(i int64) {
 | 
			
		||||
	C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultNull sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultNull() {
 | 
			
		||||
	C.sqlite3_result_null((*C.sqlite3_context)(c))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultText sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultText(s string) {
 | 
			
		||||
	h := (*reflect.StringHeader)(unsafe.Pointer(&s))
 | 
			
		||||
	cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)
 | 
			
		||||
	C.my_result_text((*C.sqlite3_context)(c), cs, l)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResultZeroblob sets the result of an SQL function.
 | 
			
		||||
// See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html
 | 
			
		||||
func (c *SQLiteContext) ResultZeroblob(n int) {
 | 
			
		||||
	C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build go1.8
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql/driver"
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Ping implement Pinger.
 | 
			
		||||
func (c *SQLiteConn) Ping(ctx context.Context) error {
 | 
			
		||||
	if c.db == nil {
 | 
			
		||||
		return errors.New("Connection was closed")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryContext implement QueryerContext.
 | 
			
		||||
func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, nv := range args {
 | 
			
		||||
		list[i] = namedValue(nv)
 | 
			
		||||
	}
 | 
			
		||||
	return c.query(ctx, query, list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExecContext implement ExecerContext.
 | 
			
		||||
func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, nv := range args {
 | 
			
		||||
		list[i] = namedValue(nv)
 | 
			
		||||
	}
 | 
			
		||||
	return c.exec(ctx, query, list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrepareContext implement ConnPrepareContext.
 | 
			
		||||
func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
 | 
			
		||||
	return c.prepare(ctx, query)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BeginTx implement ConnBeginTx.
 | 
			
		||||
func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
 | 
			
		||||
	return c.begin(ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryContext implement QueryerContext.
 | 
			
		||||
func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, nv := range args {
 | 
			
		||||
		list[i] = namedValue(nv)
 | 
			
		||||
	}
 | 
			
		||||
	return s.query(ctx, list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExecContext implement ExecerContext.
 | 
			
		||||
func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
 | 
			
		||||
	list := make([]namedValue, len(args))
 | 
			
		||||
	for i, nv := range args {
 | 
			
		||||
		list[i] = namedValue(nv)
 | 
			
		||||
	}
 | 
			
		||||
	return s.exec(ctx, list)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_icu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
// +build icu 
 | 
			
		||||
// +build icu
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -31,6 +31,7 @@ func (c *SQLiteConn) loadExtensions(extensions []string) error {
 | 
			
		||||
		defer C.free(unsafe.Pointer(cext))
 | 
			
		||||
		rv = C.sqlite3_load_extension(c.db, cext, nil, nil)
 | 
			
		||||
		if rv != C.SQLITE_OK {
 | 
			
		||||
			C.sqlite3_enable_load_extension(c.db, 0)
 | 
			
		||||
			return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -42,6 +43,7 @@ func (c *SQLiteConn) loadExtensions(extensions []string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadExtension load the sqlite3 extension.
 | 
			
		||||
func (c *SQLiteConn) LoadExtension(lib string, entry string) error {
 | 
			
		||||
	rv := C.sqlite3_enable_load_extension(c.db, 1)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
// Copyright (C) 2016 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// TODO: add "Gimpl do foo" team?
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
@@ -17,7 +16,7 @@ package sqlite3
 | 
			
		||||
 | 
			
		||||
void stepTrampoline(sqlite3_context*, int, sqlite3_value**);
 | 
			
		||||
void doneTrampoline(sqlite3_context*);
 | 
			
		||||
void traceCallbackTrampoline(unsigned traceEventCode, void *ctx, void *p, void *x);
 | 
			
		||||
int traceCallbackTrampoline(unsigned int traceEventCode, void *ctx, void *p, void *x);
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +75,7 @@ type TraceUserCallback func(TraceInfo) int
 | 
			
		||||
 | 
			
		||||
type TraceConfig struct {
 | 
			
		||||
	Callback        TraceUserCallback
 | 
			
		||||
	EventMask       uint
 | 
			
		||||
	EventMask       C.uint
 | 
			
		||||
	WantExpandedSQL bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -102,13 +101,13 @@ func fillExpandedSQL(info *TraceInfo, db *C.sqlite3, pStmt unsafe.Pointer) {
 | 
			
		||||
 | 
			
		||||
//export traceCallbackTrampoline
 | 
			
		||||
func traceCallbackTrampoline(
 | 
			
		||||
	traceEventCode uint,
 | 
			
		||||
	traceEventCode C.uint,
 | 
			
		||||
	// Parameter named 'C' in SQLite docs = Context given at registration:
 | 
			
		||||
	ctx unsafe.Pointer,
 | 
			
		||||
	// Parameter named 'P' in SQLite docs (Primary event data?):
 | 
			
		||||
	p unsafe.Pointer,
 | 
			
		||||
	// Parameter named 'X' in SQLite docs (eXtra event data?):
 | 
			
		||||
	xValue unsafe.Pointer) int {
 | 
			
		||||
	xValue unsafe.Pointer) C.int {
 | 
			
		||||
 | 
			
		||||
	if ctx == nil {
 | 
			
		||||
		panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode))
 | 
			
		||||
@@ -196,7 +195,7 @@ func traceCallbackTrampoline(
 | 
			
		||||
	if traceConf.Callback != nil {
 | 
			
		||||
		r = traceConf.Callback(info)
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
	return C.int(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type traceMapEntry struct {
 | 
			
		||||
@@ -358,7 +357,7 @@ func (c *SQLiteConn) RegisterAggregator(name string, impl interface{}, pure bool
 | 
			
		||||
	if pure {
 | 
			
		||||
		opts |= C.SQLITE_DETERMINISTIC
 | 
			
		||||
	}
 | 
			
		||||
	rv := C._sqlite3_create_function(c.db, cname, C.int(stepNArgs), C.int(opts), C.uintptr_t(newHandle(c, &ai)), nil, (*[0]byte)(unsafe.Pointer(C.stepTrampoline)), (*[0]byte)(unsafe.Pointer(C.doneTrampoline)))
 | 
			
		||||
	rv := sqlite3CreateFunction(c.db, cname, C.int(stepNArgs), C.int(opts), newHandle(c, &ai), nil, C.stepTrampoline, C.doneTrampoline)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
@@ -396,7 +395,7 @@ func (c *SQLiteConn) SetTrace(requested *TraceConfig) error {
 | 
			
		||||
	// The callback trampoline function does cleanup on Close event,
 | 
			
		||||
	// regardless of the presence or absence of the user callback.
 | 
			
		||||
	// Therefore it needs the Close event to be selected:
 | 
			
		||||
	actualEventMask := reqCopy.EventMask | TraceClose
 | 
			
		||||
	actualEventMask := uint(reqCopy.EventMask | TraceClose)
 | 
			
		||||
	err := c.setSQLiteTrace(actualEventMask)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sqlite3.h>
 | 
			
		||||
#endif
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName.
 | 
			
		||||
func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string {
 | 
			
		||||
	return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) {
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
 | 
			
		||||
	return 0, 0, false
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// ColumnTypeNullable implement RowsColumnTypeNullable.
 | 
			
		||||
func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) {
 | 
			
		||||
	return true, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ColumnTypeScanType implement RowsColumnTypeScanType.
 | 
			
		||||
func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type {
 | 
			
		||||
	switch C.sqlite3_column_type(rc.s.s, C.int(i)) {
 | 
			
		||||
	case C.SQLITE_INTEGER:
 | 
			
		||||
		switch C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))) {
 | 
			
		||||
		case "timestamp", "datetime", "date":
 | 
			
		||||
			return reflect.TypeOf(time.Time{})
 | 
			
		||||
		case "boolean":
 | 
			
		||||
			return reflect.TypeOf(false)
 | 
			
		||||
		}
 | 
			
		||||
		return reflect.TypeOf(int64(0))
 | 
			
		||||
	case C.SQLITE_FLOAT:
 | 
			
		||||
		return reflect.TypeOf(float64(0))
 | 
			
		||||
	case C.SQLITE_BLOB:
 | 
			
		||||
		return reflect.SliceOf(reflect.TypeOf(byte(0)))
 | 
			
		||||
	case C.SQLITE_NULL:
 | 
			
		||||
		return reflect.TypeOf(nil)
 | 
			
		||||
	case C.SQLITE_TEXT:
 | 
			
		||||
		return reflect.TypeOf("")
 | 
			
		||||
	}
 | 
			
		||||
	return reflect.SliceOf(reflect.TypeOf(byte(0)))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										646
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										646
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_vtable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,646 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
// +build vtable
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#cgo CFLAGS: -std=gnu99
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1
 | 
			
		||||
#cgo CFLAGS: -Wno-deprecated-declarations
 | 
			
		||||
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sqlite3.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <memory.h>
 | 
			
		||||
 | 
			
		||||
static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
 | 
			
		||||
  return sqlite3_mprintf(zFormat, arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct goVTab goVTab;
 | 
			
		||||
 | 
			
		||||
struct goVTab {
 | 
			
		||||
	sqlite3_vtab base;
 | 
			
		||||
	void *vTab;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
uintptr_t goMInit(void *db, void *pAux, int argc, char **argv, char **pzErr, int isCreate);
 | 
			
		||||
 | 
			
		||||
static int cXInit(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr, int isCreate) {
 | 
			
		||||
	void *vTab = (void *)goMInit(db, pAux, argc, (char**)argv, pzErr, isCreate);
 | 
			
		||||
	if (!vTab || *pzErr) {
 | 
			
		||||
		return SQLITE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	goVTab *pvTab = (goVTab *)sqlite3_malloc(sizeof(goVTab));
 | 
			
		||||
	if (!pvTab) {
 | 
			
		||||
		*pzErr = sqlite3_mprintf("%s", "Out of memory");
 | 
			
		||||
		return SQLITE_NOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	memset(pvTab, 0, sizeof(goVTab));
 | 
			
		||||
	pvTab->vTab = vTab;
 | 
			
		||||
 | 
			
		||||
	*ppVTab = (sqlite3_vtab *)pvTab;
 | 
			
		||||
	*pzErr = 0;
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int cXCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
 | 
			
		||||
	return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 1);
 | 
			
		||||
}
 | 
			
		||||
static inline int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
 | 
			
		||||
	return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVBestIndex(void *pVTab, void *icp);
 | 
			
		||||
 | 
			
		||||
static inline int cXBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *info) {
 | 
			
		||||
	char *pzErr = goVBestIndex(((goVTab*)pVTab)->vTab, info);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		if (pVTab->zErrMsg)
 | 
			
		||||
			sqlite3_free(pVTab->zErrMsg);
 | 
			
		||||
		pVTab->zErrMsg = pzErr;
 | 
			
		||||
		return SQLITE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVRelease(void *pVTab, int isDestroy);
 | 
			
		||||
 | 
			
		||||
static int cXRelease(sqlite3_vtab *pVTab, int isDestroy) {
 | 
			
		||||
	char *pzErr = goVRelease(((goVTab*)pVTab)->vTab, isDestroy);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		if (pVTab->zErrMsg)
 | 
			
		||||
			sqlite3_free(pVTab->zErrMsg);
 | 
			
		||||
		pVTab->zErrMsg = pzErr;
 | 
			
		||||
		return SQLITE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	if (pVTab->zErrMsg)
 | 
			
		||||
		sqlite3_free(pVTab->zErrMsg);
 | 
			
		||||
	sqlite3_free(pVTab);
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int cXDisconnect(sqlite3_vtab *pVTab) {
 | 
			
		||||
	return cXRelease(pVTab, 0);
 | 
			
		||||
}
 | 
			
		||||
static inline int cXDestroy(sqlite3_vtab *pVTab) {
 | 
			
		||||
	return cXRelease(pVTab, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct goVTabCursor goVTabCursor;
 | 
			
		||||
 | 
			
		||||
struct goVTabCursor {
 | 
			
		||||
	sqlite3_vtab_cursor base;
 | 
			
		||||
	void *vTabCursor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
uintptr_t goVOpen(void *pVTab, char **pzErr);
 | 
			
		||||
 | 
			
		||||
static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
 | 
			
		||||
	void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
 | 
			
		||||
	goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
 | 
			
		||||
	if (!pCursor) {
 | 
			
		||||
		return SQLITE_NOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	memset(pCursor, 0, sizeof(goVTabCursor));
 | 
			
		||||
	pCursor->vTabCursor = vTabCursor;
 | 
			
		||||
	*ppCursor = (sqlite3_vtab_cursor *)pCursor;
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int setErrMsg(sqlite3_vtab_cursor *pCursor, char *pzErr) {
 | 
			
		||||
	if (pCursor->pVtab->zErrMsg)
 | 
			
		||||
		sqlite3_free(pCursor->pVtab->zErrMsg);
 | 
			
		||||
	pCursor->pVtab->zErrMsg = pzErr;
 | 
			
		||||
	return SQLITE_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVClose(void *pCursor);
 | 
			
		||||
 | 
			
		||||
static int cXClose(sqlite3_vtab_cursor *pCursor) {
 | 
			
		||||
	char *pzErr = goVClose(((goVTabCursor*)pCursor)->vTabCursor);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		return setErrMsg(pCursor, pzErr);
 | 
			
		||||
	}
 | 
			
		||||
	sqlite3_free(pCursor);
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVFilter(void *pCursor, int idxNum, char* idxName, int argc, sqlite3_value **argv);
 | 
			
		||||
 | 
			
		||||
static int cXFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
 | 
			
		||||
	char *pzErr = goVFilter(((goVTabCursor*)pCursor)->vTabCursor, idxNum, (char*)idxStr, argc, argv);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		return setErrMsg(pCursor, pzErr);
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVNext(void *pCursor);
 | 
			
		||||
 | 
			
		||||
static int cXNext(sqlite3_vtab_cursor *pCursor) {
 | 
			
		||||
	char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		return setErrMsg(pCursor, pzErr);
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int goVEof(void *pCursor);
 | 
			
		||||
 | 
			
		||||
static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
 | 
			
		||||
	return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVColumn(void *pCursor, void *cp, int col);
 | 
			
		||||
 | 
			
		||||
static int cXColumn(sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i) {
 | 
			
		||||
	char *pzErr = goVColumn(((goVTabCursor*)pCursor)->vTabCursor, ctx, i);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		return setErrMsg(pCursor, pzErr);
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVRowid(void *pCursor, sqlite3_int64 *pRowid);
 | 
			
		||||
 | 
			
		||||
static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
 | 
			
		||||
	char *pzErr = goVRowid(((goVTabCursor*)pCursor)->vTabCursor, pRowid);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		return setErrMsg(pCursor, pzErr);
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* goVUpdate(void *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid);
 | 
			
		||||
 | 
			
		||||
static int cXUpdate(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
 | 
			
		||||
	char *pzErr = goVUpdate(((goVTab*)pVTab)->vTab, argc, argv, pRowid);
 | 
			
		||||
	if (pzErr) {
 | 
			
		||||
		if (pVTab->zErrMsg)
 | 
			
		||||
			sqlite3_free(pVTab->zErrMsg);
 | 
			
		||||
		pVTab->zErrMsg = pzErr;
 | 
			
		||||
		return SQLITE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	return SQLITE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static sqlite3_module goModule = {
 | 
			
		||||
	0,                       // iVersion
 | 
			
		||||
	cXCreate,                // xCreate - create a table
 | 
			
		||||
	cXConnect,               // xConnect - connect to an existing table
 | 
			
		||||
	cXBestIndex,             // xBestIndex - Determine search strategy
 | 
			
		||||
	cXDisconnect,            // xDisconnect - Disconnect from a table
 | 
			
		||||
	cXDestroy,               // xDestroy - Drop a table
 | 
			
		||||
	cXOpen,                  // xOpen - open a cursor
 | 
			
		||||
	cXClose,                 // xClose - close a cursor
 | 
			
		||||
	cXFilter,                // xFilter - configure scan constraints
 | 
			
		||||
	cXNext,                  // xNext - advance a cursor
 | 
			
		||||
	cXEof,                   // xEof
 | 
			
		||||
	cXColumn,                // xColumn - read data
 | 
			
		||||
	cXRowid,                 // xRowid - read data
 | 
			
		||||
	cXUpdate,                // xUpdate - write data
 | 
			
		||||
// Not implemented
 | 
			
		||||
	0,                       // xBegin - begin transaction
 | 
			
		||||
	0,                       // xSync - sync transaction
 | 
			
		||||
	0,                       // xCommit - commit transaction
 | 
			
		||||
	0,                       // xRollback - rollback transaction
 | 
			
		||||
	0,                       // xFindFunction - function overloading
 | 
			
		||||
	0,                       // xRename - rename the table
 | 
			
		||||
	0,                       // xSavepoint
 | 
			
		||||
	0,                       // xRelease
 | 
			
		||||
	0	                     // xRollbackTo
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void goMDestroy(void*);
 | 
			
		||||
 | 
			
		||||
static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
 | 
			
		||||
  return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type sqliteModule struct {
 | 
			
		||||
	c      *SQLiteConn
 | 
			
		||||
	name   string
 | 
			
		||||
	module Module
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sqliteVTab struct {
 | 
			
		||||
	module *sqliteModule
 | 
			
		||||
	vTab   VTab
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sqliteVTabCursor struct {
 | 
			
		||||
	vTab       *sqliteVTab
 | 
			
		||||
	vTabCursor VTabCursor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Op is type of operations.
 | 
			
		||||
type Op uint8
 | 
			
		||||
 | 
			
		||||
// Op mean identity of operations.
 | 
			
		||||
const (
 | 
			
		||||
	OpEQ         Op = 2
 | 
			
		||||
	OpGT            = 4
 | 
			
		||||
	OpLE            = 8
 | 
			
		||||
	OpLT            = 16
 | 
			
		||||
	OpGE            = 32
 | 
			
		||||
	OpMATCH         = 64
 | 
			
		||||
	OpLIKE          = 65 /* 3.10.0 and later only */
 | 
			
		||||
	OpGLOB          = 66 /* 3.10.0 and later only */
 | 
			
		||||
	OpREGEXP        = 67 /* 3.10.0 and later only */
 | 
			
		||||
	OpScanUnique    = 1  /* Scan visits at most 1 row */
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InfoConstraint give information of constraint.
 | 
			
		||||
type InfoConstraint struct {
 | 
			
		||||
	Column int
 | 
			
		||||
	Op     Op
 | 
			
		||||
	Usable bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InfoOrderBy give information of order-by.
 | 
			
		||||
type InfoOrderBy struct {
 | 
			
		||||
	Column int
 | 
			
		||||
	Desc   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func constraints(info *C.sqlite3_index_info) []InfoConstraint {
 | 
			
		||||
	l := info.nConstraint
 | 
			
		||||
	slice := (*[1 << 30]C.struct_sqlite3_index_constraint)(unsafe.Pointer(info.aConstraint))[:l:l]
 | 
			
		||||
 | 
			
		||||
	cst := make([]InfoConstraint, 0, l)
 | 
			
		||||
	for _, c := range slice {
 | 
			
		||||
		var usable bool
 | 
			
		||||
		if c.usable > 0 {
 | 
			
		||||
			usable = true
 | 
			
		||||
		}
 | 
			
		||||
		cst = append(cst, InfoConstraint{
 | 
			
		||||
			Column: int(c.iColumn),
 | 
			
		||||
			Op:     Op(c.op),
 | 
			
		||||
			Usable: usable,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return cst
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
 | 
			
		||||
	l := info.nOrderBy
 | 
			
		||||
	slice := (*[1 << 30]C.struct_sqlite3_index_orderby)(unsafe.Pointer(info.aOrderBy))[:l:l]
 | 
			
		||||
 | 
			
		||||
	ob := make([]InfoOrderBy, 0, l)
 | 
			
		||||
	for _, c := range slice {
 | 
			
		||||
		var desc bool
 | 
			
		||||
		if c.desc > 0 {
 | 
			
		||||
			desc = true
 | 
			
		||||
		}
 | 
			
		||||
		ob = append(ob, InfoOrderBy{
 | 
			
		||||
			Column: int(c.iColumn),
 | 
			
		||||
			Desc:   desc,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return ob
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IndexResult is a Go struct representation of what eventually ends up in the
 | 
			
		||||
// output fields for `sqlite3_index_info`
 | 
			
		||||
// See: https://www.sqlite.org/c3ref/index_info.html
 | 
			
		||||
type IndexResult struct {
 | 
			
		||||
	Used           []bool // aConstraintUsage
 | 
			
		||||
	IdxNum         int
 | 
			
		||||
	IdxStr         string
 | 
			
		||||
	AlreadyOrdered bool // orderByConsumed
 | 
			
		||||
	EstimatedCost  float64
 | 
			
		||||
	EstimatedRows  float64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mPrintf is a utility wrapper around sqlite3_mprintf
 | 
			
		||||
func mPrintf(format, arg string) *C.char {
 | 
			
		||||
	cf := C.CString(format)
 | 
			
		||||
	defer C.free(unsafe.Pointer(cf))
 | 
			
		||||
	ca := C.CString(arg)
 | 
			
		||||
	defer C.free(unsafe.Pointer(ca))
 | 
			
		||||
	return C._sqlite3_mprintf(cf, ca)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goMInit
 | 
			
		||||
func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
 | 
			
		||||
	m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
 | 
			
		||||
	if m.c.db != (*C.sqlite3)(db) {
 | 
			
		||||
		*pzErr = mPrintf("%s", "Inconsistent db handles")
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	args := make([]string, argc)
 | 
			
		||||
	var A []*C.char
 | 
			
		||||
	slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
 | 
			
		||||
	a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
 | 
			
		||||
	for i, s := range a.([]*C.char) {
 | 
			
		||||
		args[i] = C.GoString(s)
 | 
			
		||||
	}
 | 
			
		||||
	var vTab VTab
 | 
			
		||||
	var err error
 | 
			
		||||
	if isCreate == 1 {
 | 
			
		||||
		vTab, err = m.module.Create(m.c, args)
 | 
			
		||||
	} else {
 | 
			
		||||
		vTab, err = m.module.Connect(m.c, args)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		*pzErr = mPrintf("%s", err.Error())
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	vt := sqliteVTab{m, vTab}
 | 
			
		||||
	*pzErr = nil
 | 
			
		||||
	return C.uintptr_t(newHandle(m.c, &vt))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVRelease
 | 
			
		||||
func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
 | 
			
		||||
	vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
 | 
			
		||||
	var err error
 | 
			
		||||
	if isDestroy == 1 {
 | 
			
		||||
		err = vt.vTab.Destroy()
 | 
			
		||||
	} else {
 | 
			
		||||
		err = vt.vTab.Disconnect()
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVOpen
 | 
			
		||||
func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
 | 
			
		||||
	vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
 | 
			
		||||
	vTabCursor, err := vt.vTab.Open()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		*pzErr = mPrintf("%s", err.Error())
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	vtc := sqliteVTabCursor{vt, vTabCursor}
 | 
			
		||||
	*pzErr = nil
 | 
			
		||||
	return C.uintptr_t(newHandle(vt.module.c, &vtc))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVBestIndex
 | 
			
		||||
func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
 | 
			
		||||
	vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
 | 
			
		||||
	info := (*C.sqlite3_index_info)(icp)
 | 
			
		||||
	csts := constraints(info)
 | 
			
		||||
	res, err := vt.vTab.BestIndex(csts, orderBys(info))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	if len(res.Used) != len(csts) {
 | 
			
		||||
		return mPrintf("Result.Used != expected value", "")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get a pointer to constraint_usage struct so we can update in place.
 | 
			
		||||
	l := info.nConstraint
 | 
			
		||||
	s := (*[1 << 30]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(info.aConstraintUsage))[:l:l]
 | 
			
		||||
	index := 1
 | 
			
		||||
	for i := C.int(0); i < info.nConstraint; i++ {
 | 
			
		||||
		if res.Used[i] {
 | 
			
		||||
			s[i].argvIndex = C.int(index)
 | 
			
		||||
			s[i].omit = C.uchar(1)
 | 
			
		||||
			index++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info.idxNum = C.int(res.IdxNum)
 | 
			
		||||
	idxStr := C.CString(res.IdxStr)
 | 
			
		||||
	defer C.free(unsafe.Pointer(idxStr))
 | 
			
		||||
	info.idxStr = idxStr
 | 
			
		||||
	info.needToFreeIdxStr = C.int(0)
 | 
			
		||||
	if res.AlreadyOrdered {
 | 
			
		||||
		info.orderByConsumed = C.int(1)
 | 
			
		||||
	}
 | 
			
		||||
	info.estimatedCost = C.double(res.EstimatedCost)
 | 
			
		||||
	info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVClose
 | 
			
		||||
func goVClose(pCursor unsafe.Pointer) *C.char {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	err := vtc.vTabCursor.Close()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goMDestroy
 | 
			
		||||
func goMDestroy(pClientData unsafe.Pointer) {
 | 
			
		||||
	m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
 | 
			
		||||
	m.module.DestroyModule()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVFilter
 | 
			
		||||
func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
 | 
			
		||||
	vals := make([]interface{}, 0, argc)
 | 
			
		||||
	for _, v := range args {
 | 
			
		||||
		conv, err := callbackArgGeneric(v)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return mPrintf("%s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		vals = append(vals, conv.Interface())
 | 
			
		||||
	}
 | 
			
		||||
	err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVNext
 | 
			
		||||
func goVNext(pCursor unsafe.Pointer) *C.char {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	err := vtc.vTabCursor.Next()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVEof
 | 
			
		||||
func goVEof(pCursor unsafe.Pointer) C.int {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	err := vtc.vTabCursor.EOF()
 | 
			
		||||
	if err {
 | 
			
		||||
		return 1
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVColumn
 | 
			
		||||
func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	c := (*SQLiteContext)(cp)
 | 
			
		||||
	err := vtc.vTabCursor.Column(c, int(col))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVRowid
 | 
			
		||||
func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
 | 
			
		||||
	vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
 | 
			
		||||
	rowid, err := vtc.vTabCursor.Rowid()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	*pRowid = C.sqlite3_int64(rowid)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export goVUpdate
 | 
			
		||||
func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
 | 
			
		||||
	vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
 | 
			
		||||
 | 
			
		||||
	var tname string
 | 
			
		||||
	if n, ok := vt.vTab.(interface {
 | 
			
		||||
		TableName() string
 | 
			
		||||
	}); ok {
 | 
			
		||||
		tname = n.TableName() + " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
 | 
			
		||||
	if v, ok := vt.vTab.(VTabUpdater); ok {
 | 
			
		||||
		// convert argv
 | 
			
		||||
		args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
 | 
			
		||||
		vals := make([]interface{}, 0, argc)
 | 
			
		||||
		for _, v := range args {
 | 
			
		||||
			conv, err := callbackArgGeneric(v)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return mPrintf("%s", err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// work around for SQLITE_NULL
 | 
			
		||||
			x := conv.Interface()
 | 
			
		||||
			if z, ok := x.([]byte); ok && z == nil {
 | 
			
		||||
				x = nil
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			vals = append(vals, x)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch {
 | 
			
		||||
		case argc == 1:
 | 
			
		||||
			err = v.Delete(vals[0])
 | 
			
		||||
 | 
			
		||||
		case argc > 1 && vals[0] == nil:
 | 
			
		||||
			var id int64
 | 
			
		||||
			id, err = v.Insert(vals[1], vals[2:])
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				*pRowid = C.sqlite3_int64(id)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case argc > 1:
 | 
			
		||||
			err = v.Update(vals[1], vals[2:])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mPrintf("%s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Module is a "virtual table module", it defines the implementation of a
 | 
			
		||||
// virtual tables. See: http://sqlite.org/c3ref/module.html
 | 
			
		||||
type Module interface {
 | 
			
		||||
	// http://sqlite.org/vtab.html#xcreate
 | 
			
		||||
	Create(c *SQLiteConn, args []string) (VTab, error)
 | 
			
		||||
	// http://sqlite.org/vtab.html#xconnect
 | 
			
		||||
	Connect(c *SQLiteConn, args []string) (VTab, error)
 | 
			
		||||
	// http://sqlite.org/c3ref/create_module.html
 | 
			
		||||
	DestroyModule()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VTab describes a particular instance of the virtual table.
 | 
			
		||||
// See: http://sqlite.org/c3ref/vtab.html
 | 
			
		||||
type VTab interface {
 | 
			
		||||
	// http://sqlite.org/vtab.html#xbestindex
 | 
			
		||||
	BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
 | 
			
		||||
	// http://sqlite.org/vtab.html#xdisconnect
 | 
			
		||||
	Disconnect() error
 | 
			
		||||
	// http://sqlite.org/vtab.html#sqlite3_module.xDestroy
 | 
			
		||||
	Destroy() error
 | 
			
		||||
	// http://sqlite.org/vtab.html#xopen
 | 
			
		||||
	Open() (VTabCursor, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VTabUpdater is a type that allows a VTab to be inserted, updated, or
 | 
			
		||||
// deleted.
 | 
			
		||||
// See: https://sqlite.org/vtab.html#xupdate
 | 
			
		||||
type VTabUpdater interface {
 | 
			
		||||
	Delete(interface{}) error
 | 
			
		||||
	Insert(interface{}, []interface{}) (int64, error)
 | 
			
		||||
	Update(interface{}, []interface{}) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VTabCursor describes cursors that point into the virtual table and are used
 | 
			
		||||
// to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
 | 
			
		||||
type VTabCursor interface {
 | 
			
		||||
	// http://sqlite.org/vtab.html#xclose
 | 
			
		||||
	Close() error
 | 
			
		||||
	// http://sqlite.org/vtab.html#xfilter
 | 
			
		||||
	Filter(idxNum int, idxStr string, vals []interface{}) error
 | 
			
		||||
	// http://sqlite.org/vtab.html#xnext
 | 
			
		||||
	Next() error
 | 
			
		||||
	// http://sqlite.org/vtab.html#xeof
 | 
			
		||||
	EOF() bool
 | 
			
		||||
	// http://sqlite.org/vtab.html#xcolumn
 | 
			
		||||
	Column(c *SQLiteContext, col int) error
 | 
			
		||||
	// http://sqlite.org/vtab.html#xrowid
 | 
			
		||||
	Rowid() (int64, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeclareVTab declares the Schema of a virtual table.
 | 
			
		||||
// See: http://sqlite.org/c3ref/declare_vtab.html
 | 
			
		||||
func (c *SQLiteConn) DeclareVTab(sql string) error {
 | 
			
		||||
	zSQL := C.CString(sql)
 | 
			
		||||
	defer C.free(unsafe.Pointer(zSQL))
 | 
			
		||||
	rv := C.sqlite3_declare_vtab(c.db, zSQL)
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateModule registers a virtual table implementation.
 | 
			
		||||
// See: http://sqlite.org/c3ref/create_module.html
 | 
			
		||||
func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
 | 
			
		||||
	mname := C.CString(moduleName)
 | 
			
		||||
	defer C.free(unsafe.Pointer(mname))
 | 
			
		||||
	udm := sqliteModule{c, moduleName, module}
 | 
			
		||||
	rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
 | 
			
		||||
	if rv != C.SQLITE_OK {
 | 
			
		||||
		return c.lastError()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -13,7 +13,7 @@
 | 
			
		||||
** This header file defines the SQLite interface for use by
 | 
			
		||||
** shared libraries that want to be imported as extensions into
 | 
			
		||||
** an SQLite instance.  Shared libraries that intend to be loaded
 | 
			
		||||
** as extensions by SQLite should #include this file instead of
 | 
			
		||||
** as extensions by SQLite should #include this file instead of 
 | 
			
		||||
** sqlite3.h.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef SQLITE3EXT_H
 | 
			
		||||
@@ -544,14 +544,14 @@ typedef int (*sqlite3_loadext_entry)(
 | 
			
		||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
 | 
			
		||||
 | 
			
		||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
 | 
			
		||||
  /* This case when the file really is being compiled as a loadable
 | 
			
		||||
  /* This case when the file really is being compiled as a loadable 
 | 
			
		||||
  ** extension */
 | 
			
		||||
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
 | 
			
		||||
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
 | 
			
		||||
# define SQLITE_EXTENSION_INIT3     \
 | 
			
		||||
    extern const sqlite3_api_routines *sqlite3_api;
 | 
			
		||||
#else
 | 
			
		||||
  /* This case when the file is being statically linked into the
 | 
			
		||||
  /* This case when the file is being statically linked into the 
 | 
			
		||||
  ** application */
 | 
			
		||||
# define SQLITE_EXTENSION_INIT1     /*no-op*/
 | 
			
		||||
# define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
 | 
			
		||||
@@ -562,4 +562,4 @@ typedef int (*sqlite3_loadext_entry)(
 | 
			
		||||
#else // USE_LIBSQLITE3
 | 
			
		||||
 // If users really want to link against the system sqlite3 we
 | 
			
		||||
// need to make this file a noop.
 | 
			
		||||
 #endif
 | 
			
		||||
 #endif
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/github.com/mattn/go-sqlite3/tracecallback_noimpl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/mattn/go-sqlite3/tracecallback_noimpl.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,9 +0,0 @@
 | 
			
		||||
// +build !trace
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
import "errors"
 | 
			
		||||
 | 
			
		||||
func (c *SQLiteConn) RegisterAggregator(name string, impl interface{}, pure bool) error {
 | 
			
		||||
	return errors.New("This feature is not implemented")
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user