diff options
Diffstat (limited to 'vendor/modernc.org/sqlite')
| -rw-r--r-- | vendor/modernc.org/sqlite/AUTHORS | 3 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/CONTRIBUTORS | 4 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/README.md | 53 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/dmesg.go | 56 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/doc.go | 59 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/lib/mutex.go | 8 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/nodmesg.go | 12 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/sqlite.go | 607 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/sqlite_go18.go | 51 | ||||
| -rw-r--r-- | vendor/modernc.org/sqlite/unconvert.sh | 2 | 
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 | 
