podman
2281 строка · 65.4 Кб
1// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
2// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
3//
4// Use of this source code is governed by an MIT-style
5// license that can be found in the LICENSE file.
6
7//go:build cgo
8// +build cgo
9
10package sqlite311
12/*
13#cgo CFLAGS: -std=gnu99
14#cgo CFLAGS: -DSQLITE_ENABLE_RTREE
15#cgo CFLAGS: -DSQLITE_THREADSAFE=1
16#cgo CFLAGS: -DHAVE_USLEEP=1
17#cgo CFLAGS: -DSQLITE_ENABLE_FTS3
18#cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS
19#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
20#cgo CFLAGS: -DSQLITE_OMIT_DEPRECATED
21#cgo CFLAGS: -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
22#cgo CFLAGS: -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT
23#cgo CFLAGS: -Wno-deprecated-declarations
24#cgo openbsd CFLAGS: -I/usr/local/include
25#cgo openbsd LDFLAGS: -L/usr/local/lib
26#ifndef USE_LIBSQLITE3
27#include "sqlite3-binding.h"
28#else
29#include <sqlite3.h>
30#endif
31#include <stdlib.h>
32#include <string.h>
33
34#ifdef __CYGWIN__
35# include <errno.h>
36#endif
37
38#ifndef SQLITE_OPEN_READWRITE
39# define SQLITE_OPEN_READWRITE 0
40#endif
41
42#ifndef SQLITE_OPEN_FULLMUTEX
43# define SQLITE_OPEN_FULLMUTEX 0
44#endif
45
46#ifndef SQLITE_DETERMINISTIC
47# define SQLITE_DETERMINISTIC 0
48#endif
49
50#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64)
51# undef USE_PREAD
52# undef USE_PWRITE
53# define USE_PREAD64 1
54# define USE_PWRITE64 1
55#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE)
56# undef USE_PREAD
57# undef USE_PWRITE
58# define USE_PREAD64 1
59# define USE_PWRITE64 1
60#endif
61
62static int
63_sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) {
64#ifdef SQLITE_OPEN_URI
65return sqlite3_open_v2(filename, ppDb, flags | SQLITE_OPEN_URI, zVfs);
66#else
67return sqlite3_open_v2(filename, ppDb, flags, zVfs);
68#endif
69}
70
71static int
72_sqlite3_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
73return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
74}
75
76static int
77_sqlite3_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
78return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
79}
80
81#include <stdio.h>
82#include <stdint.h>
83
84static int
85_sqlite3_exec(sqlite3* db, const char* pcmd, long long* rowid, long long* changes)
86{
87int rv = sqlite3_exec(db, pcmd, 0, 0, 0);
88*rowid = (long long) sqlite3_last_insert_rowid(db);
89*changes = (long long) sqlite3_changes(db);
90return rv;
91}
92
93#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
94extern int _sqlite3_step_blocking(sqlite3_stmt *stmt);
95extern int _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes);
96extern int _sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail);
97
98static int
99_sqlite3_step_internal(sqlite3_stmt *stmt)
100{
101return _sqlite3_step_blocking(stmt);
102}
103
104static int
105_sqlite3_step_row_internal(sqlite3_stmt* stmt, long long* rowid, long long* changes)
106{
107return _sqlite3_step_row_blocking(stmt, rowid, changes);
108}
109
110static int
111_sqlite3_prepare_v2_internal(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
112{
113return _sqlite3_prepare_v2_blocking(db, zSql, nBytes, ppStmt, pzTail);
114}
115
116#else
117static int
118_sqlite3_step_internal(sqlite3_stmt *stmt)
119{
120return sqlite3_step(stmt);
121}
122
123static int
124_sqlite3_step_row_internal(sqlite3_stmt* stmt, long long* rowid, long long* changes)
125{
126int rv = sqlite3_step(stmt);
127sqlite3* db = sqlite3_db_handle(stmt);
128*rowid = (long long) sqlite3_last_insert_rowid(db);
129*changes = (long long) sqlite3_changes(db);
130return rv;
131}
132
133static int
134_sqlite3_prepare_v2_internal(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
135{
136return sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail);
137}
138#endif
139
140void _sqlite3_result_text(sqlite3_context* ctx, const char* s) {
141sqlite3_result_text(ctx, s, -1, &free);
142}
143
144void _sqlite3_result_blob(sqlite3_context* ctx, const void* b, int l) {
145sqlite3_result_blob(ctx, b, l, SQLITE_TRANSIENT);
146}
147
148
149int _sqlite3_create_function(
150sqlite3 *db,
151const char *zFunctionName,
152int nArg,
153int eTextRep,
154uintptr_t pApp,
155void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
156void (*xStep)(sqlite3_context*,int,sqlite3_value**),
157void (*xFinal)(sqlite3_context*)
158) {
159return sqlite3_create_function(db, zFunctionName, nArg, eTextRep, (void*) pApp, xFunc, xStep, xFinal);
160}
161
162void callbackTrampoline(sqlite3_context*, int, sqlite3_value**);
163void stepTrampoline(sqlite3_context*, int, sqlite3_value**);
164void doneTrampoline(sqlite3_context*);
165
166int compareTrampoline(void*, int, char*, int, char*);
167int commitHookTrampoline(void*);
168void rollbackHookTrampoline(void*);
169void updateHookTrampoline(void*, int, char*, char*, sqlite3_int64);
170
171int authorizerTrampoline(void*, int, char*, char*, char*, char*);
172
173#ifdef SQLITE_LIMIT_WORKER_THREADS
174# define _SQLITE_HAS_LIMIT
175# define SQLITE_LIMIT_LENGTH 0
176# define SQLITE_LIMIT_SQL_LENGTH 1
177# define SQLITE_LIMIT_COLUMN 2
178# define SQLITE_LIMIT_EXPR_DEPTH 3
179# define SQLITE_LIMIT_COMPOUND_SELECT 4
180# define SQLITE_LIMIT_VDBE_OP 5
181# define SQLITE_LIMIT_FUNCTION_ARG 6
182# define SQLITE_LIMIT_ATTACHED 7
183# define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
184# define SQLITE_LIMIT_VARIABLE_NUMBER 9
185# define SQLITE_LIMIT_TRIGGER_DEPTH 10
186# define SQLITE_LIMIT_WORKER_THREADS 11
187# else
188# define SQLITE_LIMIT_WORKER_THREADS 11
189#endif
190
191static int _sqlite3_limit(sqlite3* db, int limitId, int newLimit) {
192#ifndef _SQLITE_HAS_LIMIT
193return -1;
194#else
195return sqlite3_limit(db, limitId, newLimit);
196#endif
197}
198
199#if SQLITE_VERSION_NUMBER < 3012000
200static int sqlite3_system_errno(sqlite3 *db) {
201return 0;
202}
203#endif
204*/
205import "C"206import (207"context"208"database/sql"209"database/sql/driver"210"errors"211"fmt"212"io"213"net/url"214"reflect"215"runtime"216"strconv"217"strings"218"sync"219"syscall"220"time"221"unsafe"222)
223
224// SQLiteTimestampFormats is timestamp formats understood by both this module
225// and SQLite. The first format in the slice will be used when saving time
226// values into the database. When parsing a string from a timestamp or datetime
227// column, the formats are tried in order.
228var SQLiteTimestampFormats = []string{229// By default, store timestamps with whatever timezone they come with.230// When parsed, they will be returned with the same timezone.231"2006-01-02 15:04:05.999999999-07:00",232"2006-01-02T15:04:05.999999999-07:00",233"2006-01-02 15:04:05.999999999",234"2006-01-02T15:04:05.999999999",235"2006-01-02 15:04:05",236"2006-01-02T15:04:05",237"2006-01-02 15:04",238"2006-01-02T15:04",239"2006-01-02",240}
241
242const (243columnDate string = "date"244columnDatetime string = "datetime"245columnTimestamp string = "timestamp"246)
247
248// This variable can be replaced with -ldflags like below:
249// go build -ldflags="-X 'github.com/mattn/go-sqlite3.driverName=my-sqlite3'"
250var driverName = "sqlite3"251
252func init() {253if driverName != "" {254sql.Register(driverName, &SQLiteDriver{})255}256}
257
258// Version returns SQLite library version information.
259func Version() (libVersion string, libVersionNumber int, sourceID string) {260libVersion = C.GoString(C.sqlite3_libversion())261libVersionNumber = int(C.sqlite3_libversion_number())262sourceID = C.GoString(C.sqlite3_sourceid())263return libVersion, libVersionNumber, sourceID264}
265
266const (267// used by authorizer and pre_update_hook268SQLITE_DELETE = C.SQLITE_DELETE269SQLITE_INSERT = C.SQLITE_INSERT270SQLITE_UPDATE = C.SQLITE_UPDATE271
272// used by authorzier - as return value273SQLITE_OK = C.SQLITE_OK274SQLITE_IGNORE = C.SQLITE_IGNORE275SQLITE_DENY = C.SQLITE_DENY276
277// different actions query tries to do - passed as argument to authorizer278SQLITE_CREATE_INDEX = C.SQLITE_CREATE_INDEX279SQLITE_CREATE_TABLE = C.SQLITE_CREATE_TABLE280SQLITE_CREATE_TEMP_INDEX = C.SQLITE_CREATE_TEMP_INDEX281SQLITE_CREATE_TEMP_TABLE = C.SQLITE_CREATE_TEMP_TABLE282SQLITE_CREATE_TEMP_TRIGGER = C.SQLITE_CREATE_TEMP_TRIGGER283SQLITE_CREATE_TEMP_VIEW = C.SQLITE_CREATE_TEMP_VIEW284SQLITE_CREATE_TRIGGER = C.SQLITE_CREATE_TRIGGER285SQLITE_CREATE_VIEW = C.SQLITE_CREATE_VIEW286SQLITE_CREATE_VTABLE = C.SQLITE_CREATE_VTABLE287SQLITE_DROP_INDEX = C.SQLITE_DROP_INDEX288SQLITE_DROP_TABLE = C.SQLITE_DROP_TABLE289SQLITE_DROP_TEMP_INDEX = C.SQLITE_DROP_TEMP_INDEX290SQLITE_DROP_TEMP_TABLE = C.SQLITE_DROP_TEMP_TABLE291SQLITE_DROP_TEMP_TRIGGER = C.SQLITE_DROP_TEMP_TRIGGER292SQLITE_DROP_TEMP_VIEW = C.SQLITE_DROP_TEMP_VIEW293SQLITE_DROP_TRIGGER = C.SQLITE_DROP_TRIGGER294SQLITE_DROP_VIEW = C.SQLITE_DROP_VIEW295SQLITE_DROP_VTABLE = C.SQLITE_DROP_VTABLE296SQLITE_PRAGMA = C.SQLITE_PRAGMA297SQLITE_READ = C.SQLITE_READ298SQLITE_SELECT = C.SQLITE_SELECT299SQLITE_TRANSACTION = C.SQLITE_TRANSACTION300SQLITE_ATTACH = C.SQLITE_ATTACH301SQLITE_DETACH = C.SQLITE_DETACH302SQLITE_ALTER_TABLE = C.SQLITE_ALTER_TABLE303SQLITE_REINDEX = C.SQLITE_REINDEX304SQLITE_ANALYZE = C.SQLITE_ANALYZE305SQLITE_FUNCTION = C.SQLITE_FUNCTION306SQLITE_SAVEPOINT = C.SQLITE_SAVEPOINT307SQLITE_COPY = C.SQLITE_COPY308/*SQLITE_RECURSIVE = C.SQLITE_RECURSIVE*/309)
310
311// Standard File Control Opcodes
312// See: https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
313const (314SQLITE_FCNTL_LOCKSTATE = int(1)315SQLITE_FCNTL_GET_LOCKPROXYFILE = int(2)316SQLITE_FCNTL_SET_LOCKPROXYFILE = int(3)317SQLITE_FCNTL_LAST_ERRNO = int(4)318SQLITE_FCNTL_SIZE_HINT = int(5)319SQLITE_FCNTL_CHUNK_SIZE = int(6)320SQLITE_FCNTL_FILE_POINTER = int(7)321SQLITE_FCNTL_SYNC_OMITTED = int(8)322SQLITE_FCNTL_WIN32_AV_RETRY = int(9)323SQLITE_FCNTL_PERSIST_WAL = int(10)324SQLITE_FCNTL_OVERWRITE = int(11)325SQLITE_FCNTL_VFSNAME = int(12)326SQLITE_FCNTL_POWERSAFE_OVERWRITE = int(13)327SQLITE_FCNTL_PRAGMA = int(14)328SQLITE_FCNTL_BUSYHANDLER = int(15)329SQLITE_FCNTL_TEMPFILENAME = int(16)330SQLITE_FCNTL_MMAP_SIZE = int(18)331SQLITE_FCNTL_TRACE = int(19)332SQLITE_FCNTL_HAS_MOVED = int(20)333SQLITE_FCNTL_SYNC = int(21)334SQLITE_FCNTL_COMMIT_PHASETWO = int(22)335SQLITE_FCNTL_WIN32_SET_HANDLE = int(23)336SQLITE_FCNTL_WAL_BLOCK = int(24)337SQLITE_FCNTL_ZIPVFS = int(25)338SQLITE_FCNTL_RBU = int(26)339SQLITE_FCNTL_VFS_POINTER = int(27)340SQLITE_FCNTL_JOURNAL_POINTER = int(28)341SQLITE_FCNTL_WIN32_GET_HANDLE = int(29)342SQLITE_FCNTL_PDB = int(30)343SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = int(31)344SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = int(32)345SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = int(33)346SQLITE_FCNTL_LOCK_TIMEOUT = int(34)347SQLITE_FCNTL_DATA_VERSION = int(35)348SQLITE_FCNTL_SIZE_LIMIT = int(36)349SQLITE_FCNTL_CKPT_DONE = int(37)350SQLITE_FCNTL_RESERVE_BYTES = int(38)351SQLITE_FCNTL_CKPT_START = int(39)352SQLITE_FCNTL_EXTERNAL_READER = int(40)353SQLITE_FCNTL_CKSM_FILE = int(41)354)
355
356// SQLiteDriver implements driver.Driver.
357type SQLiteDriver struct {358Extensions []string359ConnectHook func(*SQLiteConn) error360}
361
362// SQLiteConn implements driver.Conn.
363type SQLiteConn struct {364mu sync.Mutex365db *C.sqlite3366loc *time.Location367txlock string368funcs []*functionInfo369aggregators []*aggInfo370}
371
372// SQLiteTx implements driver.Tx.
373type SQLiteTx struct {374c *SQLiteConn375}
376
377// SQLiteStmt implements driver.Stmt.
378type SQLiteStmt struct {379mu sync.Mutex380c *SQLiteConn381s *C.sqlite3_stmt382t string383closed bool384cls bool385}
386
387// SQLiteResult implements sql.Result.
388type SQLiteResult struct {389id int64390changes int64391}
392
393// SQLiteRows implements driver.Rows.
394type SQLiteRows struct {395s *SQLiteStmt396nc int397cols []string398decltype []string399cls bool400closed bool401ctx context.Context // no better alternative to pass context into Next() method402}
403
404type functionInfo struct {405f reflect.Value406argConverters []callbackArgConverter407variadicConverter callbackArgConverter
408retConverter callbackRetConverter
409}
410
411func (fi *functionInfo) Call(ctx *C.sqlite3_context, argv []*C.sqlite3_value) {412args, err := callbackConvertArgs(argv, fi.argConverters, fi.variadicConverter)413if err != nil {414callbackError(ctx, err)415return416}417
418ret := fi.f.Call(args)419
420if len(ret) == 2 && ret[1].Interface() != nil {421callbackError(ctx, ret[1].Interface().(error))422return423}424
425err = fi.retConverter(ctx, ret[0])426if err != nil {427callbackError(ctx, err)428return429}430}
431
432type aggInfo struct {433constructor reflect.Value434
435// Active aggregator objects for aggregations in flight. The436// aggregators are indexed by a counter stored in the aggregation437// user data space provided by sqlite.438active map[int64]reflect.Value439next int64440
441stepArgConverters []callbackArgConverter442stepVariadicConverter callbackArgConverter
443
444doneRetConverter callbackRetConverter
445}
446
447func (ai *aggInfo) agg(ctx *C.sqlite3_context) (int64, reflect.Value, error) {448aggIdx := (*int64)(C.sqlite3_aggregate_context(ctx, C.int(8)))449if *aggIdx == 0 {450*aggIdx = ai.next451ret := ai.constructor.Call(nil)452if len(ret) == 2 && ret[1].Interface() != nil {453return 0, reflect.Value{}, ret[1].Interface().(error)454}455if ret[0].IsNil() {456return 0, reflect.Value{}, errors.New("aggregator constructor returned nil state")457}458ai.next++459ai.active[*aggIdx] = ret[0]460}461return *aggIdx, ai.active[*aggIdx], nil462}
463
464func (ai *aggInfo) Step(ctx *C.sqlite3_context, argv []*C.sqlite3_value) {465_, agg, err := ai.agg(ctx)466if err != nil {467callbackError(ctx, err)468return469}470
471args, err := callbackConvertArgs(argv, ai.stepArgConverters, ai.stepVariadicConverter)472if err != nil {473callbackError(ctx, err)474return475}476
477ret := agg.MethodByName("Step").Call(args)478if len(ret) == 1 && ret[0].Interface() != nil {479callbackError(ctx, ret[0].Interface().(error))480return481}482}
483
484func (ai *aggInfo) Done(ctx *C.sqlite3_context) {485idx, agg, err := ai.agg(ctx)486if err != nil {487callbackError(ctx, err)488return489}490defer func() { delete(ai.active, idx) }()491
492ret := agg.MethodByName("Done").Call(nil)493if len(ret) == 2 && ret[1].Interface() != nil {494callbackError(ctx, ret[1].Interface().(error))495return496}497
498err = ai.doneRetConverter(ctx, ret[0])499if err != nil {500callbackError(ctx, err)501return502}503}
504
505// Commit transaction.
506func (tx *SQLiteTx) Commit() error {507_, err := tx.c.exec(context.Background(), "COMMIT", nil)508if err != nil {509// sqlite3 may leave the transaction open in this scenario.510// However, database/sql considers the transaction complete once we511// return from Commit() - we must clean up to honour its semantics.512// We don't know if the ROLLBACK is strictly necessary, but according513// to sqlite's docs, there is no harm in calling ROLLBACK unnecessarily.514tx.c.exec(context.Background(), "ROLLBACK", nil)515}516return err517}
518
519// Rollback transaction.
520func (tx *SQLiteTx) Rollback() error {521_, err := tx.c.exec(context.Background(), "ROLLBACK", nil)522return err523}
524
525// RegisterCollation makes a Go function available as a collation.
526//
527// cmp receives two UTF-8 strings, a and b. The result should be 0 if
528// a==b, -1 if a < b, and +1 if a > b.
529//
530// cmp must always return the same result given the same
531// inputs. Additionally, it must have the following properties for all
532// strings A, B and C: if A==B then B==A; if A==B and B==C then A==C;
533// if A<B then B>A; if A<B and B<C then A<C.
534//
535// If cmp does not obey these constraints, sqlite3's behavior is
536// undefined when the collation is used.
537func (c *SQLiteConn) RegisterCollation(name string, cmp func(string, string) int) error {538handle := newHandle(c, cmp)539cname := C.CString(name)540defer C.free(unsafe.Pointer(cname))541rv := C.sqlite3_create_collation(c.db, cname, C.SQLITE_UTF8, handle, (*[0]byte)(unsafe.Pointer(C.compareTrampoline)))542if rv != C.SQLITE_OK {543return c.lastError()544}545return nil546}
547
548// RegisterCommitHook sets the commit hook for a connection.
549//
550// If the callback returns non-zero the transaction will become a rollback.
551//
552// If there is an existing commit hook for this connection, it will be
553// removed. If callback is nil the existing hook (if any) will be removed
554// without creating a new one.
555func (c *SQLiteConn) RegisterCommitHook(callback func() int) {556if callback == nil {557C.sqlite3_commit_hook(c.db, nil, nil)558} else {559C.sqlite3_commit_hook(c.db, (*[0]byte)(C.commitHookTrampoline), newHandle(c, callback))560}561}
562
563// RegisterRollbackHook sets the rollback hook for a connection.
564//
565// If there is an existing rollback hook for this connection, it will be
566// removed. If callback is nil the existing hook (if any) will be removed
567// without creating a new one.
568func (c *SQLiteConn) RegisterRollbackHook(callback func()) {569if callback == nil {570C.sqlite3_rollback_hook(c.db, nil, nil)571} else {572C.sqlite3_rollback_hook(c.db, (*[0]byte)(C.rollbackHookTrampoline), newHandle(c, callback))573}574}
575
576// RegisterUpdateHook sets the update hook for a connection.
577//
578// The parameters to the callback are the operation (one of the constants
579// SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE), the database name, the
580// table name, and the rowid.
581//
582// If there is an existing update hook for this connection, it will be
583// removed. If callback is nil the existing hook (if any) will be removed
584// without creating a new one.
585func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64)) {586if callback == nil {587C.sqlite3_update_hook(c.db, nil, nil)588} else {589C.sqlite3_update_hook(c.db, (*[0]byte)(C.updateHookTrampoline), newHandle(c, callback))590}591}
592
593// RegisterAuthorizer sets the authorizer for connection.
594//
595// The parameters to the callback are the operation (one of the constants
596// SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE), and 1 to 3 arguments,
597// depending on operation. More details see:
598// https://www.sqlite.org/c3ref/c_alter_table.html
599func (c *SQLiteConn) RegisterAuthorizer(callback func(int, string, string, string) int) {600if callback == nil {601C.sqlite3_set_authorizer(c.db, nil, nil)602} else {603C.sqlite3_set_authorizer(c.db, (*[0]byte)(C.authorizerTrampoline), newHandle(c, callback))604}605}
606
607// RegisterFunc makes a Go function available as a SQLite function.
608//
609// The Go function can have arguments of the following types: any
610// numeric type except complex, bool, []byte, string and any.
611// any arguments are given the direct translation of the SQLite data type:
612// int64 for INTEGER, float64 for FLOAT, []byte for BLOB, string for TEXT.
613//
614// The function can additionally be variadic, as long as the type of
615// the variadic argument is one of the above.
616//
617// If pure is true. SQLite will assume that the function's return
618// value depends only on its inputs, and make more aggressive
619// optimizations in its queries.
620//
621// See _example/go_custom_funcs for a detailed example.
622func (c *SQLiteConn) RegisterFunc(name string, impl any, pure bool) error {623var fi functionInfo624fi.f = reflect.ValueOf(impl)625t := fi.f.Type()626if t.Kind() != reflect.Func {627return errors.New("Non-function passed to RegisterFunc")628}629if t.NumOut() != 1 && t.NumOut() != 2 {630return errors.New("SQLite functions must return 1 or 2 values")631}632if t.NumOut() == 2 && !t.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {633return errors.New("Second return value of SQLite function must be error")634}635
636numArgs := t.NumIn()637if t.IsVariadic() {638numArgs--639}640
641for i := 0; i < numArgs; i++ {642conv, err := callbackArg(t.In(i))643if err != nil {644return err645}646fi.argConverters = append(fi.argConverters, conv)647}648
649if t.IsVariadic() {650conv, err := callbackArg(t.In(numArgs).Elem())651if err != nil {652return err653}654fi.variadicConverter = conv655// Pass -1 to sqlite so that it allows any number of656// arguments. The call helper verifies that the minimum number657// of arguments is present for variadic functions.658numArgs = -1659}660
661conv, err := callbackRet(t.Out(0))662if err != nil {663return err664}665fi.retConverter = conv666
667// fi must outlast the database connection, or we'll have dangling pointers.668c.funcs = append(c.funcs, &fi)669
670cname := C.CString(name)671defer C.free(unsafe.Pointer(cname))672opts := C.SQLITE_UTF8673if pure {674opts |= C.SQLITE_DETERMINISTIC675}676rv := sqlite3CreateFunction(c.db, cname, C.int(numArgs), C.int(opts), newHandle(c, &fi), C.callbackTrampoline, nil, nil)677if rv != C.SQLITE_OK {678return c.lastError()679}680return nil681}
682
683func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp unsafe.Pointer, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {684return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(uintptr(pApp)), (*[0]byte)(xFunc), (*[0]byte)(xStep), (*[0]byte)(xFinal))685}
686
687// RegisterAggregator makes a Go type available as a SQLite aggregation function.
688//
689// Because aggregation is incremental, it's implemented in Go with a
690// type that has 2 methods: func Step(values) accumulates one row of
691// data into the accumulator, and func Done() ret finalizes and
692// returns the aggregate value. "values" and "ret" may be any type
693// supported by RegisterFunc.
694//
695// RegisterAggregator takes as implementation a constructor function
696// that constructs an instance of the aggregator type each time an
697// aggregation begins. The constructor must return a pointer to a
698// type, or an interface that implements Step() and Done().
699//
700// The constructor function and the Step/Done methods may optionally
701// return an error in addition to their other return values.
702//
703// See _example/go_custom_funcs for a detailed example.
704func (c *SQLiteConn) RegisterAggregator(name string, impl any, pure bool) error {705var ai aggInfo706ai.constructor = reflect.ValueOf(impl)707t := ai.constructor.Type()708if t.Kind() != reflect.Func {709return errors.New("non-function passed to RegisterAggregator")710}711if t.NumOut() != 1 && t.NumOut() != 2 {712return errors.New("SQLite aggregator constructors must return 1 or 2 values")713}714if t.NumOut() == 2 && !t.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {715return errors.New("Second return value of SQLite function must be error")716}717if t.NumIn() != 0 {718return errors.New("SQLite aggregator constructors must not have arguments")719}720
721agg := t.Out(0)722switch agg.Kind() {723case reflect.Ptr, reflect.Interface:724default:725return errors.New("SQlite aggregator constructor must return a pointer object")726}727stepFn, found := agg.MethodByName("Step")728if !found {729return errors.New("SQlite aggregator doesn't have a Step() function")730}731step := stepFn.Type732if step.NumOut() != 0 && step.NumOut() != 1 {733return errors.New("SQlite aggregator Step() function must return 0 or 1 values")734}735if step.NumOut() == 1 && !step.Out(0).Implements(reflect.TypeOf((*error)(nil)).Elem()) {736return errors.New("type of SQlite aggregator Step() return value must be error")737}738
739stepNArgs := step.NumIn()740start := 0741if agg.Kind() == reflect.Ptr {742// Skip over the method receiver743stepNArgs--744start++745}746if step.IsVariadic() {747stepNArgs--748}749for i := start; i < start+stepNArgs; i++ {750conv, err := callbackArg(step.In(i))751if err != nil {752return err753}754ai.stepArgConverters = append(ai.stepArgConverters, conv)755}756if step.IsVariadic() {757conv, err := callbackArg(step.In(start + stepNArgs).Elem())758if err != nil {759return err760}761ai.stepVariadicConverter = conv762// Pass -1 to sqlite so that it allows any number of763// arguments. The call helper verifies that the minimum number764// of arguments is present for variadic functions.765stepNArgs = -1766}767
768doneFn, found := agg.MethodByName("Done")769if !found {770return errors.New("SQlite aggregator doesn't have a Done() function")771}772done := doneFn.Type773doneNArgs := done.NumIn()774if agg.Kind() == reflect.Ptr {775// Skip over the method receiver776doneNArgs--777}778if doneNArgs != 0 {779return errors.New("SQlite aggregator Done() function must have no arguments")780}781if done.NumOut() != 1 && done.NumOut() != 2 {782return errors.New("SQLite aggregator Done() function must return 1 or 2 values")783}784if done.NumOut() == 2 && !done.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {785return errors.New("second return value of SQLite aggregator Done() function must be error")786}787
788conv, err := callbackRet(done.Out(0))789if err != nil {790return err791}792ai.doneRetConverter = conv793ai.active = make(map[int64]reflect.Value)794ai.next = 1795
796// ai must outlast the database connection, or we'll have dangling pointers.797c.aggregators = append(c.aggregators, &ai)798
799cname := C.CString(name)800defer C.free(unsafe.Pointer(cname))801opts := C.SQLITE_UTF8802if pure {803opts |= C.SQLITE_DETERMINISTIC804}805rv := sqlite3CreateFunction(c.db, cname, C.int(stepNArgs), C.int(opts), newHandle(c, &ai), nil, C.stepTrampoline, C.doneTrampoline)806if rv != C.SQLITE_OK {807return c.lastError()808}809return nil810}
811
812// AutoCommit return which currently auto commit or not.
813func (c *SQLiteConn) AutoCommit() bool {814c.mu.Lock()815defer c.mu.Unlock()816return int(C.sqlite3_get_autocommit(c.db)) != 0817}
818
819func (c *SQLiteConn) lastError() error {820return lastError(c.db)821}
822
823// Note: may be called with db == nil
824func lastError(db *C.sqlite3) error {825rv := C.sqlite3_errcode(db) // returns SQLITE_NOMEM if db == nil826if rv == C.SQLITE_OK {827return nil828}829extrv := C.sqlite3_extended_errcode(db) // returns SQLITE_NOMEM if db == nil830errStr := C.GoString(C.sqlite3_errmsg(db)) // returns "out of memory" if db == nil831
832// https://www.sqlite.org/c3ref/system_errno.html833// sqlite3_system_errno is only meaningful if the error code was SQLITE_CANTOPEN,834// or it was SQLITE_IOERR and the extended code was not SQLITE_IOERR_NOMEM835var systemErrno syscall.Errno836if rv == C.SQLITE_CANTOPEN || (rv == C.SQLITE_IOERR && extrv != C.SQLITE_IOERR_NOMEM) {837systemErrno = syscall.Errno(C.sqlite3_system_errno(db))838}839
840return Error{841Code: ErrNo(rv),842ExtendedCode: ErrNoExtended(extrv),843SystemErrno: systemErrno,844err: errStr,845}846}
847
848// Exec implements Execer.
849func (c *SQLiteConn) Exec(query string, args []driver.Value) (driver.Result, error) {850list := make([]driver.NamedValue, len(args))851for i, v := range args {852list[i] = driver.NamedValue{853Ordinal: i + 1,854Value: v,855}856}857return c.exec(context.Background(), query, list)858}
859
860func (c *SQLiteConn) exec(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {861start := 0862for {863s, err := c.prepare(ctx, query)864if err != nil {865return nil, err866}867var res driver.Result868if s.(*SQLiteStmt).s != nil {869stmtArgs := make([]driver.NamedValue, 0, len(args))870na := s.NumInput()871if len(args)-start < na {872s.Close()873return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))874}875// consume the number of arguments used in the current876// statement and append all named arguments not877// contained therein878if len(args[start:start+na]) > 0 {879stmtArgs = append(stmtArgs, args[start:start+na]...)880for i := range args {881if (i < start || i >= na) && args[i].Name != "" {882stmtArgs = append(stmtArgs, args[i])883}884}885for i := range stmtArgs {886stmtArgs[i].Ordinal = i + 1887}888}889res, err = s.(*SQLiteStmt).exec(ctx, stmtArgs)890if err != nil && err != driver.ErrSkip {891s.Close()892return nil, err893}894start += na895}896tail := s.(*SQLiteStmt).t897s.Close()898if tail == "" {899if res == nil {900// https://github.com/mattn/go-sqlite3/issues/963901res = &SQLiteResult{0, 0}902}903return res, nil904}905query = tail906}907}
908
909// Query implements Queryer.
910func (c *SQLiteConn) Query(query string, args []driver.Value) (driver.Rows, error) {911list := make([]driver.NamedValue, len(args))912for i, v := range args {913list[i] = driver.NamedValue{914Ordinal: i + 1,915Value: v,916}917}918return c.query(context.Background(), query, list)919}
920
921func (c *SQLiteConn) query(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {922start := 0923for {924stmtArgs := make([]driver.NamedValue, 0, len(args))925s, err := c.prepare(ctx, query)926if err != nil {927return nil, err928}929s.(*SQLiteStmt).cls = true930na := s.NumInput()931if len(args)-start < na {932return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args)-start)933}934// consume the number of arguments used in the current935// statement and append all named arguments not contained936// therein937stmtArgs = append(stmtArgs, args[start:start+na]...)938for i := range args {939if (i < start || i >= na) && args[i].Name != "" {940stmtArgs = append(stmtArgs, args[i])941}942}943for i := range stmtArgs {944stmtArgs[i].Ordinal = i + 1945}946rows, err := s.(*SQLiteStmt).query(ctx, stmtArgs)947if err != nil && err != driver.ErrSkip {948s.Close()949return rows, err950}951start += na952tail := s.(*SQLiteStmt).t953if tail == "" {954return rows, nil955}956rows.Close()957s.Close()958query = tail959}960}
961
962// Begin transaction.
963func (c *SQLiteConn) Begin() (driver.Tx, error) {964return c.begin(context.Background())965}
966
967func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {968if _, err := c.exec(ctx, c.txlock, nil); err != nil {969return nil, err970}971return &SQLiteTx{c}, nil972}
973
974// Open database and return a new connection.
975//
976// A pragma can take either zero or one argument.
977// The argument is may be either in parentheses or it may be separated from
978// the pragma name by an equal sign. The two syntaxes yield identical results.
979// In many pragmas, the argument is a boolean. The boolean can be one of:
980//
981// 1 yes true on
982// 0 no false off
983//
984// You can specify a DSN string using a URI as the filename.
985//
986// test.db
987// file:test.db?cache=shared&mode=memory
988// :memory:
989// file::memory:
990//
991// mode
992// Access mode of the database.
993// https://www.sqlite.org/c3ref/open.html
994// Values:
995// - ro
996// - rw
997// - rwc
998// - memory
999//
1000// cache
1001// SQLite Shared-Cache Mode
1002// https://www.sqlite.org/sharedcache.html
1003// Values:
1004// - shared
1005// - private
1006//
1007// immutable=Boolean
1008// The immutable parameter is a boolean query parameter that indicates
1009// that the database file is stored on read-only media. When immutable is set,
1010// SQLite assumes that the database file cannot be changed,
1011// even by a process with higher privilege,
1012// and so the database is opened read-only and all locking and change detection is disabled.
1013// Caution: Setting the immutable property on a database file that
1014// does in fact change can result in incorrect query results and/or SQLITE_CORRUPT errors.
1015//
1016// go-sqlite3 adds the following query parameters to those used by SQLite:
1017//
1018// _loc=XXX
1019// Specify location of time format. It's possible to specify "auto".
1020//
1021// _mutex=XXX
1022// Specify mutex mode. XXX can be "no", "full".
1023//
1024// _txlock=XXX
1025// Specify locking behavior for transactions. XXX can be "immediate",
1026// "deferred", "exclusive".
1027//
1028// _auto_vacuum=X | _vacuum=X
1029// 0 | none - Auto Vacuum disabled
1030// 1 | full - Auto Vacuum FULL
1031// 2 | incremental - Auto Vacuum Incremental
1032//
1033// _busy_timeout=XXX"| _timeout=XXX
1034// Specify value for sqlite3_busy_timeout.
1035//
1036// _case_sensitive_like=Boolean | _cslike=Boolean
1037// https://www.sqlite.org/pragma.html#pragma_case_sensitive_like
1038// Default or disabled the LIKE operation is case-insensitive.
1039// When enabling this options behaviour of LIKE will become case-sensitive.
1040//
1041// _defer_foreign_keys=Boolean | _defer_fk=Boolean
1042// Defer Foreign Keys until outermost transaction is committed.
1043//
1044// _foreign_keys=Boolean | _fk=Boolean
1045// Enable or disable enforcement of foreign keys.
1046//
1047// _ignore_check_constraints=Boolean
1048// This pragma enables or disables the enforcement of CHECK constraints.
1049// The default setting is off, meaning that CHECK constraints are enforced by default.
1050//
1051// _journal_mode=MODE | _journal=MODE
1052// Set journal mode for the databases associated with the current connection.
1053// https://www.sqlite.org/pragma.html#pragma_journal_mode
1054//
1055// _locking_mode=X | _locking=X
1056// Sets the database connection locking-mode.
1057// The locking-mode is either NORMAL or EXCLUSIVE.
1058// https://www.sqlite.org/pragma.html#pragma_locking_mode
1059//
1060// _query_only=Boolean
1061// The query_only pragma prevents all changes to database files when enabled.
1062//
1063// _recursive_triggers=Boolean | _rt=Boolean
1064// Enable or disable recursive triggers.
1065//
1066// _secure_delete=Boolean|FAST
1067// When secure_delete is on, SQLite overwrites deleted content with zeros.
1068// https://www.sqlite.org/pragma.html#pragma_secure_delete
1069//
1070// _synchronous=X | _sync=X
1071// Change the setting of the "synchronous" flag.
1072// https://www.sqlite.org/pragma.html#pragma_synchronous
1073//
1074// _writable_schema=Boolean
1075// When this pragma is on, the SQLITE_MASTER tables in which database
1076// can be changed using ordinary UPDATE, INSERT, and DELETE statements.
1077// Warning: misuse of this pragma can easily result in a corrupt database file.
1078func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {1079if C.sqlite3_threadsafe() == 0 {1080return nil, errors.New("sqlite library was not compiled for thread-safe operation")1081}1082
1083var pkey string1084
1085// Options1086var loc *time.Location1087authCreate := false1088authUser := ""1089authPass := ""1090authCrypt := ""1091authSalt := ""1092mutex := C.int(C.SQLITE_OPEN_FULLMUTEX)1093txlock := "BEGIN"1094
1095// PRAGMA's1096autoVacuum := -11097busyTimeout := 50001098caseSensitiveLike := -11099deferForeignKeys := -11100foreignKeys := -11101ignoreCheckConstraints := -11102var journalMode string1103lockingMode := "NORMAL"1104queryOnly := -11105recursiveTriggers := -11106secureDelete := "DEFAULT"1107synchronousMode := "NORMAL"1108writableSchema := -11109vfsName := ""1110var cacheSize *int641111
1112pos := strings.IndexRune(dsn, '?')1113if pos >= 1 {1114params, err := url.ParseQuery(dsn[pos+1:])1115if err != nil {1116return nil, err1117}1118
1119// Authentication1120if _, ok := params["_auth"]; ok {1121authCreate = true1122}1123if val := params.Get("_auth_user"); val != "" {1124authUser = val1125}1126if val := params.Get("_auth_pass"); val != "" {1127authPass = val1128}1129if val := params.Get("_auth_crypt"); val != "" {1130authCrypt = val1131}1132if val := params.Get("_auth_salt"); val != "" {1133authSalt = val1134}1135
1136// _loc1137if val := params.Get("_loc"); val != "" {1138switch strings.ToLower(val) {1139case "auto":1140loc = time.Local1141default:1142loc, err = time.LoadLocation(val)1143if err != nil {1144return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err)1145}1146}1147}1148
1149// _mutex1150if val := params.Get("_mutex"); val != "" {1151switch strings.ToLower(val) {1152case "no":1153mutex = C.SQLITE_OPEN_NOMUTEX1154case "full":1155mutex = C.SQLITE_OPEN_FULLMUTEX1156default:1157return nil, fmt.Errorf("Invalid _mutex: %v", val)1158}1159}1160
1161// _txlock1162if val := params.Get("_txlock"); val != "" {1163switch strings.ToLower(val) {1164case "immediate":1165txlock = "BEGIN IMMEDIATE"1166case "exclusive":1167txlock = "BEGIN EXCLUSIVE"1168case "deferred":1169txlock = "BEGIN"1170default:1171return nil, fmt.Errorf("Invalid _txlock: %v", val)1172}1173}1174
1175// Auto Vacuum (_vacuum)1176//1177// https://www.sqlite.org/pragma.html#pragma_auto_vacuum1178//1179pkey = "" // Reset pkey1180if _, ok := params["_auto_vacuum"]; ok {1181pkey = "_auto_vacuum"1182}1183if _, ok := params["_vacuum"]; ok {1184pkey = "_vacuum"1185}1186if val := params.Get(pkey); val != "" {1187switch strings.ToLower(val) {1188case "0", "none":1189autoVacuum = 01190case "1", "full":1191autoVacuum = 11192case "2", "incremental":1193autoVacuum = 21194default:1195return nil, fmt.Errorf("Invalid _auto_vacuum: %v, expecting value of '0 NONE 1 FULL 2 INCREMENTAL'", val)1196}1197}1198
1199// Busy Timeout (_busy_timeout)1200//1201// https://www.sqlite.org/pragma.html#pragma_busy_timeout1202//1203pkey = "" // Reset pkey1204if _, ok := params["_busy_timeout"]; ok {1205pkey = "_busy_timeout"1206}1207if _, ok := params["_timeout"]; ok {1208pkey = "_timeout"1209}1210if val := params.Get(pkey); val != "" {1211iv, err := strconv.ParseInt(val, 10, 64)1212if err != nil {1213return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)1214}1215busyTimeout = int(iv)1216}1217
1218// Case Sensitive Like (_cslike)1219//1220// https://www.sqlite.org/pragma.html#pragma_case_sensitive_like1221//1222pkey = "" // Reset pkey1223if _, ok := params["_case_sensitive_like"]; ok {1224pkey = "_case_sensitive_like"1225}1226if _, ok := params["_cslike"]; ok {1227pkey = "_cslike"1228}1229if val := params.Get(pkey); val != "" {1230switch strings.ToLower(val) {1231case "0", "no", "false", "off":1232caseSensitiveLike = 01233case "1", "yes", "true", "on":1234caseSensitiveLike = 11235default:1236return nil, fmt.Errorf("Invalid _case_sensitive_like: %v, expecting boolean value of '0 1 false true no yes off on'", val)1237}1238}1239
1240// Defer Foreign Keys (_defer_foreign_keys | _defer_fk)1241//1242// https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys1243//1244pkey = "" // Reset pkey1245if _, ok := params["_defer_foreign_keys"]; ok {1246pkey = "_defer_foreign_keys"1247}1248if _, ok := params["_defer_fk"]; ok {1249pkey = "_defer_fk"1250}1251if val := params.Get(pkey); val != "" {1252switch strings.ToLower(val) {1253case "0", "no", "false", "off":1254deferForeignKeys = 01255case "1", "yes", "true", "on":1256deferForeignKeys = 11257default:1258return nil, fmt.Errorf("Invalid _defer_foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val)1259}1260}1261
1262// Foreign Keys (_foreign_keys | _fk)1263//1264// https://www.sqlite.org/pragma.html#pragma_foreign_keys1265//1266pkey = "" // Reset pkey1267if _, ok := params["_foreign_keys"]; ok {1268pkey = "_foreign_keys"1269}1270if _, ok := params["_fk"]; ok {1271pkey = "_fk"1272}1273if val := params.Get(pkey); val != "" {1274switch strings.ToLower(val) {1275case "0", "no", "false", "off":1276foreignKeys = 01277case "1", "yes", "true", "on":1278foreignKeys = 11279default:1280return nil, fmt.Errorf("Invalid _foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val)1281}1282}1283
1284// Ignore CHECK Constrains (_ignore_check_constraints)1285//1286// https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints1287//1288if val := params.Get("_ignore_check_constraints"); val != "" {1289switch strings.ToLower(val) {1290case "0", "no", "false", "off":1291ignoreCheckConstraints = 01292case "1", "yes", "true", "on":1293ignoreCheckConstraints = 11294default:1295return nil, fmt.Errorf("Invalid _ignore_check_constraints: %v, expecting boolean value of '0 1 false true no yes off on'", val)1296}1297}1298
1299// Journal Mode (_journal_mode | _journal)1300//1301// https://www.sqlite.org/pragma.html#pragma_journal_mode1302//1303pkey = "" // Reset pkey1304if _, ok := params["_journal_mode"]; ok {1305pkey = "_journal_mode"1306}1307if _, ok := params["_journal"]; ok {1308pkey = "_journal"1309}1310if val := params.Get(pkey); val != "" {1311switch strings.ToUpper(val) {1312case "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "OFF":1313journalMode = strings.ToUpper(val)1314case "WAL":1315journalMode = strings.ToUpper(val)1316
1317// For WAL Mode set Synchronous Mode to 'NORMAL'1318// See https://www.sqlite.org/pragma.html#pragma_synchronous1319synchronousMode = "NORMAL"1320default:1321return nil, fmt.Errorf("Invalid _journal: %v, expecting value of 'DELETE TRUNCATE PERSIST MEMORY WAL OFF'", val)1322}1323}1324
1325// Locking Mode (_locking)1326//1327// https://www.sqlite.org/pragma.html#pragma_locking_mode1328//1329pkey = "" // Reset pkey1330if _, ok := params["_locking_mode"]; ok {1331pkey = "_locking_mode"1332}1333if _, ok := params["_locking"]; ok {1334pkey = "_locking"1335}1336if val := params.Get(pkey); val != "" {1337switch strings.ToUpper(val) {1338case "NORMAL", "EXCLUSIVE":1339lockingMode = strings.ToUpper(val)1340default:1341return nil, fmt.Errorf("Invalid _locking_mode: %v, expecting value of 'NORMAL EXCLUSIVE", val)1342}1343}1344
1345// Query Only (_query_only)1346//1347// https://www.sqlite.org/pragma.html#pragma_query_only1348//1349if val := params.Get("_query_only"); val != "" {1350switch strings.ToLower(val) {1351case "0", "no", "false", "off":1352queryOnly = 01353case "1", "yes", "true", "on":1354queryOnly = 11355default:1356return nil, fmt.Errorf("Invalid _query_only: %v, expecting boolean value of '0 1 false true no yes off on'", val)1357}1358}1359
1360// Recursive Triggers (_recursive_triggers)1361//1362// https://www.sqlite.org/pragma.html#pragma_recursive_triggers1363//1364pkey = "" // Reset pkey1365if _, ok := params["_recursive_triggers"]; ok {1366pkey = "_recursive_triggers"1367}1368if _, ok := params["_rt"]; ok {1369pkey = "_rt"1370}1371if val := params.Get(pkey); val != "" {1372switch strings.ToLower(val) {1373case "0", "no", "false", "off":1374recursiveTriggers = 01375case "1", "yes", "true", "on":1376recursiveTriggers = 11377default:1378return nil, fmt.Errorf("Invalid _recursive_triggers: %v, expecting boolean value of '0 1 false true no yes off on'", val)1379}1380}1381
1382// Secure Delete (_secure_delete)1383//1384// https://www.sqlite.org/pragma.html#pragma_secure_delete1385//1386if val := params.Get("_secure_delete"); val != "" {1387switch strings.ToLower(val) {1388case "0", "no", "false", "off":1389secureDelete = "OFF"1390case "1", "yes", "true", "on":1391secureDelete = "ON"1392case "fast":1393secureDelete = "FAST"1394default:1395return nil, fmt.Errorf("Invalid _secure_delete: %v, expecting boolean value of '0 1 false true no yes off on fast'", val)1396}1397}1398
1399// Synchronous Mode (_synchronous | _sync)1400//1401// https://www.sqlite.org/pragma.html#pragma_synchronous1402//1403pkey = "" // Reset pkey1404if _, ok := params["_synchronous"]; ok {1405pkey = "_synchronous"1406}1407if _, ok := params["_sync"]; ok {1408pkey = "_sync"1409}1410if val := params.Get(pkey); val != "" {1411switch strings.ToUpper(val) {1412case "0", "OFF", "1", "NORMAL", "2", "FULL", "3", "EXTRA":1413synchronousMode = strings.ToUpper(val)1414default:1415return nil, fmt.Errorf("Invalid _synchronous: %v, expecting value of '0 OFF 1 NORMAL 2 FULL 3 EXTRA'", val)1416}1417}1418
1419// Writable Schema (_writeable_schema)1420//1421// https://www.sqlite.org/pragma.html#pragma_writeable_schema1422//1423if val := params.Get("_writable_schema"); val != "" {1424switch strings.ToLower(val) {1425case "0", "no", "false", "off":1426writableSchema = 01427case "1", "yes", "true", "on":1428writableSchema = 11429default:1430return nil, fmt.Errorf("Invalid _writable_schema: %v, expecting boolean value of '0 1 false true no yes off on'", val)1431}1432}1433
1434// Cache size (_cache_size)1435//1436// https://sqlite.org/pragma.html#pragma_cache_size1437//1438if val := params.Get("_cache_size"); val != "" {1439iv, err := strconv.ParseInt(val, 10, 64)1440if err != nil {1441return nil, fmt.Errorf("Invalid _cache_size: %v: %v", val, err)1442}1443cacheSize = &iv1444}1445
1446if val := params.Get("vfs"); val != "" {1447vfsName = val1448}1449
1450if !strings.HasPrefix(dsn, "file:") {1451dsn = dsn[:pos]1452}1453}1454
1455var db *C.sqlite31456name := C.CString(dsn)1457defer C.free(unsafe.Pointer(name))1458var vfs *C.char1459if vfsName != "" {1460vfs = C.CString(vfsName)1461defer C.free(unsafe.Pointer(vfs))1462}1463rv := C._sqlite3_open_v2(name, &db,1464mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE,1465vfs)1466if rv != 0 {1467// Save off the error _before_ closing the database.1468// This is safe even if db is nil.1469err := lastError(db)1470if db != nil {1471C.sqlite3_close_v2(db)1472}1473return nil, err1474}1475if db == nil {1476return nil, errors.New("sqlite succeeded without returning a database")1477}1478
1479exec := func(s string) error {1480cs := C.CString(s)1481rv := C.sqlite3_exec(db, cs, nil, nil, nil)1482C.free(unsafe.Pointer(cs))1483if rv != C.SQLITE_OK {1484return lastError(db)1485}1486return nil1487}1488
1489// Busy timeout1490if err := exec(fmt.Sprintf("PRAGMA busy_timeout = %d;", busyTimeout)); err != nil {1491C.sqlite3_close_v2(db)1492return nil, err1493}1494
1495// USER AUTHENTICATION1496//1497// User Authentication is always performed even when1498// sqlite_userauth is not compiled in, because without user authentication1499// the authentication is a no-op.1500//1501// Workflow1502// - Authenticate1503// ON::SUCCESS => Continue1504// ON::SQLITE_AUTH => Return error and exit Open(...)1505//1506// - Activate User Authentication1507// Check if the user wants to activate User Authentication.1508// If so then first create a temporary AuthConn to the database1509// This is possible because we are already successfully authenticated.1510//1511// - Check if `sqlite_user`` table exists1512// YES => Add the provided user from DSN as Admin User and1513// activate user authentication.1514// NO => Continue1515//1516
1517// Create connection to SQLite1518conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}1519
1520// Password Cipher has to be registered before authentication1521if len(authCrypt) > 0 {1522switch strings.ToUpper(authCrypt) {1523case "SHA1":1524if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil {1525return nil, fmt.Errorf("CryptEncoderSHA1: %s", err)1526}1527case "SSHA1":1528if len(authSalt) == 0 {1529return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt")1530}1531if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil {1532return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err)1533}1534case "SHA256":1535if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil {1536return nil, fmt.Errorf("CryptEncoderSHA256: %s", err)1537}1538case "SSHA256":1539if len(authSalt) == 0 {1540return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt")1541}1542if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil {1543return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err)1544}1545case "SHA384":1546if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil {1547return nil, fmt.Errorf("CryptEncoderSHA384: %s", err)1548}1549case "SSHA384":1550if len(authSalt) == 0 {1551return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt")1552}1553if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil {1554return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err)1555}1556case "SHA512":1557if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil {1558return nil, fmt.Errorf("CryptEncoderSHA512: %s", err)1559}1560case "SSHA512":1561if len(authSalt) == 0 {1562return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt")1563}1564if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil {1565return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err)1566}1567}1568}1569
1570// Preform Authentication1571if err := conn.Authenticate(authUser, authPass); err != nil {1572return nil, err1573}1574
1575// Register: authenticate1576// Authenticate will perform an authentication of the provided username1577// and password against the database.1578//1579// If a database contains the SQLITE_USER table, then the1580// call to Authenticate must be invoked with an1581// appropriate username and password prior to enable read and write1582//access to the database.1583//1584// Return SQLITE_OK on success or SQLITE_ERROR if the username/password1585// combination is incorrect or unknown.1586//1587// If the SQLITE_USER table is not present in the database file, then1588// this interface is a harmless no-op returnning SQLITE_OK.1589if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil {1590return nil, err1591}1592//1593// Register: auth_user_add1594// auth_user_add can be used (by an admin user only)1595// to create a new user. When called on a no-authentication-required1596// database, this routine converts the database into an authentication-1597// required database, automatically makes the added user an1598// administrator, and logs in the current connection as that user.1599// The AuthUserAdd only works for the "main" database, not1600// for any ATTACH-ed databases. Any call to AuthUserAdd by a1601// non-admin user results in an error.1602if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil {1603return nil, err1604}1605//1606// Register: auth_user_change1607// auth_user_change can be used to change a users1608// login credentials or admin privilege. Any user can change their own1609// login credentials. Only an admin user can change another users login1610// credentials or admin privilege setting. No user may change their own1611// admin privilege setting.1612if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil {1613return nil, err1614}1615//1616// Register: auth_user_delete1617// auth_user_delete can be used (by an admin user only)1618// to delete a user. The currently logged-in user cannot be deleted,1619// which guarantees that there is always an admin user and hence that1620// the database cannot be converted into a no-authentication-required1621// database.1622if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil {1623return nil, err1624}1625
1626// Register: auth_enabled1627// auth_enabled can be used to check if user authentication is enabled1628if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil {1629return nil, err1630}1631
1632// Auto Vacuum1633// Moved auto_vacuum command, the user preference for auto_vacuum needs to be implemented directly after1634// the authentication and before the sqlite_user table gets created if the user1635// decides to activate User Authentication because1636// auto_vacuum needs to be set before any tables are created1637// and activating user authentication creates the internal table `sqlite_user`.1638if autoVacuum > -1 {1639if err := exec(fmt.Sprintf("PRAGMA auto_vacuum = %d;", autoVacuum)); err != nil {1640C.sqlite3_close_v2(db)1641return nil, err1642}1643}1644
1645// Check if user wants to activate User Authentication1646if authCreate {1647// Before going any further, we need to check that the user1648// has provided an username and password within the DSN.1649// We are not allowed to continue.1650if len(authUser) == 0 {1651return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'")1652}1653if len(authPass) == 0 {1654return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'")1655}1656
1657// Check if User Authentication is Enabled1658authExists := conn.AuthEnabled()1659if !authExists {1660if err := conn.AuthUserAdd(authUser, authPass, true); err != nil {1661return nil, err1662}1663}1664}1665
1666// Case Sensitive LIKE1667if caseSensitiveLike > -1 {1668if err := exec(fmt.Sprintf("PRAGMA case_sensitive_like = %d;", caseSensitiveLike)); err != nil {1669C.sqlite3_close_v2(db)1670return nil, err1671}1672}1673
1674// Defer Foreign Keys1675if deferForeignKeys > -1 {1676if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil {1677C.sqlite3_close_v2(db)1678return nil, err1679}1680}1681
1682// Forgein Keys1683if foreignKeys > -1 {1684if err := exec(fmt.Sprintf("PRAGMA foreign_keys = %d;", foreignKeys)); err != nil {1685C.sqlite3_close_v2(db)1686return nil, err1687}1688}1689
1690// Ignore CHECK Constraints1691if ignoreCheckConstraints > -1 {1692if err := exec(fmt.Sprintf("PRAGMA ignore_check_constraints = %d;", ignoreCheckConstraints)); err != nil {1693C.sqlite3_close_v2(db)1694return nil, err1695}1696}1697
1698// Journal Mode1699if journalMode != "" {1700if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {1701C.sqlite3_close_v2(db)1702return nil, err1703}1704}1705
1706// Locking Mode1707// Because the default is NORMAL and this is not changed in this package1708// by using the compile time SQLITE_DEFAULT_LOCKING_MODE this PRAGMA can always be executed1709if err := exec(fmt.Sprintf("PRAGMA locking_mode = %s;", lockingMode)); err != nil {1710C.sqlite3_close_v2(db)1711return nil, err1712}1713
1714// Query Only1715if queryOnly > -1 {1716if err := exec(fmt.Sprintf("PRAGMA query_only = %d;", queryOnly)); err != nil {1717C.sqlite3_close_v2(db)1718return nil, err1719}1720}1721
1722// Recursive Triggers1723if recursiveTriggers > -1 {1724if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil {1725C.sqlite3_close_v2(db)1726return nil, err1727}1728}1729
1730// Secure Delete1731//1732// Because this package can set the compile time flag SQLITE_SECURE_DELETE with a build tag1733// the default value for secureDelete var is 'DEFAULT' this way1734// you can compile with secure_delete 'ON' and disable it for a specific database connection.1735if secureDelete != "DEFAULT" {1736if err := exec(fmt.Sprintf("PRAGMA secure_delete = %s;", secureDelete)); err != nil {1737C.sqlite3_close_v2(db)1738return nil, err1739}1740}1741
1742// Synchronous Mode1743//1744// Because default is NORMAL this statement is always executed1745if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil {1746conn.Close()1747return nil, err1748}1749
1750// Writable Schema1751if writableSchema > -1 {1752if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil {1753C.sqlite3_close_v2(db)1754return nil, err1755}1756}1757
1758// Cache Size1759if cacheSize != nil {1760if err := exec(fmt.Sprintf("PRAGMA cache_size = %d;", *cacheSize)); err != nil {1761C.sqlite3_close_v2(db)1762return nil, err1763}1764}1765
1766if len(d.Extensions) > 0 {1767if err := conn.loadExtensions(d.Extensions); err != nil {1768conn.Close()1769return nil, err1770}1771}1772
1773if d.ConnectHook != nil {1774if err := d.ConnectHook(conn); err != nil {1775conn.Close()1776return nil, err1777}1778}1779runtime.SetFinalizer(conn, (*SQLiteConn).Close)1780return conn, nil1781}
1782
1783// Close the connection.
1784func (c *SQLiteConn) Close() error {1785rv := C.sqlite3_close_v2(c.db)1786if rv != C.SQLITE_OK {1787return c.lastError()1788}1789deleteHandles(c)1790c.mu.Lock()1791c.db = nil1792c.mu.Unlock()1793runtime.SetFinalizer(c, nil)1794return nil1795}
1796
1797func (c *SQLiteConn) dbConnOpen() bool {1798if c == nil {1799return false1800}1801c.mu.Lock()1802defer c.mu.Unlock()1803return c.db != nil1804}
1805
1806// Prepare the query string. Return a new statement.
1807func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {1808return c.prepare(context.Background(), query)1809}
1810
1811func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, error) {1812pquery := C.CString(query)1813defer C.free(unsafe.Pointer(pquery))1814var s *C.sqlite3_stmt1815var tail *C.char1816rv := C._sqlite3_prepare_v2_internal(c.db, pquery, C.int(-1), &s, &tail)1817if rv != C.SQLITE_OK {1818return nil, c.lastError()1819}1820var t string1821if tail != nil && *tail != '\000' {1822t = strings.TrimSpace(C.GoString(tail))1823}1824ss := &SQLiteStmt{c: c, s: s, t: t}1825runtime.SetFinalizer(ss, (*SQLiteStmt).Close)1826return ss, nil1827}
1828
1829// Run-Time Limit Categories.
1830// See: http://www.sqlite.org/c3ref/c_limit_attached.html
1831const (1832SQLITE_LIMIT_LENGTH = C.SQLITE_LIMIT_LENGTH1833SQLITE_LIMIT_SQL_LENGTH = C.SQLITE_LIMIT_SQL_LENGTH1834SQLITE_LIMIT_COLUMN = C.SQLITE_LIMIT_COLUMN1835SQLITE_LIMIT_EXPR_DEPTH = C.SQLITE_LIMIT_EXPR_DEPTH1836SQLITE_LIMIT_COMPOUND_SELECT = C.SQLITE_LIMIT_COMPOUND_SELECT1837SQLITE_LIMIT_VDBE_OP = C.SQLITE_LIMIT_VDBE_OP1838SQLITE_LIMIT_FUNCTION_ARG = C.SQLITE_LIMIT_FUNCTION_ARG1839SQLITE_LIMIT_ATTACHED = C.SQLITE_LIMIT_ATTACHED1840SQLITE_LIMIT_LIKE_PATTERN_LENGTH = C.SQLITE_LIMIT_LIKE_PATTERN_LENGTH1841SQLITE_LIMIT_VARIABLE_NUMBER = C.SQLITE_LIMIT_VARIABLE_NUMBER1842SQLITE_LIMIT_TRIGGER_DEPTH = C.SQLITE_LIMIT_TRIGGER_DEPTH1843SQLITE_LIMIT_WORKER_THREADS = C.SQLITE_LIMIT_WORKER_THREADS1844)
1845
1846// GetFilename returns the absolute path to the file containing
1847// the requested schema. When passed an empty string, it will
1848// instead use the database's default schema: "main".
1849// See: sqlite3_db_filename, https://www.sqlite.org/c3ref/db_filename.html
1850func (c *SQLiteConn) GetFilename(schemaName string) string {1851if schemaName == "" {1852schemaName = "main"1853}1854return C.GoString(C.sqlite3_db_filename(c.db, C.CString(schemaName)))1855}
1856
1857// GetLimit returns the current value of a run-time limit.
1858// See: sqlite3_limit, http://www.sqlite.org/c3ref/limit.html
1859func (c *SQLiteConn) GetLimit(id int) int {1860return int(C._sqlite3_limit(c.db, C.int(id), C.int(-1)))1861}
1862
1863// SetLimit changes the value of a run-time limits.
1864// Then this method returns the prior value of the limit.
1865// See: sqlite3_limit, http://www.sqlite.org/c3ref/limit.html
1866func (c *SQLiteConn) SetLimit(id int, newVal int) int {1867return int(C._sqlite3_limit(c.db, C.int(id), C.int(newVal)))1868}
1869
1870// SetFileControlInt invokes the xFileControl method on a given database. The
1871// dbName is the name of the database. It will default to "main" if left blank.
1872// The op is one of the opcodes prefixed by "SQLITE_FCNTL_". The arg argument
1873// and return code are both opcode-specific. Please see the SQLite documentation.
1874//
1875// This method is not thread-safe as the returned error code can be changed by
1876// another call if invoked concurrently.
1877//
1878// See: sqlite3_file_control, https://www.sqlite.org/c3ref/file_control.html
1879func (c *SQLiteConn) SetFileControlInt(dbName string, op int, arg int) error {1880if dbName == "" {1881dbName = "main"1882}1883
1884cDBName := C.CString(dbName)1885defer C.free(unsafe.Pointer(cDBName))1886
1887cArg := C.int(arg)1888rv := C.sqlite3_file_control(c.db, cDBName, C.int(op), unsafe.Pointer(&cArg))1889if rv != C.SQLITE_OK {1890return c.lastError()1891}1892return nil1893}
1894
1895// Close the statement.
1896func (s *SQLiteStmt) Close() error {1897s.mu.Lock()1898defer s.mu.Unlock()1899if s.closed {1900return nil1901}1902s.closed = true1903if !s.c.dbConnOpen() {1904return errors.New("sqlite statement with already closed database connection")1905}1906rv := C.sqlite3_finalize(s.s)1907s.s = nil1908if rv != C.SQLITE_OK {1909return s.c.lastError()1910}1911s.c = nil1912runtime.SetFinalizer(s, nil)1913return nil1914}
1915
1916// NumInput return a number of parameters.
1917func (s *SQLiteStmt) NumInput() int {1918return int(C.sqlite3_bind_parameter_count(s.s))1919}
1920
1921var placeHolder = []byte{0}1922
1923func (s *SQLiteStmt) bind(args []driver.NamedValue) error {1924rv := C.sqlite3_reset(s.s)1925if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {1926return s.c.lastError()1927}1928
1929bindIndices := make([][3]int, len(args))1930prefixes := []string{":", "@", "$"}1931for i, v := range args {1932bindIndices[i][0] = args[i].Ordinal1933if v.Name != "" {1934for j := range prefixes {1935cname := C.CString(prefixes[j] + v.Name)1936bindIndices[i][j] = int(C.sqlite3_bind_parameter_index(s.s, cname))1937C.free(unsafe.Pointer(cname))1938}1939args[i].Ordinal = bindIndices[i][0]1940}1941}1942
1943for i, arg := range args {1944for j := range bindIndices[i] {1945if bindIndices[i][j] == 0 {1946continue1947}1948n := C.int(bindIndices[i][j])1949switch v := arg.Value.(type) {1950case nil:1951rv = C.sqlite3_bind_null(s.s, n)1952case string:1953if len(v) == 0 {1954rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.int(0))1955} else {1956b := []byte(v)1957rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))1958}1959case int64:1960rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v))1961case bool:1962if v {1963rv = C.sqlite3_bind_int(s.s, n, 1)1964} else {1965rv = C.sqlite3_bind_int(s.s, n, 0)1966}1967case float64:1968rv = C.sqlite3_bind_double(s.s, n, C.double(v))1969case []byte:1970if v == nil {1971rv = C.sqlite3_bind_null(s.s, n)1972} else {1973ln := len(v)1974if ln == 0 {1975v = placeHolder1976}1977rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln))1978}1979case time.Time:1980b := []byte(v.Format(SQLiteTimestampFormats[0]))1981rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))1982}1983if rv != C.SQLITE_OK {1984return s.c.lastError()1985}1986}1987}1988return nil1989}
1990
1991// Query the statement with arguments. Return records.
1992func (s *SQLiteStmt) Query(args []driver.Value) (driver.Rows, error) {1993list := make([]driver.NamedValue, len(args))1994for i, v := range args {1995list[i] = driver.NamedValue{1996Ordinal: i + 1,1997Value: v,1998}1999}2000return s.query(context.Background(), list)2001}
2002
2003func (s *SQLiteStmt) query(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {2004if err := s.bind(args); err != nil {2005return nil, err2006}2007
2008rows := &SQLiteRows{2009s: s,2010nc: int(C.sqlite3_column_count(s.s)),2011cols: nil,2012decltype: nil,2013cls: s.cls,2014closed: false,2015ctx: ctx,2016}2017runtime.SetFinalizer(rows, (*SQLiteRows).Close)2018
2019return rows, nil2020}
2021
2022// LastInsertId return last inserted ID.
2023func (r *SQLiteResult) LastInsertId() (int64, error) {2024return r.id, nil2025}
2026
2027// RowsAffected return how many rows affected.
2028func (r *SQLiteResult) RowsAffected() (int64, error) {2029return r.changes, nil2030}
2031
2032// Exec execute the statement with arguments. Return result object.
2033func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {2034list := make([]driver.NamedValue, len(args))2035for i, v := range args {2036list[i] = driver.NamedValue{2037Ordinal: i + 1,2038Value: v,2039}2040}2041return s.exec(context.Background(), list)2042}
2043
2044func isInterruptErr(err error) bool {2045sqliteErr, ok := err.(Error)2046if ok {2047return sqliteErr.Code == ErrInterrupt2048}2049return false2050}
2051
2052// exec executes a query that doesn't return rows. Attempts to honor context timeout.
2053func (s *SQLiteStmt) exec(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {2054if ctx.Done() == nil {2055return s.execSync(args)2056}2057
2058type result struct {2059r driver.Result2060err error2061}2062resultCh := make(chan result)2063defer close(resultCh)2064go func() {2065r, err := s.execSync(args)2066resultCh <- result{r, err}2067}()2068var rv result2069select {2070case rv = <-resultCh:2071case <-ctx.Done():2072select {2073case rv = <-resultCh: // no need to interrupt, operation completed in db2074default:2075// this is still racy and can be no-op if executed between sqlite3_* calls in execSync.2076C.sqlite3_interrupt(s.c.db)2077rv = <-resultCh // wait for goroutine completed2078if isInterruptErr(rv.err) {2079return nil, ctx.Err()2080}2081}2082}2083return rv.r, rv.err2084}
2085
2086func (s *SQLiteStmt) execSync(args []driver.NamedValue) (driver.Result, error) {2087if err := s.bind(args); err != nil {2088C.sqlite3_reset(s.s)2089C.sqlite3_clear_bindings(s.s)2090return nil, err2091}2092
2093var rowid, changes C.longlong2094rv := C._sqlite3_step_row_internal(s.s, &rowid, &changes)2095if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {2096err := s.c.lastError()2097C.sqlite3_reset(s.s)2098C.sqlite3_clear_bindings(s.s)2099return nil, err2100}2101
2102return &SQLiteResult{id: int64(rowid), changes: int64(changes)}, nil2103}
2104
2105// Readonly reports if this statement is considered readonly by SQLite.
2106//
2107// See: https://sqlite.org/c3ref/stmt_readonly.html
2108func (s *SQLiteStmt) Readonly() bool {2109return C.sqlite3_stmt_readonly(s.s) == 12110}
2111
2112// Close the rows.
2113func (rc *SQLiteRows) Close() error {2114rc.s.mu.Lock()2115if rc.s.closed || rc.closed {2116rc.s.mu.Unlock()2117return nil2118}2119rc.closed = true2120if rc.cls {2121rc.s.mu.Unlock()2122return rc.s.Close()2123}2124rv := C.sqlite3_reset(rc.s.s)2125if rv != C.SQLITE_OK {2126rc.s.mu.Unlock()2127return rc.s.c.lastError()2128}2129rc.s.mu.Unlock()2130rc.s = nil2131runtime.SetFinalizer(rc, nil)2132return nil2133}
2134
2135// Columns return column names.
2136func (rc *SQLiteRows) Columns() []string {2137rc.s.mu.Lock()2138defer rc.s.mu.Unlock()2139if rc.s.s != nil && rc.nc != len(rc.cols) {2140rc.cols = make([]string, rc.nc)2141for i := 0; i < rc.nc; i++ {2142rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i)))2143}2144}2145return rc.cols2146}
2147
2148func (rc *SQLiteRows) declTypes() []string {2149if rc.s.s != nil && rc.decltype == nil {2150rc.decltype = make([]string, rc.nc)2151for i := 0; i < rc.nc; i++ {2152rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))2153}2154}2155return rc.decltype2156}
2157
2158// DeclTypes return column types.
2159func (rc *SQLiteRows) DeclTypes() []string {2160rc.s.mu.Lock()2161defer rc.s.mu.Unlock()2162return rc.declTypes()2163}
2164
2165// Next move cursor to next. Attempts to honor context timeout from QueryContext call.
2166func (rc *SQLiteRows) Next(dest []driver.Value) error {2167rc.s.mu.Lock()2168defer rc.s.mu.Unlock()2169
2170if rc.s.closed {2171return io.EOF2172}2173
2174if rc.ctx.Done() == nil {2175return rc.nextSyncLocked(dest)2176}2177resultCh := make(chan error)2178defer close(resultCh)2179go func() {2180resultCh <- rc.nextSyncLocked(dest)2181}()2182select {2183case err := <-resultCh:2184return err2185case <-rc.ctx.Done():2186select {2187case <-resultCh: // no need to interrupt2188default:2189// this is still racy and can be no-op if executed between sqlite3_* calls in nextSyncLocked.2190C.sqlite3_interrupt(rc.s.c.db)2191<-resultCh // ensure goroutine completed2192}2193return rc.ctx.Err()2194}2195}
2196
2197// nextSyncLocked moves cursor to next; must be called with locked mutex.
2198func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {2199rv := C._sqlite3_step_internal(rc.s.s)2200if rv == C.SQLITE_DONE {2201return io.EOF2202}2203if rv != C.SQLITE_ROW {2204rv = C.sqlite3_reset(rc.s.s)2205if rv != C.SQLITE_OK {2206return rc.s.c.lastError()2207}2208return nil2209}2210
2211rc.declTypes()2212
2213for i := range dest {2214switch C.sqlite3_column_type(rc.s.s, C.int(i)) {2215case C.SQLITE_INTEGER:2216val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))2217switch rc.decltype[i] {2218case columnTimestamp, columnDatetime, columnDate:2219var t time.Time2220// Assume a millisecond unix timestamp if it's 13 digits -- too2221// large to be a reasonable timestamp in seconds.2222if val > 1e12 || val < -1e12 {2223val *= int64(time.Millisecond) // convert ms to nsec2224t = time.Unix(0, val)2225} else {2226t = time.Unix(val, 0)2227}2228t = t.UTC()2229if rc.s.c.loc != nil {2230t = t.In(rc.s.c.loc)2231}2232dest[i] = t2233case "boolean":2234dest[i] = val > 02235default:2236dest[i] = val2237}2238case C.SQLITE_FLOAT:2239dest[i] = float64(C.sqlite3_column_double(rc.s.s, C.int(i)))2240case C.SQLITE_BLOB:2241p := C.sqlite3_column_blob(rc.s.s, C.int(i))2242if p == nil {2243dest[i] = []byte{}2244continue2245}2246n := C.sqlite3_column_bytes(rc.s.s, C.int(i))2247dest[i] = C.GoBytes(p, n)2248case C.SQLITE_NULL:2249dest[i] = nil2250case C.SQLITE_TEXT:2251var err error2252var timeVal time.Time2253
2254n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))2255s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))2256
2257switch rc.decltype[i] {2258case columnTimestamp, columnDatetime, columnDate:2259var t time.Time2260s = strings.TrimSuffix(s, "Z")2261for _, format := range SQLiteTimestampFormats {2262if timeVal, err = time.ParseInLocation(format, s, time.UTC); err == nil {2263t = timeVal2264break2265}2266}2267if err != nil {2268// The column is a time value, so return the zero time on parse failure.2269t = time.Time{}2270}2271if rc.s.c.loc != nil {2272t = t.In(rc.s.c.loc)2273}2274dest[i] = t2275default:2276dest[i] = s2277}2278}2279}2280return nil2281}
2282