summaryrefslogtreecommitdiff
path: root/vendor/modernc.org/sqlite
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/modernc.org/sqlite')
-rw-r--r--vendor/modernc.org/sqlite/AUTHORS3
-rw-r--r--vendor/modernc.org/sqlite/CONTRIBUTORS4
-rw-r--r--vendor/modernc.org/sqlite/README.md53
-rw-r--r--vendor/modernc.org/sqlite/dmesg.go56
-rw-r--r--vendor/modernc.org/sqlite/doc.go59
-rw-r--r--vendor/modernc.org/sqlite/lib/mutex.go8
-rw-r--r--vendor/modernc.org/sqlite/nodmesg.go12
-rw-r--r--vendor/modernc.org/sqlite/sqlite.go607
-rw-r--r--vendor/modernc.org/sqlite/sqlite_go18.go51
-rw-r--r--vendor/modernc.org/sqlite/unconvert.sh2
10 files changed, 736 insertions, 119 deletions
diff --git a/vendor/modernc.org/sqlite/AUTHORS b/vendor/modernc.org/sqlite/AUTHORS
index dae34d6bb..acff1e830 100644
--- a/vendor/modernc.org/sqlite/AUTHORS
+++ b/vendor/modernc.org/sqlite/AUTHORS
@@ -12,12 +12,13 @@ Artyom Pervukhin <github@artyom.dev>
Dan Peterson <danp@danp.net>
David Walton <david@davidwalton.com>
Davsk Ltd Co <skinner.david@gmail.com>
+FerretDB Inc.
Jaap Aarts <jaap.aarts1@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Josh Bleecher Snyder <josharian@gmail.com>
Logan Snow <logansnow@protonmail.com>
Michael Hoffmann <mhoffm@posteo.de>
+Michael Rykov <mrykov@gmail.com>
Ross Light <ross@zombiezen.com>
Saed SayedAhmed <saadmtsa@gmail.com>
Steffen Butzer <steffen(dot)butzer@outlook.com>
-Michael Rykov <mrykov@gmail.com>
diff --git a/vendor/modernc.org/sqlite/CONTRIBUTORS b/vendor/modernc.org/sqlite/CONTRIBUTORS
index 04e28754d..d025d2013 100644
--- a/vendor/modernc.org/sqlite/CONTRIBUTORS
+++ b/vendor/modernc.org/sqlite/CONTRIBUTORS
@@ -7,6 +7,7 @@
# Please keep the list sorted.
Alexander Menzhinsky <amenzhinsky@gmail.com>
+Alexey Palazhchenko <alexey.palazhchenko@gmail.com>
Artyom Pervukhin <github@artyom.dev>
Dan Peterson <danp@danp.net>
David Skinner <skinner.david@gmail.com>
@@ -20,8 +21,9 @@ Josh Bleecher Snyder <josharian@gmail.com>
Logan Snow <logansnow@protonmail.com>
Matthew Gabeler-Lee <fastcat@gmail.com>
Michael Hoffmann <mhoffm@posteo.de>
+Michael Rykov <mrykov@gmail.com>
Ross Light <ross@zombiezen.com>
Saed SayedAhmed <saadmtsa@gmail.com>
+Sean McGivern <sean@mcgivern.me.uk>
Steffen Butzer <steffen(dot)butzer@outlook.com>
Yaacov Akiba Slama <ya@slamail.org>
-Michael Rykov <mrykov@gmail.com>
diff --git a/vendor/modernc.org/sqlite/README.md b/vendor/modernc.org/sqlite/README.md
index a47f345f9..aa45ff87a 100644
--- a/vendor/modernc.org/sqlite/README.md
+++ b/vendor/modernc.org/sqlite/README.md
@@ -21,3 +21,56 @@ allowing one of the maintainers to work on it also in office hours.
## Builders
[modern-c.appspot.com/-/builder/?importpath=modernc.org%2fsqlite](https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fsqlite)
+
+## Speedtest1
+
+Numbers for the pure Go version were produced by
+
+ ~/src/modernc.org/sqlite/speedtest1$ go build && ./speedtest1
+
+Numbers for the pure C version were produced by
+
+ ~/src/modernc.org/sqlite/testdata/sqlite-src-3410200/test$ gcc speedtest1.c ../../sqlite-amalgamation-3410200/sqlite3.c -lpthread -ldl && ./a.out
+
+The results are from Go version 1.20.4 and GCC version 10.2.1 on a
+Linux/amd64 machine, CPU: AMD Ryzen 9 3900X 12-Core Processor × 24, 128GB
+RAM. Shown are the best of 3 runs.
+
+ Go C
+
+ -- Speedtest1 for SQLite 3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69 -- Speedtest1 for SQLite 3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69
+ 100 - 50000 INSERTs into table with no index...................... 0.071s 100 - 50000 INSERTs into table with no index...................... 0.077s
+ 110 - 50000 ordered INSERTS with one index/PK..................... 0.114s 110 - 50000 ordered INSERTS with one index/PK..................... 0.082s
+ 120 - 50000 unordered INSERTS with one index/PK................... 0.137s 120 - 50000 unordered INSERTS with one index/PK................... 0.099s
+ 130 - 25 SELECTS, numeric BETWEEN, unindexed...................... 0.083s 130 - 25 SELECTS, numeric BETWEEN, unindexed...................... 0.091s
+ 140 - 10 SELECTS, LIKE, unindexed................................. 0.210s 140 - 10 SELECTS, LIKE, unindexed................................. 0.120s
+ 142 - 10 SELECTS w/ORDER BY, unindexed............................ 0.276s 142 - 10 SELECTS w/ORDER BY, unindexed............................ 0.182s
+ 145 - 10 SELECTS w/ORDER BY and LIMIT, unindexed.................. 0.183s 145 - 10 SELECTS w/ORDER BY and LIMIT, unindexed.................. 0.099s
+ 150 - CREATE INDEX five times..................................... 0.172s 150 - CREATE INDEX five times..................................... 0.127s
+ 160 - 10000 SELECTS, numeric BETWEEN, indexed..................... 0.080s 160 - 10000 SELECTS, numeric BETWEEN, indexed..................... 0.078s
+ 161 - 10000 SELECTS, numeric BETWEEN, PK.......................... 0.080s 161 - 10000 SELECTS, numeric BETWEEN, PK.......................... 0.078s
+ 170 - 10000 SELECTS, text BETWEEN, indexed........................ 0.187s 170 - 10000 SELECTS, text BETWEEN, indexed........................ 0.169s
+ 180 - 50000 INSERTS with three indexes............................ 0.196s 180 - 50000 INSERTS with three indexes............................ 0.154s
+ 190 - DELETE and REFILL one table................................. 0.200s 190 - DELETE and REFILL one table................................. 0.155s
+ 200 - VACUUM...................................................... 0.180s 200 - VACUUM...................................................... 0.142s
+ 210 - ALTER TABLE ADD COLUMN, and query........................... 0.004s 210 - ALTER TABLE ADD COLUMN, and query........................... 0.005s
+ 230 - 10000 UPDATES, numeric BETWEEN, indexed..................... 0.093s 230 - 10000 UPDATES, numeric BETWEEN, indexed..................... 0.080s
+ 240 - 50000 UPDATES of individual rows............................ 0.153s 240 - 50000 UPDATES of individual rows............................ 0.137s
+ 250 - One big UPDATE of the whole 50000-row table................. 0.024s 250 - One big UPDATE of the whole 50000-row table................. 0.019s
+ 260 - Query added column after filling............................ 0.004s 260 - Query added column after filling............................ 0.005s
+ 270 - 10000 DELETEs, numeric BETWEEN, indexed..................... 0.278s 270 - 10000 DELETEs, numeric BETWEEN, indexed..................... 0.263s
+ 280 - 50000 DELETEs of individual rows............................ 0.188s 280 - 50000 DELETEs of individual rows............................ 0.180s
+ 290 - Refill two 50000-row tables using REPLACE................... 0.411s 290 - Refill two 50000-row tables using REPLACE................... 0.359s
+ 300 - Refill a 50000-row table using (b&1)==(a&1)................. 0.175s 300 - Refill a 50000-row table using (b&1)==(a&1)................. 0.151s
+ 310 - 10000 four-ways joins....................................... 0.427s 310 - 10000 four-ways joins....................................... 0.365s
+ 320 - subquery in result set...................................... 0.440s 320 - subquery in result set...................................... 0.521s
+ 400 - 70000 REPLACE ops on an IPK................................. 0.125s 400 - 70000 REPLACE ops on an IPK................................. 0.106s
+ 410 - 70000 SELECTS on an IPK..................................... 0.081s 410 - 70000 SELECTS on an IPK..................................... 0.078s
+ 500 - 70000 REPLACE on TEXT PK.................................... 0.174s 500 - 70000 REPLACE on TEXT PK.................................... 0.116s
+ 510 - 70000 SELECTS on a TEXT PK.................................. 0.153s 510 - 70000 SELECTS on a TEXT PK.................................. 0.117s
+ 520 - 70000 SELECT DISTINCT....................................... 0.083s 520 - 70000 SELECT DISTINCT....................................... 0.067s
+ 980 - PRAGMA integrity_check...................................... 0.436s 980 - PRAGMA integrity_check...................................... 0.377s
+ 990 - ANALYZE..................................................... 0.107s 990 - ANALYZE..................................................... 0.038s
+ TOTAL....................................................... 5.525s TOTAL....................................................... 4.637s
+
+This particular test executes 16.1% faster in the C version.
diff --git a/vendor/modernc.org/sqlite/dmesg.go b/vendor/modernc.org/sqlite/dmesg.go
new file mode 100644
index 000000000..5670301ef
--- /dev/null
+++ b/vendor/modernc.org/sqlite/dmesg.go
@@ -0,0 +1,56 @@
+// Copyright 2023 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build sqlite.dmesg
+// +build sqlite.dmesg
+
+package sqlite // import "modernc.org/sqlite"
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+const dmesgs = true
+
+var (
+ pid = fmt.Sprintf("[%v %v] ", os.Getpid(), filepath.Base(os.Args[0]))
+ logf *os.File
+)
+
+func init() {
+ t := time.Now()
+ // 01/02 03:04:05PM '06 -0700
+ dn := t.Format("sqlite-dmesg-2006-01-02-03-150405")
+ dn = filepath.Join(os.TempDir(), fmt.Sprintf("%s.%d", dn, os.Getpid()))
+ if err := os.Mkdir(dn, 0770); err != nil {
+ panic(err.Error())
+ }
+
+ fn := filepath.Join(dn, "dmesg.log")
+ var err error
+ if logf, err = os.OpenFile(fn, os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_SYNC, 0644); err != nil {
+ panic(err.Error())
+ }
+
+ dmesg("%v", time.Now())
+ fmt.Fprintf(os.Stderr, "debug messages in %s\n", fn)
+}
+
+func dmesg(s string, args ...interface{}) {
+ if s == "" {
+ s = strings.Repeat("%v ", len(args))
+ }
+ s = fmt.Sprintf(pid+s, args...)
+ s += fmt.Sprintf(" (%v: %v:)", origin(3), origin(2))
+ switch {
+ case len(s) != 0 && s[len(s)-1] == '\n':
+ fmt.Fprint(logf, s)
+ default:
+ fmt.Fprintln(logf, s)
+ }
+}
diff --git a/vendor/modernc.org/sqlite/doc.go b/vendor/modernc.org/sqlite/doc.go
index 04a7887a6..d572e1eb8 100644
--- a/vendor/modernc.org/sqlite/doc.go
+++ b/vendor/modernc.org/sqlite/doc.go
@@ -35,12 +35,69 @@
//
// Builders
//
-// Builder results available at
+// Builder results available at:
//
// https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fsqlite
//
+// Speedtest1
+//
+// Numbers for the pure Go version were produced by
+//
+// ~/src/modernc.org/sqlite/speedtest1$ go build && ./speedtest1
+//
+// Numbers for the pure C version were produced by
+//
+// ~/src/modernc.org/sqlite/testdata/sqlite-src-3410200/test$ gcc speedtest1.c ../../sqlite-amalgamation-3410200/sqlite3.c -lpthread -ldl && ./a.out
+//
+// The results are from Go version 1.20.4 and GCC version 10.2.1 on a
+// Linux/amd64 machine, CPU: AMD Ryzen 9 3900X 12-Core Processor × 24, 128GB
+// RAM. Shown are the best of 3 runs.
+//
+// Go C
+//
+// -- Speedtest1 for SQLite 3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69 -- Speedtest1 for SQLite 3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69
+// 100 - 50000 INSERTs into table with no index...................... 0.071s 100 - 50000 INSERTs into table with no index...................... 0.077s
+// 110 - 50000 ordered INSERTS with one index/PK..................... 0.114s 110 - 50000 ordered INSERTS with one index/PK..................... 0.082s
+// 120 - 50000 unordered INSERTS with one index/PK................... 0.137s 120 - 50000 unordered INSERTS with one index/PK................... 0.099s
+// 130 - 25 SELECTS, numeric BETWEEN, unindexed...................... 0.083s 130 - 25 SELECTS, numeric BETWEEN, unindexed...................... 0.091s
+// 140 - 10 SELECTS, LIKE, unindexed................................. 0.210s 140 - 10 SELECTS, LIKE, unindexed................................. 0.120s
+// 142 - 10 SELECTS w/ORDER BY, unindexed............................ 0.276s 142 - 10 SELECTS w/ORDER BY, unindexed............................ 0.182s
+// 145 - 10 SELECTS w/ORDER BY and LIMIT, unindexed.................. 0.183s 145 - 10 SELECTS w/ORDER BY and LIMIT, unindexed.................. 0.099s
+// 150 - CREATE INDEX five times..................................... 0.172s 150 - CREATE INDEX five times..................................... 0.127s
+// 160 - 10000 SELECTS, numeric BETWEEN, indexed..................... 0.080s 160 - 10000 SELECTS, numeric BETWEEN, indexed..................... 0.078s
+// 161 - 10000 SELECTS, numeric BETWEEN, PK.......................... 0.080s 161 - 10000 SELECTS, numeric BETWEEN, PK.......................... 0.078s
+// 170 - 10000 SELECTS, text BETWEEN, indexed........................ 0.187s 170 - 10000 SELECTS, text BETWEEN, indexed........................ 0.169s
+// 180 - 50000 INSERTS with three indexes............................ 0.196s 180 - 50000 INSERTS with three indexes............................ 0.154s
+// 190 - DELETE and REFILL one table................................. 0.200s 190 - DELETE and REFILL one table................................. 0.155s
+// 200 - VACUUM...................................................... 0.180s 200 - VACUUM...................................................... 0.142s
+// 210 - ALTER TABLE ADD COLUMN, and query........................... 0.004s 210 - ALTER TABLE ADD COLUMN, and query........................... 0.005s
+// 230 - 10000 UPDATES, numeric BETWEEN, indexed..................... 0.093s 230 - 10000 UPDATES, numeric BETWEEN, indexed..................... 0.080s
+// 240 - 50000 UPDATES of individual rows............................ 0.153s 240 - 50000 UPDATES of individual rows............................ 0.137s
+// 250 - One big UPDATE of the whole 50000-row table................. 0.024s 250 - One big UPDATE of the whole 50000-row table................. 0.019s
+// 260 - Query added column after filling............................ 0.004s 260 - Query added column after filling............................ 0.005s
+// 270 - 10000 DELETEs, numeric BETWEEN, indexed..................... 0.278s 270 - 10000 DELETEs, numeric BETWEEN, indexed..................... 0.263s
+// 280 - 50000 DELETEs of individual rows............................ 0.188s 280 - 50000 DELETEs of individual rows............................ 0.180s
+// 290 - Refill two 50000-row tables using REPLACE................... 0.411s 290 - Refill two 50000-row tables using REPLACE................... 0.359s
+// 300 - Refill a 50000-row table using (b&1)==(a&1)................. 0.175s 300 - Refill a 50000-row table using (b&1)==(a&1)................. 0.151s
+// 310 - 10000 four-ways joins....................................... 0.427s 310 - 10000 four-ways joins....................................... 0.365s
+// 320 - subquery in result set...................................... 0.440s 320 - subquery in result set...................................... 0.521s
+// 400 - 70000 REPLACE ops on an IPK................................. 0.125s 400 - 70000 REPLACE ops on an IPK................................. 0.106s
+// 410 - 70000 SELECTS on an IPK..................................... 0.081s 410 - 70000 SELECTS on an IPK..................................... 0.078s
+// 500 - 70000 REPLACE on TEXT PK.................................... 0.174s 500 - 70000 REPLACE on TEXT PK.................................... 0.116s
+// 510 - 70000 SELECTS on a TEXT PK.................................. 0.153s 510 - 70000 SELECTS on a TEXT PK.................................. 0.117s
+// 520 - 70000 SELECT DISTINCT....................................... 0.083s 520 - 70000 SELECT DISTINCT....................................... 0.067s
+// 980 - PRAGMA integrity_check...................................... 0.436s 980 - PRAGMA integrity_check...................................... 0.377s
+// 990 - ANALYZE..................................................... 0.107s 990 - ANALYZE..................................................... 0.038s
+// TOTAL....................................................... 5.525s TOTAL....................................................... 4.637s
+//
+// This particular test executes 16.1% faster in the C version.
+//
// Changelog
//
+// 2023-06-01 v1.23.0:
+//
+// Allow registering aggregate functions
+//
// 2023-04-22 v1.22.0:
//
// Support linux/s390x.
diff --git a/vendor/modernc.org/sqlite/lib/mutex.go b/vendor/modernc.org/sqlite/lib/mutex.go
index be44263ae..4dd679a36 100644
--- a/vendor/modernc.org/sqlite/lib/mutex.go
+++ b/vendor/modernc.org/sqlite/lib/mutex.go
@@ -92,13 +92,17 @@ func mutexFromPtr(p uintptr) *mutex {
if p == 0 {
return nil
}
+
ix := p - 1
+
+ mutexes.Lock()
+ defer mutexes.Unlock()
+
return &mutexes.a[ix>>8][ix&255]
}
func (m *mutexPool) alloc(recursive bool) uintptr {
m.Lock()
-
defer m.Unlock()
n := len(m.freeList)
@@ -124,8 +128,8 @@ func (m *mutexPool) free(p uintptr) {
ptr := mutexFromPtr(p)
ix := ptr.poolIndex
*ptr = mutex{}
- m.Lock()
+ m.Lock()
defer m.Unlock()
m.freeList = append(m.freeList, ix)
diff --git a/vendor/modernc.org/sqlite/nodmesg.go b/vendor/modernc.org/sqlite/nodmesg.go
new file mode 100644
index 000000000..f78313461
--- /dev/null
+++ b/vendor/modernc.org/sqlite/nodmesg.go
@@ -0,0 +1,12 @@
+// Copyright 2023 The Sqlite Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !sqlite.dmesg
+// +build !sqlite.dmesg
+
+package sqlite // import "modernc.org/sqlite"
+
+const dmesgs = false
+
+func dmesg(s string, args ...interface{}) {}
diff --git a/vendor/modernc.org/sqlite/sqlite.go b/vendor/modernc.org/sqlite/sqlite.go
index 61826cd0f..4dd876f80 100644
--- a/vendor/modernc.org/sqlite/sqlite.go
+++ b/vendor/modernc.org/sqlite/sqlite.go
@@ -10,11 +10,14 @@ import (
"context"
"database/sql"
"database/sql/driver"
+ "errors"
"fmt"
"io"
"math"
+ "math/bits"
"net/url"
"reflect"
+ "runtime"
"strconv"
"strings"
"sync"
@@ -1319,7 +1322,12 @@ func (c *conn) errstr(rc int32) error {
// Begin starts a transaction.
//
// Deprecated: Drivers should implement ConnBeginTx instead (or additionally).
-func (c *conn) Begin() (driver.Tx, error) {
+func (c *conn) Begin() (dt driver.Tx, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p: (driver.Tx %p, err %v)", c, dt, err)
+ }()
+ }
return c.begin(context.Background(), driver.TxOptions{})
}
@@ -1333,7 +1341,12 @@ func (c *conn) begin(ctx context.Context, opts driver.TxOptions) (t driver.Tx, e
// Because the sql package maintains a free pool of connections and only calls
// Close when there's a surplus of idle connections, it shouldn't be necessary
// for drivers to do their own connection caching.
-func (c *conn) Close() error {
+func (c *conn) Close() (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p: err %v", c, err)
+ }()
+ }
c.Lock() // Defend against race with .interrupt invoked by context handling.
defer c.Unlock()
@@ -1362,27 +1375,106 @@ func (c *conn) closeV2(db uintptr) error {
return nil
}
+// FunctionImpl describes an [application-defined SQL function]. If Scalar is
+// set, it is treated as a scalar function; otherwise, it is treated as an
+// aggregate function using MakeAggregate.
+//
+// [application-defined SQL function]: https://sqlite.org/appfunc.html
+type FunctionImpl struct {
+ // NArgs is the required number of arguments that the function accepts.
+ // If NArgs is negative, then the function is variadic.
+ NArgs int32
+
+ // If Deterministic is true, the function must always give the same
+ // output when the input parameters are the same. This enables functions
+ // to be used in additional contexts like the WHERE clause of partial
+ // indexes and enables additional optimizations.
+ //
+ // See https://sqlite.org/c3ref/c_deterministic.html#sqlitedeterministic
+ // for more details.
+ Deterministic bool
+
+ // Scalar is called when a scalar function is invoked in SQL. The
+ // argument Values are not valid past the return of the function.
+ Scalar func(ctx *FunctionContext, args []driver.Value) (driver.Value, error)
+
+ // MakeAggregate is called at the beginning of each evaluation of an
+ // aggregate function.
+ MakeAggregate func(ctx FunctionContext) (AggregateFunction, error)
+}
+
+// An AggregateFunction is an invocation of an aggregate or window function. See
+// the documentation for [aggregate function callbacks] and [application-defined
+// window functions] for an overview.
+//
+// [aggregate function callbacks]: https://www.sqlite.org/appfunc.html#the_aggregate_function_callbacks
+// [application-defined window functions]: https://www.sqlite.org/windowfunctions.html#user_defined_aggregate_window_functions
+type AggregateFunction interface {
+ // Step is called for each row of an aggregate function's SQL
+ // invocation. The argument Values are not valid past the return of the
+ // function.
+ Step(ctx *FunctionContext, rowArgs []driver.Value) error
+
+ // WindowInverse is called to remove the oldest presently aggregated
+ // result of Step from the current window. The arguments are those
+ // passed to Step for the row being removed. The argument Values are not
+ // valid past the return of the function.
+ WindowInverse(ctx *FunctionContext, rowArgs []driver.Value) error
+
+ // WindowValue is called to get the current value of an aggregate
+ // function. This is used to return the final value of the function,
+ // whether it is used as a window function or not.
+ WindowValue(ctx *FunctionContext) (driver.Value, error)
+
+ // Final is called after all of the aggregate function's input rows have
+ // been stepped through. No other methods will be called on the
+ // AggregateFunction after calling Final. WindowValue returns the value
+ // from the function.
+ Final(ctx *FunctionContext)
+}
+
type userDefinedFunction struct {
zFuncName uintptr
nArg int32
eTextRep int32
- xFunc func(*libc.TLS, uintptr, int32, uintptr)
+ pApp uintptr
+ scalar bool
freeOnce sync.Once
}
func (c *conn) createFunctionInternal(fun *userDefinedFunction) error {
- if rc := sqlite3.Xsqlite3_create_function(
- c.tls,
- c.db,
- fun.zFuncName,
- fun.nArg,
- fun.eTextRep,
- 0,
- *(*uintptr)(unsafe.Pointer(&fun.xFunc)),
- 0,
- 0,
- ); rc != sqlite3.SQLITE_OK {
+ var rc int32
+
+ if fun.scalar {
+ rc = sqlite3.Xsqlite3_create_function(
+ c.tls,
+ c.db,
+ fun.zFuncName,
+ fun.nArg,
+ fun.eTextRep,
+ fun.pApp,
+ cFuncPointer(funcTrampoline),
+ 0,
+ 0,
+ )
+ } else {
+ rc = sqlite3.Xsqlite3_create_window_function(
+ c.tls,
+ c.db,
+ fun.zFuncName,
+ fun.nArg,
+ fun.eTextRep,
+ fun.pApp,
+ cFuncPointer(stepTrampoline),
+ cFuncPointer(finalTrampoline),
+ cFuncPointer(valueTrampoline),
+ cFuncPointer(inverseTrampoline),
+ 0,
+ )
+ }
+
+ if rc != sqlite3.SQLITE_OK {
return c.errstr(rc)
}
return nil
@@ -1396,7 +1488,12 @@ func (c *conn) createFunctionInternal(fun *userDefinedFunction) error {
// Exec may return ErrSkip.
//
// Deprecated: Drivers should implement ExecerContext instead.
-func (c *conn) Exec(query string, args []driver.Value) (driver.Result, error) {
+func (c *conn) Exec(query string, args []driver.Value) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q, args %v: (driver.Result %p, err %v)", c, query, args, dr, err)
+ }()
+ }
return c.exec(context.Background(), query, toNamedValues(args))
}
@@ -1416,7 +1513,12 @@ func (c *conn) exec(ctx context.Context, query string, args []driver.NamedValue)
}
// Prepare returns a prepared statement, bound to this connection.
-func (c *conn) Prepare(query string) (driver.Stmt, error) {
+func (c *conn) Prepare(query string) (ds driver.Stmt, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q: (driver.Stmt %p, err %v)", c, query, ds, err)
+ }()
+ }
return c.prepare(context.Background(), query)
}
@@ -1433,7 +1535,12 @@ func (c *conn) prepare(ctx context.Context, query string) (s driver.Stmt, err er
// Query may return ErrSkip.
//
// Deprecated: Drivers should implement QueryerContext instead.
-func (c *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
+func (c *conn) Query(query string, args []driver.Value) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, query %q, args %v: (driver.Rows %p, err %v)", c, query, args, dr, err)
+ }()
+ }
return c.query(context.Background(), query, toNamedValues(args))
}
@@ -1491,7 +1598,12 @@ func newDriver() *Driver { return d }
// not specify one, which SQLite maps to "deferred". More information is
// available at
// https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
-func (d *Driver) Open(name string) (driver.Conn, error) {
+func (d *Driver) Open(name string) (conn driver.Conn, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("name %q: (driver.Conn %p, err %v)", name, conn, err)
+ }()
+ }
c, err := newConn(name)
if err != nil {
return nil, err
@@ -1508,10 +1620,38 @@ func (d *Driver) Open(name string) (driver.Conn, error) {
// FunctionContext represents the context user defined functions execute in.
// Fields and/or methods of this type may get addedd in the future.
-type FunctionContext struct{}
+type FunctionContext struct {
+ tls *libc.TLS
+ ctx uintptr
+}
const sqliteValPtrSize = unsafe.Sizeof(&sqlite3.Sqlite3_value{})
+// RegisterFunction registers a function named zFuncName with nArg arguments.
+// Passing -1 for nArg indicates the function is variadic. The FunctionImpl
+// determines whether the function is deterministic or not, and whether it is a
+// scalar function (when Scalar is defined) or an aggregate function (when
+// Scalar is not defined and MakeAggregate is defined).
+//
+// The new function will be available to all new connections opened after
+// executing RegisterFunction.
+func RegisterFunction(
+ zFuncName string,
+ impl *FunctionImpl,
+) error {
+ return registerFunction(zFuncName, impl)
+}
+
+// MustRegisterFunction is like RegisterFunction but panics on error.
+func MustRegisterFunction(
+ zFuncName string,
+ impl *FunctionImpl,
+) {
+ if err := RegisterFunction(zFuncName, impl); err != nil {
+ panic(err)
+ }
+}
+
// RegisterScalarFunction registers a scalar function named zFuncName with nArg
// arguments. Passing -1 for nArg indicates the function is variadic.
//
@@ -1521,8 +1661,13 @@ func RegisterScalarFunction(
zFuncName string,
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
-) error {
- return registerScalarFunction(zFuncName, nArg, sqlite3.SQLITE_UTF8, xFunc)
+) (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("zFuncName %q, nArg %v, xFunc %p: err %v", zFuncName, nArg, xFunc, err)
+ }()
+ }
+ return registerFunction(zFuncName, &FunctionImpl{NArgs: nArg, Scalar: xFunc, Deterministic: false})
}
// MustRegisterScalarFunction is like RegisterScalarFunction but panics on
@@ -1532,6 +1677,9 @@ func MustRegisterScalarFunction(
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) {
+ if dmesgs {
+ dmesg("zFuncName %q, nArg %v, xFunc %p", zFuncName, nArg, xFunc)
+ }
if err := RegisterScalarFunction(zFuncName, nArg, xFunc); err != nil {
panic(err)
}
@@ -1544,6 +1692,9 @@ func MustRegisterDeterministicScalarFunction(
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) {
+ if dmesgs {
+ dmesg("zFuncName %q, nArg %v, xFunc %p", zFuncName, nArg, xFunc)
+ }
if err := RegisterDeterministicScalarFunction(zFuncName, nArg, xFunc); err != nil {
panic(err)
}
@@ -1560,15 +1711,18 @@ func RegisterDeterministicScalarFunction(
zFuncName string,
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
-) error {
- return registerScalarFunction(zFuncName, nArg, sqlite3.SQLITE_UTF8|sqlite3.SQLITE_DETERMINISTIC, xFunc)
+) (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("zFuncName %q, nArg %v, xFunc %p: err %v", zFuncName, nArg, xFunc, err)
+ }()
+ }
+ return registerFunction(zFuncName, &FunctionImpl{NArgs: nArg, Scalar: xFunc, Deterministic: true})
}
-func registerScalarFunction(
+func registerFunction(
zFuncName string,
- nArg int32,
- eTextRep int32,
- xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
+ impl *FunctionImpl,
) error {
if _, ok := d.udfs[zFuncName]; ok {
@@ -1581,91 +1735,334 @@ func registerScalarFunction(
return err
}
+ var textrep int32 = sqlite3.SQLITE_UTF8
+
+ if impl.Deterministic {
+ textrep |= sqlite3.SQLITE_DETERMINISTIC
+ }
+
udf := &userDefinedFunction{
zFuncName: name,
- nArg: nArg,
- eTextRep: eTextRep,
- xFunc: func(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
- setErrorResult := func(res error) {
- errmsg, cerr := libc.CString(res.Error())
- if cerr != nil {
- panic(cerr)
- }
- defer libc.Xfree(tls, errmsg)
- sqlite3.Xsqlite3_result_error(tls, ctx, errmsg, -1)
- sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
- }
+ nArg: impl.NArgs,
+ eTextRep: textrep,
+ }
- args := make([]driver.Value, argc)
- for i := int32(0); i < argc; i++ {
- valPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(i)*sqliteValPtrSize))
-
- switch valType := sqlite3.Xsqlite3_value_type(tls, valPtr); valType {
- case sqlite3.SQLITE_TEXT:
- args[i] = libc.GoString(sqlite3.Xsqlite3_value_text(tls, valPtr))
- case sqlite3.SQLITE_INTEGER:
- args[i] = sqlite3.Xsqlite3_value_int64(tls, valPtr)
- case sqlite3.SQLITE_FLOAT:
- args[i] = sqlite3.Xsqlite3_value_double(tls, valPtr)
- case sqlite3.SQLITE_NULL:
- args[i] = nil
- case sqlite3.SQLITE_BLOB:
- size := sqlite3.Xsqlite3_value_bytes(tls, valPtr)
- blobPtr := sqlite3.Xsqlite3_value_blob(tls, valPtr)
- v := make([]byte, size)
- copy(v, (*libc.RawMem)(unsafe.Pointer(blobPtr))[:size:size])
- args[i] = v
- default:
- panic(fmt.Sprintf("unexpected argument type %q passed by sqlite", valType))
- }
- }
+ if impl.Scalar != nil {
+ xFuncs.mu.Lock()
+ id := xFuncs.ids.next()
+ xFuncs.m[id] = impl.Scalar
+ xFuncs.mu.Unlock()
- res, err := xFunc(&FunctionContext{}, args)
- if err != nil {
- setErrorResult(err)
- return
- }
+ udf.scalar = true
+ udf.pApp = id
+ } else {
+ xAggregateFactories.mu.Lock()
+ id := xAggregateFactories.ids.next()
+ xAggregateFactories.m[id] = impl.MakeAggregate
+ xAggregateFactories.mu.Unlock()
- switch resTyped := res.(type) {
- case nil:
- sqlite3.Xsqlite3_result_null(tls, ctx)
- case int64:
- sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped)
- case float64:
- sqlite3.Xsqlite3_result_double(tls, ctx, resTyped)
- case bool:
- sqlite3.Xsqlite3_result_int(tls, ctx, libc.Bool32(resTyped))
- case time.Time:
- sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped.Unix())
- case string:
- size := int32(len(resTyped))
- cstr, err := libc.CString(resTyped)
- if err != nil {
- panic(err)
- }
- defer libc.Xfree(tls, cstr)
- sqlite3.Xsqlite3_result_text(tls, ctx, cstr, size, sqlite3.SQLITE_TRANSIENT)
- case []byte:
- size := int32(len(resTyped))
- if size == 0 {
- sqlite3.Xsqlite3_result_zeroblob(tls, ctx, 0)
- return
- }
- p := libc.Xmalloc(tls, types.Size_t(size))
- if p == 0 {
- panic(fmt.Sprintf("unable to allocate space for blob: %d", size))
- }
- defer libc.Xfree(tls, p)
- copy((*libc.RawMem)(unsafe.Pointer(p))[:size:size], resTyped)
-
- sqlite3.Xsqlite3_result_blob(tls, ctx, p, size, sqlite3.SQLITE_TRANSIENT)
- default:
- setErrorResult(fmt.Errorf("function did not return a valid driver.Value: %T", resTyped))
- return
- }
- },
+ udf.pApp = id
}
+
d.udfs[zFuncName] = udf
return nil
}
+
+func origin(skip int) string {
+ pc, fn, fl, _ := runtime.Caller(skip)
+ f := runtime.FuncForPC(pc)
+ var fns string
+ if f != nil {
+ fns = f.Name()
+ if x := strings.LastIndex(fns, "."); x > 0 {
+ fns = fns[x+1:]
+ }
+ }
+ return fmt.Sprintf("%s:%d:%s", fn, fl, fns)
+}
+
+func errorResultFunction(tls *libc.TLS, ctx uintptr) func(error) {
+ return func(res error) {
+ errmsg, cerr := libc.CString(res.Error())
+ if cerr != nil {
+ panic(cerr)
+ }
+ defer libc.Xfree(tls, errmsg)
+ sqlite3.Xsqlite3_result_error(tls, ctx, errmsg, -1)
+ sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
+ }
+}
+
+func functionArgs(tls *libc.TLS, argc int32, argv uintptr) []driver.Value {
+ args := make([]driver.Value, argc)
+ for i := int32(0); i < argc; i++ {
+ valPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(i)*sqliteValPtrSize))
+
+ switch valType := sqlite3.Xsqlite3_value_type(tls, valPtr); valType {
+ case sqlite3.SQLITE_TEXT:
+ args[i] = libc.GoString(sqlite3.Xsqlite3_value_text(tls, valPtr))
+ case sqlite3.SQLITE_INTEGER:
+ args[i] = sqlite3.Xsqlite3_value_int64(tls, valPtr)
+ case sqlite3.SQLITE_FLOAT:
+ args[i] = sqlite3.Xsqlite3_value_double(tls, valPtr)
+ case sqlite3.SQLITE_NULL:
+ args[i] = nil
+ case sqlite3.SQLITE_BLOB:
+ size := sqlite3.Xsqlite3_value_bytes(tls, valPtr)
+ blobPtr := sqlite3.Xsqlite3_value_blob(tls, valPtr)
+ v := make([]byte, size)
+ copy(v, (*libc.RawMem)(unsafe.Pointer(blobPtr))[:size:size])
+ args[i] = v
+ default:
+ panic(fmt.Sprintf("unexpected argument type %q passed by sqlite", valType))
+ }
+ }
+
+ return args
+}
+
+func functionReturnValue(tls *libc.TLS, ctx uintptr, res driver.Value) error {
+ switch resTyped := res.(type) {
+ case nil:
+ sqlite3.Xsqlite3_result_null(tls, ctx)
+ case int64:
+ sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped)
+ case float64:
+ sqlite3.Xsqlite3_result_double(tls, ctx, resTyped)
+ case bool:
+ sqlite3.Xsqlite3_result_int(tls, ctx, libc.Bool32(resTyped))
+ case time.Time:
+ sqlite3.Xsqlite3_result_int64(tls, ctx, resTyped.Unix())
+ case string:
+ size := int32(len(resTyped))
+ cstr, err := libc.CString(resTyped)
+ if err != nil {
+ panic(err)
+ }
+ defer libc.Xfree(tls, cstr)
+ sqlite3.Xsqlite3_result_text(tls, ctx, cstr, size, sqlite3.SQLITE_TRANSIENT)
+ case []byte:
+ size := int32(len(resTyped))
+ if size == 0 {
+ sqlite3.Xsqlite3_result_zeroblob(tls, ctx, 0)
+ return nil
+ }
+ p := libc.Xmalloc(tls, types.Size_t(size))
+ if p == 0 {
+ panic(fmt.Sprintf("unable to allocate space for blob: %d", size))
+ }
+ defer libc.Xfree(tls, p)
+ copy((*libc.RawMem)(unsafe.Pointer(p))[:size:size], resTyped)
+
+ sqlite3.Xsqlite3_result_blob(tls, ctx, p, size, sqlite3.SQLITE_TRANSIENT)
+ default:
+ return fmt.Errorf("function did not return a valid driver.Value: %T", resTyped)
+ }
+
+ return nil
+}
+
+// The below is all taken from zombiezen.com/go/sqlite. Aggregate functions need
+// to maintain state (for instance, the count of values seen so far). We give
+// each aggregate function an ID, generated by idGen, and put that in the pApp
+// argument to sqlite3_create_function. We track this on the Go side in
+// xAggregateFactories.
+//
+// When (if) the function is called is called by a query, we call the
+// MakeAggregate factory function to set it up, and track that in
+// xAggregateContext, retrieving it via sqlite3_aggregate_context.
+//
+// We also need to ensure that, for both aggregate and scalar functions, the
+// function pointer we pass to SQLite meets certain rules on the Go side, so
+// that the pointer remains valid.
+var (
+ xFuncs = struct {
+ mu sync.RWMutex
+ m map[uintptr]func(*FunctionContext, []driver.Value) (driver.Value, error)
+ ids idGen
+ }{
+ m: make(map[uintptr]func(*FunctionContext, []driver.Value) (driver.Value, error)),
+ }
+
+ xAggregateFactories = struct {
+ mu sync.RWMutex
+ m map[uintptr]func(FunctionContext) (AggregateFunction, error)
+ ids idGen
+ }{
+ m: make(map[uintptr]func(FunctionContext) (AggregateFunction, error)),
+ }
+
+ xAggregateContext = struct {
+ mu sync.RWMutex
+ m map[uintptr]AggregateFunction
+ ids idGen
+ }{
+ m: make(map[uintptr]AggregateFunction),
+ }
+)
+
+type idGen struct {
+ bitset []uint64
+}
+
+func (gen *idGen) next() uintptr {
+ base := uintptr(1)
+ for i := 0; i < len(gen.bitset); i, base = i+1, base+64 {
+ b := gen.bitset[i]
+ if b != 1<<64-1 {
+ n := uintptr(bits.TrailingZeros64(^b))
+ gen.bitset[i] |= 1 << n
+ return base + n
+ }
+ }
+ gen.bitset = append(gen.bitset, 1)
+ return base
+}
+
+func (gen *idGen) reclaim(id uintptr) {
+ bit := id - 1
+ gen.bitset[bit/64] &^= 1 << (bit % 64)
+}
+
+func makeAggregate(tls *libc.TLS, ctx uintptr) (AggregateFunction, uintptr) {
+ goCtx := FunctionContext{tls: tls, ctx: ctx}
+ aggCtx := (*uintptr)(unsafe.Pointer(sqlite3.Xsqlite3_aggregate_context(tls, ctx, int32(ptrSize))))
+ setErrorResult := errorResultFunction(tls, ctx)
+ if aggCtx == nil {
+ setErrorResult(errors.New("insufficient memory for aggregate"))
+ return nil, 0
+ }
+ if *aggCtx != 0 {
+ // Already created.
+ xAggregateContext.mu.RLock()
+ f := xAggregateContext.m[*aggCtx]
+ xAggregateContext.mu.RUnlock()
+ return f, *aggCtx
+ }
+
+ factoryID := sqlite3.Xsqlite3_user_data(tls, ctx)
+ xAggregateFactories.mu.RLock()
+ factory := xAggregateFactories.m[factoryID]
+ xAggregateFactories.mu.RUnlock()
+
+ f, err := factory(goCtx)
+ if err != nil {
+ setErrorResult(err)
+ return nil, 0
+ }
+ if f == nil {
+ setErrorResult(errors.New("MakeAggregate function returned nil"))
+ return nil, 0
+ }
+
+ xAggregateContext.mu.Lock()
+ *aggCtx = xAggregateContext.ids.next()
+ xAggregateContext.m[*aggCtx] = f
+ xAggregateContext.mu.Unlock()
+ return f, *aggCtx
+}
+
+// cFuncPointer converts a function defined by a function declaration to a C pointer.
+// The result of using cFuncPointer on closures is undefined.
+func cFuncPointer[T any](f T) uintptr {
+ // This assumes the memory representation described in https://golang.org/s/go11func.
+ //
+ // cFuncPointer does its conversion by doing the following in order:
+ // 1) Create a Go struct containing a pointer to a pointer to
+ // the function. It is assumed that the pointer to the function will be
+ // stored in the read-only data section and thus will not move.
+ // 2) Convert the pointer to the Go struct to a pointer to uintptr through
+ // unsafe.Pointer. This is permitted via Rule #1 of unsafe.Pointer.
+ // 3) Dereference the pointer to uintptr to obtain the function value as a
+ // uintptr. This is safe as long as function values are passed as pointers.
+ return *(*uintptr)(unsafe.Pointer(&struct{ f T }{f}))
+}
+
+func funcTrampoline(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
+ id := sqlite3.Xsqlite3_user_data(tls, ctx)
+ xFuncs.mu.RLock()
+ xFunc := xFuncs.m[id]
+ xFuncs.mu.RUnlock()
+
+ setErrorResult := errorResultFunction(tls, ctx)
+ res, err := xFunc(&FunctionContext{}, functionArgs(tls, argc, argv))
+
+ if err != nil {
+ setErrorResult(err)
+ return
+ }
+
+ err = functionReturnValue(tls, ctx, res)
+ if err != nil {
+ setErrorResult(err)
+ }
+}
+
+func stepTrampoline(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
+ impl, _ := makeAggregate(tls, ctx)
+ if impl == nil {
+ return
+ }
+
+ setErrorResult := errorResultFunction(tls, ctx)
+ err := impl.Step(&FunctionContext{}, functionArgs(tls, argc, argv))
+ if err != nil {
+ setErrorResult(err)
+ }
+}
+
+func inverseTrampoline(tls *libc.TLS, ctx uintptr, argc int32, argv uintptr) {
+ impl, _ := makeAggregate(tls, ctx)
+ if impl == nil {
+ return
+ }
+
+ setErrorResult := errorResultFunction(tls, ctx)
+ err := impl.WindowInverse(&FunctionContext{}, functionArgs(tls, argc, argv))
+ if err != nil {
+ setErrorResult(err)
+ }
+}
+
+func valueTrampoline(tls *libc.TLS, ctx uintptr) {
+ impl, _ := makeAggregate(tls, ctx)
+ if impl == nil {
+ return
+ }
+
+ setErrorResult := errorResultFunction(tls, ctx)
+ res, err := impl.WindowValue(&FunctionContext{})
+ if err != nil {
+ setErrorResult(err)
+ } else {
+ err = functionReturnValue(tls, ctx, res)
+ if err != nil {
+ setErrorResult(err)
+ }
+ }
+}
+
+func finalTrampoline(tls *libc.TLS, ctx uintptr) {
+ impl, id := makeAggregate(tls, ctx)
+ if impl == nil {
+ return
+ }
+
+ setErrorResult := errorResultFunction(tls, ctx)
+ res, err := impl.WindowValue(&FunctionContext{})
+ if err != nil {
+ setErrorResult(err)
+ } else {
+ err = functionReturnValue(tls, ctx, res)
+ if err != nil {
+ setErrorResult(err)
+ }
+ }
+ impl.Final(&FunctionContext{})
+
+ xAggregateContext.mu.Lock()
+ defer xAggregateContext.mu.Unlock()
+ delete(xAggregateContext.m, id)
+ xAggregateContext.ids.reclaim(id)
+}
diff --git a/vendor/modernc.org/sqlite/sqlite_go18.go b/vendor/modernc.org/sqlite/sqlite_go18.go
index 474d00271..6e720e8a3 100644
--- a/vendor/modernc.org/sqlite/sqlite_go18.go
+++ b/vendor/modernc.org/sqlite/sqlite_go18.go
@@ -13,37 +13,72 @@ import (
)
// Ping implements driver.Pinger
-func (c *conn) Ping(ctx context.Context) error {
- _, err := c.ExecContext(ctx, "select 1", nil)
+func (c *conn) Ping(ctx context.Context) (err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p: err %v", c, ctx, err)
+ }()
+ }
+ _, err = c.ExecContext(ctx, "select 1", nil)
return err
}
// BeginTx implements driver.ConnBeginTx
-func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
+func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (dt driver.Tx, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, opts %+v: (driver.Tx %v, err %v)", c, ctx, opts, dt, err)
+ }()
+ }
return c.begin(ctx, opts)
}
// PrepareContext implements driver.ConnPrepareContext
-func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
+func (c *conn) PrepareContext(ctx context.Context, query string) (ds driver.Stmt, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q: (driver.Stmt %v, err %v)", c, ctx, query, ds, err)
+ }()
+ }
return c.prepare(ctx, query)
}
// ExecContext implements driver.ExecerContext
-func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
+func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q, args %v: (driver.Result %p, err %v)", c, ctx, query, args, dr, err)
+ }()
+ }
return c.exec(ctx, query, args)
}
// QueryContext implements driver.QueryerContext
-func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
+func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("conn %p, ctx %p, query %q, args %v: (driver.Rows %p, err %v)", c, ctx, query, args, dr, err)
+ }()
+ }
return c.query(ctx, query, args)
}
// ExecContext implements driver.StmtExecContext
-func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
+func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (dr driver.Result, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("stmt %p, ctx %p, args %v: (driver.Result %p, err %v)", s, ctx, args, dr, err)
+ }()
+ }
return s.exec(ctx, args)
}
// QueryContext implements driver.StmtQueryContext
-func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
+func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (dr driver.Rows, err error) {
+ if dmesgs {
+ defer func() {
+ dmesg("stmt %p, ctx %p, args %v: (driver.Rows %p, err %v)", s, ctx, args, dr, err)
+ }()
+ }
return s.query(ctx, args)
}
diff --git a/vendor/modernc.org/sqlite/unconvert.sh b/vendor/modernc.org/sqlite/unconvert.sh
index ccfc8da18..79ce92ff0 100644
--- a/vendor/modernc.org/sqlite/unconvert.sh
+++ b/vendor/modernc.org/sqlite/unconvert.sh
@@ -1,5 +1,5 @@
set -evx
until unconvert -fastmath -all ./...
do
- unconvert -fastmath -apply -all ./...
+ unconvert2 -fastmath -apply -all ./...
done