feat: Added Sqlite reader
Some checks failed
CI / Test (1.24) (push) Successful in -23m3s
CI / Test (1.25) (push) Successful in -22m45s
CI / Lint (push) Failing after -25m11s
CI / Build (push) Failing after -25m26s
Integration Tests / Integration Tests (push) Successful in -25m38s

This commit is contained in:
2026-02-07 09:30:45 +02:00
parent c9eed9b794
commit d0630b4899
1370 changed files with 6350551 additions and 361 deletions

32
vendor/modernc.org/sqlite/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,32 @@
# This file lists authors for copyright purposes. This file is distinct from
# the CONTRIBUTORS files. See the latter for an explanation.
#
# Names should be added to this file as:
# Name or Organization <email address>
#
# The email address is not required for organizations.
#
# Please keep the list sorted.
Angus Dippenaar <angusdippenaar@gmail.com>
Artyom Pervukhin <github@artyom.dev>
Dan Kortschak <dan@kortschak.io>
Dan Peterson <danp@danp.net>
David Walton <david@davidwalton.com>
Davsk Ltd Co <skinner.david@gmail.com>
FerretDB Inc.
Harald Albrecht <thediveo@gmx.eu>
Jaap Aarts <jaap.aarts1@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Josh Bleecher Snyder <josharian@gmail.com>
Josh Klein <josh.klein@outlook.com>
Logan Snow <logansnow@protonmail.com>
Michael Hoffmann <mhoffm@posteo.de>
Michael Rykov <mrykov@gmail.com>
Morgan Bazalgette <morgan@howl.moe>
Ross Light <ross@zombiezen.com>
Saed SayedAhmed <saadmtsa@gmail.com>
Steffen Butzer <steffen(dot)butzer@outlook.com>
Toni Spets <toni.spets@beeper.com>
W. Michael Petullo <mike@flyn.org>
SUSE LLC <moio@suse.com>

104
vendor/modernc.org/sqlite/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,104 @@
# Changelog
- 2026-01-19 v1.44.3: Resolves [issue 243](https://gitlab.com/cznic/sqlite/-/issues/243).
- 2026-01-18 v1.44.2: Upgrade to [SQLite 3.51.2](https://sqlite.org/releaselog/3_51_2.html).
- 2026-01-13 v1.44.0: Upgrade to SQLite 3.51.1.
- 2025-10-10 v1.39.1: Upgrade to SQLite 3.50.4.
- 2025-06-09 v1.38.0: Upgrade to SQLite 3.50.1.
- 2025-02-26 v1.36.0: Upgrade to SQLite 3.49.0.
- 2024-11-16 v1.34.0: Implement ResetSession and IsValid methods in connection
- 2024-07-22 v1.31.0: Support windows/386.
- 2024-06-04 v1.30.0: Upgrade to SQLite 3.46.0, release notes at
https://sqlite.org/releaselog/3_46_0.html.
- 2024-02-13 v1.29.0: Upgrade to SQLite 3.45.1, release notes at
https://sqlite.org/releaselog/3_45_1.html.
- 2023-12-14: v1.28.0: Add (*Driver).RegisterConnectionHook,
ConnectionHookFn, ExecQuerierContext, RegisterConnectionHook.
- 2023-08-03 v1.25.0: enable SQLITE_ENABLE_DBSTAT_VTAB.
- 2023-07-11 v1.24.0: Add
(*conn).{Serialize,Deserialize,NewBackup,NewRestore} methods, add Backup
type.
- 2023-06-01 v1.23.0: Allow registering aggregate functions.
- 2023-04-22 v1.22.0: Support linux/s390x.
- 2023-02-23 v1.21.0: Upgrade to SQLite 3.41.0, release notes at
https://sqlite.org/releaselog/3_41_0.html.
- 2022-11-28 v1.20.0: Support linux/ppc64le.
- 2022-09-16 v1.19.0: Support frebsd/arm64.
- 2022-07-26 v1.18.0: Add support for Go fs.FS based SQLite virtual
filesystems, see function New in modernc.org/sqlite/vfs and/or TestVFS in
all_test.go
- 2022-04-24 v1.17.0: Support windows/arm64.
- 2022-04-04 v1.16.0: Support scalar application defined functions written
in Go. See https://www.sqlite.org/appfunc.html
- 2022-03-13 v1.15.0: Support linux/riscv64.
- 2021-11-13 v1.14.0: Support windows/amd64. This target had previously
only experimental status because of a now resolved memory leak.
- 2021-09-07 v1.13.0: Support freebsd/amd64.
- 2021-06-23 v1.11.0: Upgrade to use sqlite 3.36.0, release notes at
https://www.sqlite.org/releaselog/3_36_0.html.
- 2021-05-06 v1.10.6: Fixes a memory corruption issue
(https://gitlab.com/cznic/sqlite/-/issues/53). Versions since v1.8.6 were
affected and should be updated to v1.10.6.
- 2021-03-14 v1.10.0: Update to use sqlite 3.35.0, release notes at
https://www.sqlite.org/releaselog/3_35_0.html.
- 2021-03-11 v1.9.0: Support darwin/arm64.
- 2021-01-08 v1.8.0: Support darwin/amd64.
- 2020-09-13 v1.7.0: Support linux/arm and linux/arm64.
- 2020-09-08 v1.6.0: Support linux/386.
- 2020-09-03 v1.5.0: This project is now completely CGo-free, including
the Tcl tests.
- 2020-08-26 v1.4.0: First stable release for linux/amd64. The
database/sql driver and its tests are CGo free. Tests of the translated
sqlite3.c library still require CGo.
- 2020-07-26 v1.4.0-beta1: The project has reached beta status while
supporting linux/amd64 only at the moment. The 'extraquick' Tcl testsuite
reports
- 2019-12-28 v1.2.0-alpha.3: Third alpha fixes issue #19.
- 2019-12-26 v1.1.0-alpha.2: Second alpha release adds support for
accessing a database concurrently by multiple goroutines and/or processes.
v1.1.0 is now considered feature-complete. Next planed release should be a
beta with a proper test suite.
- 2019-12-18 v1.1.0-alpha.1: First alpha release using the new cc/v3,
gocc, qbe toolchain. Some primitive tests pass on linux_{amd64,386}. Not
yet safe for concurrent access by multiple goroutines. Next alpha release
is planed to arrive before the end of this year.
- 2017-06-10: Windows/Intel no more uses the VM (thanks Steffen Butzer).
- 2017-06-05 Linux/Intel no more uses the VM (cznic/virtual).

45
vendor/modernc.org/sqlite/CONTRIBUTORS generated vendored Normal file
View File

@@ -0,0 +1,45 @@
# This file lists people who contributed code to this repository. The AUTHORS
# file lists the copyright holders; this file lists people.
#
# Names should be added to this file like so:
# Name <email address>
#
# Please keep the list sorted.
Alexander Menzhinsky <amenzhinsky@gmail.com>
Alexey Palazhchenko <alexey.palazhchenko@gmail.com>
Angus Dippenaar <angusdippenaar@gmail.com>
Artyom Pervukhin <github@artyom.dev>
Adrian Witas <adrianwit@gmail.com>
Dan Kortschak <dan@kortschak.io>
Dan Peterson <danp@danp.net>
David Skinner <skinner.david@gmail.com>
David Walton <david@davidwalton.com>
Elle Mouton <elle.mouton@gmail.com>
FlyingOnion <731677080@qq.com>
Gleb Sakhnov <gleb.sakhnov@gmail.com>
Guénaël Muller <inkey@inkey-art.net>
Harald Albrecht <thediveo@gmx.eu>
Jaap Aarts <jaap.aarts1@gmail.com>
Jan Mercl <0xjnml@gmail.com>
Josh Bleecher Snyder <josharian@gmail.com>
Josh Klein <josh.klein@outlook.com>
Kim <grufwub@gmail.com>
Logan Snow <logansnow@protonmail.com>
Mario Salgado <mariozalgo@gmail.com>
Mark Summerfield <mark@qtrac.eu>
Matthew Gabeler-Lee <fastcat@gmail.com>
Michael Hoffmann <mhoffm@posteo.de>
Michael Rykov <mrykov@gmail.com>
Morgan Bazalgette <morgan@howl.moe>
Romain Le Disez <r.gitlab@ledisez.net>
Ross Light <ross@zombiezen.com>
Saed SayedAhmed <saadmtsa@gmail.com>
Sean McGivern <sean@mcgivern.me.uk>
Steffen Butzer <steffen(dot)butzer@outlook.com>
Toni Spets <toni.spets@beeper.com>
W. Michael Petullo <mike@flyn.org>
Walter Wanderley <walterwanderley@gmail.com>
Yaacov Akiba Slama <ya@slamail.org>
Prathyush PV <prathyush.pv@temporal.io>
SUSE LLC <legal@suse.de>

6
vendor/modernc.org/sqlite/HACKING.md generated vendored Normal file
View File

@@ -0,0 +1,6 @@
Please do not tag commits unless all builders at
https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fsqlite are
happy.
Since 2024-03-12 it should be no more necessary to manually tag releases at
all as the repo is now set to be tagged automatically.

26
vendor/modernc.org/sqlite/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,26 @@
Copyright (c) 2017 The Sqlite Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

86
vendor/modernc.org/sqlite/Makefile generated vendored Normal file
View File

@@ -0,0 +1,86 @@
# Copyright 2024 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.
.PHONY: all build_all_targets clean edit editor test vendor work
all: editor
golint 2>&1
staticcheck 2>&1
build_all_targets:
GOOS=darwin GOARCH=amd64 go test -c -o /dev/null
GOOS=darwin GOARCH=amd64 go build -v ./...
GOOS=darwin GOARCH=arm64 go test -c -o /dev/null
GOOS=darwin GOARCH=arm64 go build -v ./...
GOOS=freebsd GOARCH=amd64 go test -c -o /dev/null
GOOS=freebsd GOARCH=amd64 go build -v ./...
# GOOS=freebsd GOARCH=386 go test -c -o /dev/null
# GOOS=freebsd GOARCH=386 go build -v ./...
# GOOS=freebsd GOARCH=arm go test -c -o /dev/null
# GOOS=freebsd GOARCH=arm go build -v ./...
GOOS=freebsd GOARCH=arm64 go test -c -o /dev/null
GOOS=freebsd GOARCH=arm64 go build -v ./...
GOOS=linux GOARCH=386 go test -c -o /dev/null
GOOS=linux GOARCH=386 go build -v ./...
GOOS=linux GOARCH=amd64 go test -c -o /dev/null
GOOS=linux GOARCH=amd64 go build -v ./...
GOOS=linux GOARCH=arm go test -c -o /dev/null
GOOS=linux GOARCH=arm go build -v ./...
GOOS=linux GOARCH=arm64 go test -c -o /dev/null
GOOS=linux GOARCH=arm64 go build -v ./...
GOOS=linux GOARCH=loong64 go test -c -o /dev/null
GOOS=linux GOARCH=loong64 go build -v ./...
GOOS=linux GOARCH=ppc64le go test -c -o /dev/null
GOOS=linux GOARCH=ppc64le go build -v ./...
GOOS=linux GOARCH=riscv64 go test -c -o /dev/null
GOOS=linux GOARCH=riscv64 go build -v ./...
GOOS=linux GOARCH=s390x go test -c -o /dev/null
GOOS=linux GOARCH=s390x go build -v ./...
# GOOS=netbsd GOARCH=amd64 go test -c -o /dev/null
# GOOS=netbsd GOARCH=amd64 go build -v ./...
GOOS=openbsd GOARCH=amd64 go test -c -o /dev/null
GOOS=openbsd GOARCH=amd64 go build -v ./...
GOOS=openbsd GOARCH=arm64 go test -c -o /dev/null
GOOS=openbsd GOARCH=arm64 go build -v ./...
GOOS=windows GOARCH=386 go test -c -o /dev/null
GOOS=windows GOARCH=386 go build -v ./...
GOOS=windows GOARCH=amd64 go test -c -o /dev/null
GOOS=windows GOARCH=amd64 go build -v ./...
GOOS=windows GOARCH=arm64 go test -c -o /dev/null
GOOS=windows GOARCH=arm64 go build -v ./...
echo done
clean:
rm -f log-* cpu.test mem.test *.out go.work*
go clean
edit:
@if [ -f "Session.vim" ]; then gvim -S & else gvim -p Makefile go.mod builder.json all_test.go & fi
editor:
go test -c -o /dev/null
go build -v -o /dev/null ./...
cd vendor_libsqlite3 && go build -o /dev/null main.go
test:
go test -v -timeout 24h
vendor:
cd vendor_libsqlite3 && go build -o ../vendor main.go
./vendor
rm -f vendor
make build_all_targets
make build_all_targets
work:
rm -f go.work*
go work init
go work use .
go work use ../cc/v4
go work use ../ccgo/v3
go work use ../ccgo/v4
go work use ../libc
go work use ../libtcl8.6
go work use ../libsqlite3
go work use ../libz

62
vendor/modernc.org/sqlite/README.md generated vendored Normal file
View File

@@ -0,0 +1,62 @@
## Important: Repository Mirroring
**This project is primarily developed on GitLab.** The repository you are currently viewing might be a mirror. Please review the guidelines below based on where you are viewing this:
| Platform | Role | Contributing Guidelines |
| :--- | :--- | :--- |
| **GitLab** | **Primary Source** | This is the canonical repository (`cznic/sqlite`). CI pipelines and main development happen here. |
| **GitHub** | **Mirror** | This is a mirror (`modernc-org/sqlite`). We **do accept** Issues and Pull Requests here for your convenience! <br> *Note: PRs submitted here will be manually merged into the GitLab source, so please allow extra time for processing.* |
[![Go Reference](https://pkg.go.dev/badge/modernc.org/sqlite.svg)](https://pkg.go.dev/modernc.org/sqlite)
[![LiberaPay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/jnml/donate)
[![receives](https://img.shields.io/liberapay/receives/jnml.svg?logo=liberapay)](https://liberapay.com/jnml/donate)
[![patrons](https://img.shields.io/liberapay/patrons/jnml.svg?logo=liberapay)](https://liberapay.com/jnml/donate)
---
![heart](sponsors/heart.png "heart")
[Github Sponsors Account](https://github.com/sponsors/j-modernc-org) / j-modernc-org
### Enterprise Infrastructure Tier Sponsor
![tailscale](sponsors/tailscale.png "tailscale") [Tailscale](https://tailscale.com/)
### Startup / Small Business Tier Sponsor
![octoberswimmer](sponsors/octoberswimmer.png "osctoberswimmer") [October Swimmer](https://www.octoberswimmer.com/)
---
![benchmarks](bench.png "benchmarks") [The SQLite Drivers Benchmarks Game]
[The SQLite Drivers Benchmarks Game]: https://pkg.go.dev/modernc.org/sqlite-bench#readme-tl-dr-scorecard
---
Virtual Tables (vtab)
---------------------
The driver exposes a Go API to implement SQLite virtual table modules in pure Go via the `modernc.org/sqlite/vtab` package. This lets you back SQL tables with arbitrary data sources (e.g., vector indexes, CSV files, remote APIs) and integrate with SQLites planner.
- Register: `vtab.RegisterModule(db, name, module)`. Registration applies to new connections only.
- Schema declaration: Call `ctx.Declare("CREATE TABLE <name>(<cols...>)")` within `Create` or `Connect`. The driver does not auto-declare schemas, enabling dynamic schemas.
- Module arguments: `args []string` passed to `Create/Connect` are configuration parsed from `USING module(...)`. They are not treated as columns unless your module chooses to.
- Planning (BestIndex):
- Inspect `info.Constraints` (with `Column`, `Op`, `Usable`, 0-based `ArgIndex`, and `Omit`), `info.OrderBy`, and `info.ColUsed` (bitmask of referenced columns).
- Set `ArgIndex` (0-based) to populate `Filter`s `vals` in the chosen order; set `Omit` to ask SQLite not to re-check a constraint you fully handle.
- Execution: `Cursor.Filter(idxNum, idxStr, vals)` receives arguments in the order implied by `ArgIndex`.
- Operators: Common SQLite operators map to `ConstraintOp` (EQ/NE/GT/GE/LT/LE/MATCH/IS/ISNOT/ISNULL/ISNOTNULL/LIKE/GLOB/REGEXP/FUNCTION/LIMIT/OFFSET). Unknown operators map to `OpUnknown`.
- Errors: Returning an error from vtab methods surfaces a descriptive message to SQLite (e.g., `zErrMsg` for xCreate/xConnect/xBestIndex/xFilter; `sqlite3_result_error` for xColumn).
Examples
--------
- Vector search (sqlite-vec style):
- `CREATE VIRTUAL TABLE vec_docs USING vec(dim=128, metric="cosine")`
- Module reads args (e.g., `dim`, `metric`), calls `ctx.Declare("CREATE TABLE vec_docs(id, embedding, content HIDDEN)")`, and implements search via `BestIndex`/`Filter`.
- CSV loader:
- `CREATE VIRTUAL TABLE csv_users USING csv(filename="/tmp/users.csv", delimiter=",", header=true)`
- Module reads the file header to compute columns, declares them via `ctx.Declare("CREATE TABLE csv_users(name, email, ...)")`, and streams rows via a cursor.
See `vtab` package docs for full API details.

25
vendor/modernc.org/sqlite/SQLITE-LICENSE generated vendored Normal file
View File

@@ -0,0 +1,25 @@
SQLite Is Public Domain
All of the code and documentation in SQLite has been dedicated to the public
domain by the authors. All code authors, and representatives of the companies
they work for, have signed affidavits dedicating their contributions to the
public domain and originals of those signed affidavits are stored in a firesafe
at the main offices of Hwaci. Anyone is free to copy, modify, publish, use,
compile, sell, or distribute the original SQLite code, either in source code
form or as a compiled binary, for any purpose, commercial or non-commercial,
and by any means.
The previous paragraph applies to the deliverable code and documentation in
SQLite - those parts of the SQLite library that you actually bundle and ship
with a larger application. Some scripts used as part of the build process (for
example the "configure" scripts generated by autoconf) might fall under other
open-source licenses. Nothing from these build scripts ever reaches the final
deliverable SQLite library, however, and so the licenses associated with those
scripts should not be a factor in assessing your rights to copy and use the
SQLite library.
All of the deliverable code in SQLite has been written from scratch. No code
has been taken from other projects or from the open internet. Every line of
code can be traced back to its original author, and all of those authors have
public domain dedications on file. So the SQLite code base is clean and is
uncontaminated with licensed code from other projects.

65
vendor/modernc.org/sqlite/backup.go generated vendored Normal file
View File

@@ -0,0 +1,65 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"database/sql/driver"
sqlite3 "modernc.org/sqlite/lib"
)
// Backup object is used to manage progress and cleanup an online backup. It
// is returned by NewBackup or NewRestore.
type Backup struct {
srcConn *conn // source database connection
dstConn *conn // destination database connection
pBackup uintptr // sqlite3_backup object pointer
}
// Step will copy up to n pages between the source and destination databases
// specified by the backup object. If n is negative, all remaining source
// pages are copied.
// If it successfully copies n pages and there are still more pages to be
// copied, then the function returns true with no error. If it successfully
// finishes copying all pages from source to destination, then it returns
// false with no error. If an error occurs while running, then an error is
// returned.
func (b *Backup) Step(n int32) (bool, error) {
rc := sqlite3.Xsqlite3_backup_step(b.srcConn.tls, b.pBackup, n)
if rc == sqlite3.SQLITE_OK {
return true, nil
} else if rc == sqlite3.SQLITE_DONE {
return false, nil
} else {
return false, b.srcConn.errstr(rc)
}
}
// Finish releases all resources associated with the Backup object. The Backup
// object is invalid and may not be used following a call to Finish.
func (b *Backup) Finish() error {
rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
b.dstConn.Close()
if rc == sqlite3.SQLITE_OK {
return nil
} else {
return b.srcConn.errstr(rc)
}
}
// Commit releases all resources associated with the Backup object but does not
// close the destination database connection.
//
// The destination database connection is returned to the caller or an error if raised.
// It is the responsibility of the caller to handle the connection closure.
func (b *Backup) Commit() (driver.Conn, error) {
rc := sqlite3.Xsqlite3_backup_finish(b.srcConn.tls, b.pBackup)
if rc == sqlite3.SQLITE_OK {
return b.dstConn, nil
} else {
return nil, b.srcConn.errstr(rc)
}
}

BIN
vendor/modernc.org/sqlite/bench.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

6
vendor/modernc.org/sqlite/builder.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"autogen": "<none>",
"autotag": "<none>",
"autoupdate": "<none>",
"test": "darwin/(amd64|arm64)|freebsd/(amd64|arm64)|linux/(386|amd64|arm|arm64|loong64|ppc64le|riscv64|s390x)|openbsd/(amd64|arm64)|windows/(amd64|arm64|386)"
}

1100
vendor/modernc.org/sqlite/conn.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

299
vendor/modernc.org/sqlite/convert.go generated vendored Normal file
View File

@@ -0,0 +1,299 @@
// Extracted from Go database/sql source code
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Type conversions for Scan.
package sqlite
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
// convertAssign copies to dest the value in src, converting it if possible.
// An error is returned if the copy would result in loss of information.
// dest should be a pointer type.
func convertAssign(dest, src interface{}) error {
// Common cases, without reflect.
switch s := src.(type) {
case string:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = s
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s)
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = append((*d)[:0], s...)
return nil
}
case []byte:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = string(s)
return nil
case *interface{}:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = s
return nil
}
case time.Time:
switch d := dest.(type) {
case *time.Time:
*d = s
return nil
case *string:
*d = s.Format(time.RFC3339Nano)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s.Format(time.RFC3339Nano))
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
return nil
}
case nil:
switch d := dest.(type) {
case *interface{}:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = nil
return nil
}
}
var sv reflect.Value
switch d := dest.(type) {
case *string:
sv = reflect.ValueOf(src)
switch sv.Kind() {
case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
*d = asString(src)
return nil
}
case *[]byte:
sv = reflect.ValueOf(src)
if b, ok := asBytes(nil, sv); ok {
*d = b
return nil
}
case *sql.RawBytes:
sv = reflect.ValueOf(src)
if b, ok := asBytes([]byte(*d)[:0], sv); ok {
*d = sql.RawBytes(b)
return nil
}
case *bool:
bv, err := driver.Bool.ConvertValue(src)
if err == nil {
*d = bv.(bool)
}
return err
case *interface{}:
*d = src
return nil
}
if scanner, ok := dest.(sql.Scanner); ok {
return scanner.Scan(src)
}
dpv := reflect.ValueOf(dest)
if dpv.Kind() != reflect.Ptr {
return errors.New("destination not a pointer")
}
if dpv.IsNil() {
return errNilPtr
}
if !sv.IsValid() {
sv = reflect.ValueOf(src)
}
dv := reflect.Indirect(dpv)
if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
switch b := src.(type) {
case []byte:
dv.Set(reflect.ValueOf(cloneBytes(b)))
default:
dv.Set(sv)
}
return nil
}
if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
dv.Set(sv.Convert(dv.Type()))
return nil
}
// The following conversions use a string value as an intermediate representation
// to convert between various numeric types.
//
// This also allows scanning into user defined types such as "type Int int64".
// For symmetry, also check for string destination types.
switch dv.Kind() {
case reflect.Ptr:
if src == nil {
dv.Set(reflect.Zero(dv.Type()))
return nil
}
dv.Set(reflect.New(dv.Type().Elem()))
return convertAssign(dv.Interface(), src)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s := asString(src)
i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetInt(i64)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
s := asString(src)
u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetUint(u64)
return nil
case reflect.Float32, reflect.Float64:
s := asString(src)
f64, err := strconv.ParseFloat(s, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetFloat(f64)
return nil
case reflect.String:
switch v := src.(type) {
case string:
dv.SetString(v)
return nil
case []byte:
dv.SetString(string(v))
return nil
}
}
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
}
func strconvErr(err error) error {
if ne, ok := err.(*strconv.NumError); ok {
return ne.Err
}
return err
}
func cloneBytes(b []byte) []byte {
if b == nil {
return nil
}
c := make([]byte, len(b))
copy(c, b)
return c
}
func asString(src interface{}) string {
switch v := src.(type) {
case string:
return v
case []byte:
return string(v)
}
rv := reflect.ValueOf(src)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(rv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(rv.Uint(), 10)
case reflect.Float64:
return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
case reflect.Float32:
return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
case reflect.Bool:
return strconv.FormatBool(rv.Bool())
}
return fmt.Sprintf("%v", src)
}
func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.AppendInt(buf, rv.Int(), 10), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.AppendUint(buf, rv.Uint(), 10), true
case reflect.Float32:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
case reflect.Float64:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
case reflect.Bool:
return strconv.AppendBool(buf, rv.Bool()), true
case reflect.String:
s := rv.String()
return append(buf, s...), true
}
return
}

56
vendor/modernc.org/sqlite/dmesg.go generated vendored Normal file
View File

@@ -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)
}
}

204
vendor/modernc.org/sqlite/doc.go generated vendored Normal file
View File

@@ -0,0 +1,204 @@
// Copyright 2017 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.
// Package sqlite is a sql/database driver using a CGo-free port of the C
// SQLite3 library.
//
// SQLite is an in-process implementation of a self-contained, serverless,
// zero-configuration, transactional SQL database engine.
//
// # Fragile modernc.org/libc dependency
//
// When you import this package you should use in your go.mod file the exact
// same version of modernc.org/libc as seen in the go.mod file of this
// repository.
//
// See the discussion at https://gitlab.com/cznic/sqlite/-/issues/177 for more details.
//
// # Thanks
//
// This project is sponsored by Schleibinger Geräte Teubert u. Greim GmbH by
// allowing one of the maintainers to work on it also in office hours.
//
// # Supported platforms and architectures
//
// These combinations of GOOS and GOARCH are currently supported
//
// OS Arch SQLite version
// ------------------------------
// darwin amd64 3.51.2
// darwin arm64 3.51.2
// freebsd amd64 3.51.2
// freebsd arm64 3.51.2
// linux 386 3.51.2
// linux amd64 3.51.2
// linux arm 3.51.2
// linux arm64 3.51.2
// linux loong64 3.51.2
// linux ppc64le 3.51.2
// linux riscv64 3.51.2
// linux s390x 3.51.2
// windows 386 3.51.2
// windows amd64 3.51.2
// windows arm64 3.51.2
//
// # Benchmarks
//
// [The SQLite Drivers Benchmarks Game]
//
// # Builders
//
// Builder results available at:
//
// https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fsqlite
//
//
// # Connecting to a database
//
// To access a Sqlite database do something like
//
// import (
// "database/sql"
//
// _ "modernc.org/sqlite"
// )
//
// ...
//
//
// db, err := sql.Open("sqlite", dsnURI)
//
// ...
//
// # Debug and development versions
//
// A comma separated list of options can be passed to `go generate` via the
// environment variable GO_GENERATE. Some useful options include for example:
//
// -DSQLITE_DEBUG
// -DSQLITE_MEM_DEBUG
// -ccgo-verify-structs
//
// To create a debug/development version, issue for example:
//
// $ GO_GENERATE=-DSQLITE_DEBUG,-DSQLITE_MEM_DEBUG go generate
//
// Note: To run `go generate` you need to have modernc.org/ccgo/v3 installed.
//
// # Hacking
//
// This is an example of how to use the debug logs in modernc.org/libc when hunting a bug.
//
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ git status
// On branch master
// Your branch is up to date with 'origin/master'.
//
// nothing to commit, working tree clean
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ git log -1
// commit df33b8d15107f3cc777799c0fe105f74ef499e62 (HEAD -> master, tag: v1.21.1, origin/master, origin/HEAD, wips, ok)
// Author: Jan Mercl <0xjnml@gmail.com>
// Date: Mon Mar 27 16:18:28 2023 +0200
//
// upgrade to SQLite 3.41.2
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ rm -f /tmp/libc.log ; go test -v -tags=libc.dmesg -run TestScalar ; ls -l /tmp/libc.log
// test binary compiled for linux/amd64
// === RUN TestScalar
// --- PASS: TestScalar (0.09s)
// PASS
// ok modernc.org/sqlite 0.128s
// -rw-r--r-- 1 jnml jnml 76 Apr 6 11:22 /tmp/libc.log
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ cat /tmp/libc.log
// [10723 sqlite.test] 2023-04-06 11:22:48.288066057 +0200 CEST m=+0.000707150
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$
//
// The /tmp/libc.log file is created as requested. No useful messages there because none are enabled in libc. Let's try to enable Xwrite as an example.
//
// 0:jnml@e5-1650:~/src/modernc.org/libc$ git status
// On branch master
// Your branch is up to date with 'origin/master'.
//
// Changes not staged for commit:
// (use "git add <file>..." to update what will be committed)
// (use "git restore <file>..." to discard changes in working directory)
// modified: libc_linux.go
//
// no changes added to commit (use "git add" and/or "git commit -a")
// 0:jnml@e5-1650:~/src/modernc.org/libc$ git log -1
// commit 1e22c18cf2de8aa86d5b19b165f354f99c70479c (HEAD -> master, tag: v1.22.3, origin/master, origin/HEAD)
// Author: Jan Mercl <0xjnml@gmail.com>
// Date: Wed Feb 22 20:27:45 2023 +0100
//
// support sqlite 3.41 on linux targets
// 0:jnml@e5-1650:~/src/modernc.org/libc$ git diff
// diff --git a/libc_linux.go b/libc_linux.go
// index 1c2f482..ac1f08d 100644
// --- a/libc_linux.go
// +++ b/libc_linux.go
// @@ -332,19 +332,19 @@ func Xwrite(t *TLS, fd int32, buf uintptr, count types.Size_t) types.Ssize_t {
// var n uintptr
// switch n, _, err = unix.Syscall(unix.SYS_WRITE, uintptr(fd), buf, uintptr(count)); err {
// case 0:
// - // if dmesgs {
// - // // dmesg("%v: %d %#x: %#x\n%s", origin(1), fd, count, n, hex.Dump(GoBytes(buf, int(n))))
// - // dmesg("%v: %d %#x: %#x", origin(1), fd, count, n)
// - // }
// + if dmesgs {
// + // dmesg("%v: %d %#x: %#x\n%s", origin(1), fd, count, n, hex.Dump(GoBytes(buf, int(n))))
// + dmesg("%v: %d %#x: %#x", origin(1), fd, count, n)
// + }
// return types.Ssize_t(n)
// case errno.EAGAIN:
// // nop
// }
// }
//
// - // if dmesgs {
// - // dmesg("%v: fd %v, count %#x: %v", origin(1), fd, count, err)
// - // }
// + if dmesgs {
// + dmesg("%v: fd %v, count %#x: %v", origin(1), fd, count, err)
// + }
// t.setErrno(err)
// return -1
// }
// 0:jnml@e5-1650:~/src/modernc.org/libc$
//
// We need to tell the Go build system to use our local, patched/debug libc:
//
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ go work use $(go env GOPATH)/src/modernc.org/libc
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ go work use .
//
// And run the test again:
//
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ rm -f /tmp/libc.log ; go test -v -tags=libc.dmesg -run TestScalar ; ls -l /tmp/libc.log
// test binary compiled for linux/amd64
// === RUN TestScalar
// --- PASS: TestScalar (0.26s)
// PASS
// ok modernc.org/sqlite 0.285s
// -rw-r--r-- 1 jnml jnml 918 Apr 6 11:29 /tmp/libc.log
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$ cat /tmp/libc.log
// [11910 sqlite.test] 2023-04-06 11:29:13.143589542 +0200 CEST m=+0.000689270
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x200: 0x200
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0xc: 0xc
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 7 0x1000: 0x1000
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 7 0x1000: 0x1000
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x200: 0x200
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x4: 0x4
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x1000: 0x1000
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x4: 0x4
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x4: 0x4
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x1000: 0x1000
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0x4: 0x4
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 8 0xc: 0xc
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 7 0x1000: 0x1000
// [11910 sqlite.test] libc_linux.go:337:Xwrite: 7 0x1000: 0x1000
// 0:jnml@e5-1650:~/src/modernc.org/sqlite$
//
// # Sqlite documentation
//
// See https://sqlite.org/docs.html
//
// [The SQLite Drivers Benchmarks Game]: https://pkg.go.dev/modernc.org/sqlite-bench#readme-tl-dr-scorecard
package sqlite // import "modernc.org/sqlite"

120
vendor/modernc.org/sqlite/driver.go generated vendored Normal file
View File

@@ -0,0 +1,120 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"database/sql/driver"
"fmt"
"modernc.org/sqlite/vtab"
)
// Driver implements database/sql/driver.Driver.
type Driver struct {
// user defined functions that are added to every new connection on Open
udfs map[string]*userDefinedFunction
// collations that are added to every new connection on Open
collations map[string]*collation
// connection hooks are called after a connection is opened
connectionHooks []ConnectionHookFn
// modules holds registered virtual table modules that should be added to
// every new connection on Open.
modules map[string]vtab.Module
}
var d = &Driver{
udfs: make(map[string]*userDefinedFunction, 0),
collations: make(map[string]*collation, 0),
connectionHooks: make([]ConnectionHookFn, 0),
modules: make(map[string]vtab.Module, 0),
}
func newDriver() *Driver { return d }
// Open returns a new connection to the database. The name is a string in a
// driver-specific format.
//
// Open may return a cached connection (one previously closed), but doing so is
// unnecessary; the sql package maintains a pool of idle connections for
// efficient re-use.
//
// The returned connection is only used by one goroutine at a time.
//
// The name may be a filename, e.g., "/tmp/mydata.sqlite", or a URI, in which
// case it may include a '?' followed by one or more query parameters.
// For example, "file:///tmp/mydata.sqlite?_pragma=foreign_keys(1)&_time_format=sqlite".
// The supported query parameters are:
//
// _pragma: Each value will be run as a "PRAGMA ..." statement (with the PRAGMA
// keyword added for you). May be specified more than once, '&'-separated. For more
// information on supported PRAGMAs see: https://www.sqlite.org/pragma.html
//
// _time_format: The name of a format to use when writing time values to the
// database. Currently the only supported value is "sqlite", which corresponds
// to format 7 from https://www.sqlite.org/lang_datefunc.html#time_values,
// including the timezone specifier. If this parameter is not specified, then
// the default String() format will be used.
//
// _time_integer_format: The name of a integer format to use when writing time values.
// By default, the time is stored as string and the format can be set with _time_format
// parameter. If _time_integer_format is set, the time will be stored as an integer and
// the integer value will depend on the integer format.
// If you decide to set both _time_format and _time_integer_format, the time will be
// converted as integer and the _time_format value will be ignored.
// Currently the supported value are "unix","unix_milli", "unix_micro" and "unix_nano",
// which corresponds to seconds, milliseconds, microseconds or nanoseconds
// since unixepoch (1 January 1970 00:00:00 UTC).
//
// _inttotime: Enable conversion of time column (DATE, DATETIME,TIMESTAMP) from integer
// to time if the field contain integer (int64).
//
// _txlock: The locking behavior to use when beginning a transaction. May be
// "deferred" (the default), "immediate", or "exclusive" (case insensitive). See:
// https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
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
}
for _, udf := range d.udfs {
if err = c.createFunctionInternal(udf); err != nil {
c.Close()
return nil, err
}
}
for _, coll := range d.collations {
if err = c.createCollationInternal(coll); err != nil {
c.Close()
return nil, err
}
}
for _, connHookFn := range d.connectionHooks {
if err = connHookFn(c, name); err != nil {
c.Close()
return nil, fmt.Errorf("connection hook: %w", err)
}
}
// Register any vtab modules with this connection.
// Note: vtab module registration applies to new connections only. If a
// module is registered after a connection has been opened, that existing
// connection will not see the module; open a new connection to use it.
if err := c.registerModules(); err != nil {
c.Close()
return nil, err
}
return c, nil
}
// RegisterConnectionHook registers a function to be called after each connection
// is opened. This is called after all the connection has been set up.
func (d *Driver) RegisterConnectionHook(fn ConnectionHookFn) {
d.connectionHooks = append(d.connectionHooks, fn)
}

75
vendor/modernc.org/sqlite/error.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
sqlite3 "modernc.org/sqlite/lib"
)
// Error represents sqlite library error code.
type Error struct {
msg string
code int
}
// Error implements error.
func (e *Error) Error() string { return e.msg }
// Code returns the sqlite result code for this error.
func (e *Error) Code() int { return e.code }
var (
// ErrorCodeString maps Error.Code() to its string representation.
ErrorCodeString = map[int]string{
sqlite3.SQLITE_ABORT: "Callback routine requested an abort (SQLITE_ABORT)",
sqlite3.SQLITE_AUTH: "Authorization denied (SQLITE_AUTH)",
sqlite3.SQLITE_BUSY: "The database file is locked (SQLITE_BUSY)",
sqlite3.SQLITE_CANTOPEN: "Unable to open the database file (SQLITE_CANTOPEN)",
sqlite3.SQLITE_CONSTRAINT: "Abort due to constraint violation (SQLITE_CONSTRAINT)",
sqlite3.SQLITE_CORRUPT: "The database disk image is malformed (SQLITE_CORRUPT)",
sqlite3.SQLITE_DONE: "sqlite3_step() has finished executing (SQLITE_DONE)",
sqlite3.SQLITE_EMPTY: "Internal use only (SQLITE_EMPTY)",
sqlite3.SQLITE_ERROR: "Generic error (SQLITE_ERROR)",
sqlite3.SQLITE_FORMAT: "Not used (SQLITE_FORMAT)",
sqlite3.SQLITE_FULL: "Insertion failed because database is full (SQLITE_FULL)",
sqlite3.SQLITE_INTERNAL: "Internal logic error in SQLite (SQLITE_INTERNAL)",
sqlite3.SQLITE_INTERRUPT: "Operation terminated by sqlite3_interrupt()(SQLITE_INTERRUPT)",
sqlite3.SQLITE_IOERR | (1 << 8): "(SQLITE_IOERR_READ)",
sqlite3.SQLITE_IOERR | (10 << 8): "(SQLITE_IOERR_DELETE)",
sqlite3.SQLITE_IOERR | (11 << 8): "(SQLITE_IOERR_BLOCKED)",
sqlite3.SQLITE_IOERR | (12 << 8): "(SQLITE_IOERR_NOMEM)",
sqlite3.SQLITE_IOERR | (13 << 8): "(SQLITE_IOERR_ACCESS)",
sqlite3.SQLITE_IOERR | (14 << 8): "(SQLITE_IOERR_CHECKRESERVEDLOCK)",
sqlite3.SQLITE_IOERR | (15 << 8): "(SQLITE_IOERR_LOCK)",
sqlite3.SQLITE_IOERR | (16 << 8): "(SQLITE_IOERR_CLOSE)",
sqlite3.SQLITE_IOERR | (17 << 8): "(SQLITE_IOERR_DIR_CLOSE)",
sqlite3.SQLITE_IOERR | (2 << 8): "(SQLITE_IOERR_SHORT_READ)",
sqlite3.SQLITE_IOERR | (3 << 8): "(SQLITE_IOERR_WRITE)",
sqlite3.SQLITE_IOERR | (4 << 8): "(SQLITE_IOERR_FSYNC)",
sqlite3.SQLITE_IOERR | (5 << 8): "(SQLITE_IOERR_DIR_FSYNC)",
sqlite3.SQLITE_IOERR | (6 << 8): "(SQLITE_IOERR_TRUNCATE)",
sqlite3.SQLITE_IOERR | (7 << 8): "(SQLITE_IOERR_FSTAT)",
sqlite3.SQLITE_IOERR | (8 << 8): "(SQLITE_IOERR_UNLOCK)",
sqlite3.SQLITE_IOERR | (9 << 8): "(SQLITE_IOERR_RDLOCK)",
sqlite3.SQLITE_IOERR: "Some kind of disk I/O error occurred (SQLITE_IOERR)",
sqlite3.SQLITE_LOCKED | (1 << 8): "(SQLITE_LOCKED_SHAREDCACHE)",
sqlite3.SQLITE_LOCKED: "A table in the database is locked (SQLITE_LOCKED)",
sqlite3.SQLITE_MISMATCH: "Data type mismatch (SQLITE_MISMATCH)",
sqlite3.SQLITE_MISUSE: "Library used incorrectly (SQLITE_MISUSE)",
sqlite3.SQLITE_NOLFS: "Uses OS features not supported on host (SQLITE_NOLFS)",
sqlite3.SQLITE_NOMEM: "A malloc() failed (SQLITE_NOMEM)",
sqlite3.SQLITE_NOTADB: "File opened that is not a database file (SQLITE_NOTADB)",
sqlite3.SQLITE_NOTFOUND: "Unknown opcode in sqlite3_file_control() (SQLITE_NOTFOUND)",
sqlite3.SQLITE_NOTICE: "Notifications from sqlite3_log() (SQLITE_NOTICE)",
sqlite3.SQLITE_PERM: "Access permission denied (SQLITE_PERM)",
sqlite3.SQLITE_PROTOCOL: "Database lock protocol error (SQLITE_PROTOCOL)",
sqlite3.SQLITE_RANGE: "2nd parameter to sqlite3_bind out of range (SQLITE_RANGE)",
sqlite3.SQLITE_READONLY: "Attempt to write a readonly database (SQLITE_READONLY)",
sqlite3.SQLITE_ROW: "sqlite3_step() has another row ready (SQLITE_ROW)",
sqlite3.SQLITE_SCHEMA: "The database schema changed (SQLITE_SCHEMA)",
sqlite3.SQLITE_TOOBIG: "String or BLOB exceeds size limit (SQLITE_TOOBIG)",
sqlite3.SQLITE_WARNING: "Warnings from sqlite3_log() (SQLITE_WARNING)",
}
)

43
vendor/modernc.org/sqlite/fcntl.go generated vendored Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2024 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.
package sqlite // import "modernc.org/sqlite"
import (
"unsafe"
"modernc.org/libc"
sqlite3 "modernc.org/sqlite/lib"
)
// Access to sqlite3_file_control
type FileControl interface {
// Set or query SQLITE_FCNTL_PERSIST_WAL, returns set mode or query result
FileControlPersistWAL(dbName string, mode int) (int, error)
}
var _ FileControl = (*conn)(nil)
func (c *conn) FileControlPersistWAL(dbName string, mode int) (int, error) {
pi32 := c.tls.Alloc(4)
defer c.tls.Free(4)
*(*int32)(unsafe.Pointer(pi32)) = int32(mode)
err := c.fileControl(dbName, sqlite3.SQLITE_FCNTL_PERSIST_WAL, pi32)
return int(*(*int32)(unsafe.Pointer(pi32))), err
}
func (c *conn) fileControl(dbName string, op int, pArg uintptr) error {
zDbName, err := libc.CString(dbName)
if err != nil {
return err
}
defer c.free(zDbName)
if rc := sqlite3.Xsqlite3_file_control(c.tls, c.db, zDbName, int32(op), pArg); rc != sqlite3.SQLITE_OK {
return c.errstr(rc)
}
return nil
}

78
vendor/modernc.org/sqlite/issue120.diff generated vendored Normal file
View File

@@ -0,0 +1,78 @@
--- /home/jnml/tmp/test_syscall.c 2023-04-21 16:26:44.302689709 +0200
+++ testdata/sqlite-src-3410200/src/test_syscall.c 2023-04-21 16:29:28.000869993 +0200
@@ -110,15 +110,15 @@
static int ts_fstat(int fd, struct stat *p);
static int ts_ftruncate(int fd, off_t n);
static int ts_fcntl(int fd, int cmd, ... );
-static int ts_read(int fd, void *aBuf, size_t nBuf);
-static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
+static ssize_t ts_read(int fd, void *aBuf, size_t nBuf);
+static ssize_t ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
/* Note: pread64() and pwrite64() actually use off64_t as the type on their
** last parameter. But that datatype is not defined on many systems
** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */
-static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
-static int ts_write(int fd, const void *aBuf, size_t nBuf);
-static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
-static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
+static ssize_t ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
+static ssize_t ts_write(int fd, const void *aBuf, size_t nBuf);
+static ssize_t ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
+static ssize_t ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
static int ts_fchmod(int fd, mode_t mode);
static int ts_fallocate(int fd, off_t off, off_t len);
static void *ts_mmap(void *, size_t, int, int, int, off_t);
@@ -313,7 +313,7 @@
/*
** A wrapper around read().
*/
-static int ts_read(int fd, void *aBuf, size_t nBuf){
+static ssize_t ts_read(int fd, void *aBuf, size_t nBuf){
if( tsIsFailErrno("read") ){
return -1;
}
@@ -323,7 +323,7 @@
/*
** A wrapper around pread().
*/
-static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
+static ssize_t ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
if( tsIsFailErrno("pread") ){
return -1;
}
@@ -333,7 +333,7 @@
/*
** A wrapper around pread64().
*/
-static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
+static ssize_t ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
if( tsIsFailErrno("pread64") ){
return -1;
}
@@ -343,7 +343,7 @@
/*
** A wrapper around write().
*/
-static int ts_write(int fd, const void *aBuf, size_t nBuf){
+static ssize_t ts_write(int fd, const void *aBuf, size_t nBuf){
if( tsIsFailErrno("write") ){
if( tsErrno("write")==EINTR ) orig_write(fd, aBuf, nBuf/2);
return -1;
@@ -354,7 +354,7 @@
/*
** A wrapper around pwrite().
*/
-static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
+static ssize_t ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
if( tsIsFailErrno("pwrite") ){
return -1;
}
@@ -364,7 +364,7 @@
/*
** A wrapper around pwrite64().
*/
-static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
+static ssize_t ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
if( tsIsFailErrno("pwrite64") ){
return -1;
}

16
vendor/modernc.org/sqlite/lib/defs.go generated vendored Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2022 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.
package sqlite3
const (
SQLITE_STATIC = uintptr(0) // ((sqlite3_destructor_type)0)
SQLITE_TRANSIENT = ^uintptr(0) // ((sqlite3_destructor_type)-1)
)
type (
Sqlite3_index_constraint = sqlite3_index_constraint
Sqlite3_index_orderby = sqlite3_index_orderby
Sqlite3_index_constraint_usage = sqlite3_index_constraint_usage
)

20
vendor/modernc.org/sqlite/lib/hooks.go generated vendored Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2019 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 !(linux && arm64)
package sqlite3
import (
"modernc.org/libc"
)
// Format and write a message to the log if logging is enabled.
func X__ccgo_sqlite3_log(t *libc.TLS, iErrCode int32, zFormat uintptr, va uintptr) { /* sqlite3.c:29405:17: */
libc.X__ccgo_sqlite3_log(t, iErrCode, zFormat, va)
}
func PatchIssue199() {
// nop
}

30
vendor/modernc.org/sqlite/lib/hooks_linux_arm64.go generated vendored Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2019 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.
package sqlite3
import (
"syscall"
"unsafe"
"modernc.org/libc"
)
// Format and write a message to the log if logging is enabled.
func X__ccgo_sqlite3_log(t *libc.TLS, iErrCode int32, zFormat uintptr, va uintptr) { /* sqlite3.c:29405:17: */
libc.X__ccgo_sqlite3_log(t, iErrCode, zFormat, va)
}
// https://gitlab.com/cznic/sqlite/-/issues/199
//
// We are currently stuck on libc@v1.55.3. Until that is resolved - fix the
// problem at runtime.
func PatchIssue199() {
p := unsafe.Pointer(&_aSyscall)
*(*uintptr)(unsafe.Add(p, 608)) = __ccgo_fp(_unixGetpagesizeIssue199)
}
func _unixGetpagesizeIssue199(tls *libc.TLS) (r int32) {
return int32(syscall.Getpagesize())
}

345
vendor/modernc.org/sqlite/lib/mutex.go generated vendored Normal file
View File

@@ -0,0 +1,345 @@
// Copyright 2021 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 !linux
package sqlite3
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
"modernc.org/libc"
"modernc.org/libc/sys/types"
)
func init() {
tls := libc.NewTLS()
if Xsqlite3_threadsafe(tls) == 0 {
panic(fmt.Errorf("sqlite: thread safety configuration error"))
}
varArgs := libc.Xmalloc(tls, types.Size_t(unsafe.Sizeof(uintptr(0))))
if varArgs == 0 {
panic(fmt.Errorf("cannot allocate memory"))
}
// int sqlite3_config(int, ...);
if rc := Xsqlite3_config(tls, SQLITE_CONFIG_MUTEX, libc.VaList(varArgs, uintptr(unsafe.Pointer(&mutexMethods)))); rc != SQLITE_OK {
p := Xsqlite3_errstr(tls, rc)
str := libc.GoString(p)
panic(fmt.Errorf("sqlite: failed to configure mutex methods: %v", str))
}
libc.Xfree(tls, varArgs)
tls.Close()
}
var (
mutexMethods = Sqlite3_mutex_methods{
FxMutexInit: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS) int32 }{mutexInit})),
FxMutexEnd: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS) int32 }{mutexEnd})),
FxMutexAlloc: *(*uintptr)(unsafe.Pointer(&struct {
f func(*libc.TLS, int32) uintptr
}{mutexAlloc})),
FxMutexFree: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexFree})),
FxMutexEnter: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexEnter})),
FxMutexTry: *(*uintptr)(unsafe.Pointer(&struct {
f func(*libc.TLS, uintptr) int32
}{mutexTry})),
FxMutexLeave: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexLeave})),
FxMutexHeld: *(*uintptr)(unsafe.Pointer(&struct {
f func(*libc.TLS, uintptr) int32
}{mutexHeld})),
FxMutexNotheld: *(*uintptr)(unsafe.Pointer(&struct {
f func(*libc.TLS, uintptr) int32
}{mutexNotheld})),
}
mutexApp10 mutex
mutexApp20 mutex
mutexApp30 mutex
mutexLRU0 mutex
mutexMaster0 mutex
mutexMem0 mutex
mutexOpen0 mutex
mutexPMem0 mutex
mutexPRNG0 mutex
mutexVFS10 mutex
mutexVFS20 mutex
mutexVFS30 mutex
mutexApp1 = uintptr(unsafe.Pointer(&mutexApp10))
mutexApp2 = uintptr(unsafe.Pointer(&mutexApp20))
mutexApp3 = uintptr(unsafe.Pointer(&mutexApp30))
mutexLRU = uintptr(unsafe.Pointer(&mutexLRU0))
mutexMaster = uintptr(unsafe.Pointer(&mutexMaster0))
mutexMem = uintptr(unsafe.Pointer(&mutexMem0))
mutexOpen = uintptr(unsafe.Pointer(&mutexOpen0))
mutexPMem = uintptr(unsafe.Pointer(&mutexPMem0))
mutexPRNG = uintptr(unsafe.Pointer(&mutexPRNG0))
mutexVFS1 = uintptr(unsafe.Pointer(&mutexVFS10))
mutexVFS2 = uintptr(unsafe.Pointer(&mutexVFS20))
mutexVFS3 = uintptr(unsafe.Pointer(&mutexVFS30))
)
type mutex struct {
sync.Mutex
cnt int32
id int32 // tls.ID
recursive bool
}
// int (*xMutexInit)(void);
//
// The xMutexInit method defined by this structure is invoked as part of system
// initialization by the sqlite3_initialize() function. The xMutexInit routine
// is called by SQLite exactly once for each effective call to
// sqlite3_initialize().
//
// The xMutexInit() method must be threadsafe. It must be harmless to invoke
// xMutexInit() multiple times within the same process and without intervening
// calls to xMutexEnd(). Second and subsequent calls to xMutexInit() must be
// no-ops. xMutexInit() must not use SQLite memory allocation (sqlite3_malloc()
// and its associates).
//
// If xMutexInit fails in any way, it is expected to clean up after itself
// prior to returning.
func mutexInit(tls *libc.TLS) int32 { return SQLITE_OK }
// int (*xMutexEnd)(void);
func mutexEnd(tls *libc.TLS) int32 { return SQLITE_OK }
// sqlite3_mutex *(*xMutexAlloc)(int);
//
// The sqlite3_mutex_alloc() routine allocates a new mutex and returns a
// pointer to it. The sqlite3_mutex_alloc() routine returns NULL if it is
// unable to allocate the requested mutex. The argument to
// sqlite3_mutex_alloc() must one of these integer constants:
//
// SQLITE_MUTEX_FAST
// SQLITE_MUTEX_RECURSIVE
// SQLITE_MUTEX_STATIC_MASTER
// SQLITE_MUTEX_STATIC_MEM
// SQLITE_MUTEX_STATIC_OPEN
// SQLITE_MUTEX_STATIC_PRNG
// SQLITE_MUTEX_STATIC_LRU
// SQLITE_MUTEX_STATIC_PMEM
// SQLITE_MUTEX_STATIC_APP1
// SQLITE_MUTEX_STATIC_APP2
// SQLITE_MUTEX_STATIC_APP3
// SQLITE_MUTEX_STATIC_VFS1
// SQLITE_MUTEX_STATIC_VFS2
// SQLITE_MUTEX_STATIC_VFS3
//
// The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) cause
// sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive when
// SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
// is used. The mutex implementation does not need to make a distinction
// between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
// SQLite will only request a recursive mutex in cases where it really needs
// one. If a faster non-recursive mutex implementation is available on the host
// platform, the mutex subsystem might return such a mutex in response to
// SQLITE_MUTEX_FAST.
//
// The other allowed parameters to sqlite3_mutex_alloc() (anything other than
// SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return a pointer to a
// static preexisting mutex. Nine static mutexes are used by the current
// version of SQLite. Future versions of SQLite may add additional static
// mutexes. Static mutexes are for internal use by SQLite only. Applications
// that use SQLite mutexes should use only the dynamic mutexes returned by
// SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE.
//
// Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or
// SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() returns a
// different mutex on every call. For the static mutex types, the same mutex is
// returned on every call that has the same type number.
func mutexAlloc(tls *libc.TLS, typ int32) (r uintptr) {
switch typ {
case SQLITE_MUTEX_FAST:
r = libc.Xcalloc(tls, 1, types.Size_t(unsafe.Sizeof(mutex{})))
return r
case SQLITE_MUTEX_RECURSIVE:
r = libc.Xcalloc(tls, 1, types.Size_t(unsafe.Sizeof(mutex{})))
(*mutex)(unsafe.Pointer(r)).recursive = true
return r
case SQLITE_MUTEX_STATIC_MASTER:
return mutexMaster
case SQLITE_MUTEX_STATIC_MEM:
return mutexMem
case SQLITE_MUTEX_STATIC_OPEN:
return mutexOpen
case SQLITE_MUTEX_STATIC_PRNG:
return mutexPRNG
case SQLITE_MUTEX_STATIC_LRU:
return mutexLRU
case SQLITE_MUTEX_STATIC_PMEM:
return mutexPMem
case SQLITE_MUTEX_STATIC_APP1:
return mutexApp1
case SQLITE_MUTEX_STATIC_APP2:
return mutexApp2
case SQLITE_MUTEX_STATIC_APP3:
return mutexApp3
case SQLITE_MUTEX_STATIC_VFS1:
return mutexVFS1
case SQLITE_MUTEX_STATIC_VFS2:
return mutexVFS2
case SQLITE_MUTEX_STATIC_VFS3:
return mutexVFS3
default:
return 0
}
}
// void (*xMutexFree)(sqlite3_mutex *);
func mutexFree(tls *libc.TLS, m uintptr) {
libc.Xfree(tls, m)
}
// The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt to enter
// a mutex. If another thread is already within the mutex,
// sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
// SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK upon
// successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can be
// entered multiple times by the same thread. In such cases, the mutex must be
// exited an equal number of times before another thread can enter. If the same
// thread tries to enter any mutex other than an SQLITE_MUTEX_RECURSIVE more
// than once, the behavior is undefined.
//
// If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
// sqlite3_mutex_leave() is a NULL pointer, then all three routines behave as
// no-ops.
// void (*xMutexEnter)(sqlite3_mutex *);
func mutexEnter(tls *libc.TLS, m uintptr) {
if m == 0 {
return
}
// Non-recursive mutex: Standard Go lock
if !(*mutex)(unsafe.Pointer(m)).recursive {
(*mutex)(unsafe.Pointer(m)).Lock()
atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, tls.ID)
return
}
// Recursive mutex: Check if we already own it (Fast Path)
// We can safely read ptr.id without a lock here because if it equals tls.ID,
// WE are the writer, so no other thread can be changing it.
if atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) == tls.ID {
(*mutex)(unsafe.Pointer(m)).cnt++
return
}
// We don't own it. Acquire physical lock (Slow Path).
// This blocks until the mutex is free.
(*mutex)(unsafe.Pointer(m)).Lock()
// Now that we have the lock, claim ownership.
atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, tls.ID)
(*mutex)(unsafe.Pointer(m)).cnt = 1
}
// int (*xMutexTry)(sqlite3_mutex *);
func mutexTry(tls *libc.TLS, m uintptr) int32 {
if m == 0 {
return SQLITE_OK
}
// Non-recursive mutex
if !(*mutex)(unsafe.Pointer(m)).recursive {
if (*mutex)(unsafe.Pointer(m)).TryLock() {
(*mutex)(unsafe.Pointer(m)).id = tls.ID
return SQLITE_OK
}
return SQLITE_BUSY
}
// Recursive mutex: Check if we already own it (Fast Path)
if atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) == tls.ID {
(*mutex)(unsafe.Pointer(m)).cnt++
return SQLITE_OK
}
// Try to acquire physical lock
if (*mutex)(unsafe.Pointer(m)).TryLock() {
atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, tls.ID)
(*mutex)(unsafe.Pointer(m)).cnt = 1
return SQLITE_OK
}
return SQLITE_BUSY
}
// void (*xMutexLeave)(sqlite3_mutex *);
func mutexLeave(tls *libc.TLS, m uintptr) {
if m == 0 {
return
}
// Non-recursive mutex
if !(*mutex)(unsafe.Pointer(m)).recursive {
atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, 0)
(*mutex)(unsafe.Pointer(m)).Unlock()
return
}
// Recursive mutex: Decrement count
(*mutex)(unsafe.Pointer(m)).cnt--
// If count reaches zero, we are fully releasing the mutex.
if (*mutex)(unsafe.Pointer(m)).cnt == 0 {
atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, 0)
(*mutex)(unsafe.Pointer(m)).Unlock()
}
}
// The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines are intended
// for use inside assert() statements. The SQLite core never uses these
// routines except inside an assert() and applications are advised to follow
// the lead of the core. The SQLite core only provides implementations for
// these routines when it is compiled with the SQLITE_DEBUG flag. External
// mutex implementations are only required to provide these routines if
// SQLITE_DEBUG is defined and if NDEBUG is not defined.
//
// These routines should return true if the mutex in their argument is held or
// not held, respectively, by the calling thread.
//
// The implementation is not required to provide versions of these routines
// that actually work. If the implementation does not provide working versions
// of these routines, it should at least provide stubs that always return true
// so that one does not get spurious assertion failures.
//
// If the argument to sqlite3_mutex_held() is a NULL pointer then the routine
// should return 1. This seems counter-intuitive since clearly the mutex cannot
// be held if it does not exist. But the reason the mutex does not exist is
// because the build is not using mutexes. And we do not want the assert()
// containing the call to sqlite3_mutex_held() to fail, so a non-zero return is
// the appropriate thing to do. The sqlite3_mutex_notheld() interface should
// also return 1 when given a NULL pointer.
// int (*xMutexHeld)(sqlite3_mutex *);
func mutexHeld(tls *libc.TLS, m uintptr) int32 {
if m == 0 {
return 1
}
// atomic.Load is required because we might be checking a mutex
// that we do not own (and thus another thread might be writing to).
return libc.Bool32(atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) == tls.ID)
}
// int (*xMutexNotheld)(sqlite3_mutex *);
func mutexNotheld(tls *libc.TLS, m uintptr) int32 {
if m == 0 {
return 1
}
// Returns True if ID is Zero (unheld) OR ID is some other thread's ID.
return libc.Bool32(atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) != tls.ID)
}

228964
vendor/modernc.org/sqlite/lib/sqlite_darwin_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

228537
vendor/modernc.org/sqlite/lib/sqlite_darwin_arm64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

153539
vendor/modernc.org/sqlite/lib/sqlite_freebsd_386.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222700
vendor/modernc.org/sqlite/lib/sqlite_freebsd_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

153633
vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222713
vendor/modernc.org/sqlite/lib/sqlite_freebsd_arm64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222858
vendor/modernc.org/sqlite/lib/sqlite_linux_386.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222871
vendor/modernc.org/sqlite/lib/sqlite_linux_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

223158
vendor/modernc.org/sqlite/lib/sqlite_linux_arm.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222861
vendor/modernc.org/sqlite/lib/sqlite_linux_arm64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222960
vendor/modernc.org/sqlite/lib/sqlite_linux_loong64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222908
vendor/modernc.org/sqlite/lib/sqlite_linux_ppc64le.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222836
vendor/modernc.org/sqlite/lib/sqlite_linux_riscv64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

222808
vendor/modernc.org/sqlite/lib/sqlite_linux_s390x.go generated vendored Normal file

File diff suppressed because one or more lines are too long

151230
vendor/modernc.org/sqlite/lib/sqlite_netbsd_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

221978
vendor/modernc.org/sqlite/lib/sqlite_openbsd_amd64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

221994
vendor/modernc.org/sqlite/lib/sqlite_openbsd_arm64.go generated vendored Normal file

File diff suppressed because one or more lines are too long

296206
vendor/modernc.org/sqlite/lib/sqlite_windows.go generated vendored Normal file

File diff suppressed because one or more lines are too long

296101
vendor/modernc.org/sqlite/lib/sqlite_windows_386.go generated vendored Normal file

File diff suppressed because one or more lines are too long

BIN
vendor/modernc.org/sqlite/logo.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

23
vendor/modernc.org/sqlite/mutex.go generated vendored Normal file
View File

@@ -0,0 +1,23 @@
// Copyright 2019 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.
package sqlite // import "modernc.org/sqlite"
import (
"sync"
"unsafe"
"modernc.org/libc"
"modernc.org/libc/sys/types"
)
type mutex struct {
sync.Mutex
}
func mutexAlloc(tls *libc.TLS) uintptr {
return libc.Xcalloc(tls, 1, types.Size_t(unsafe.Sizeof(mutex{})))
}
func mutexFree(tls *libc.TLS, m uintptr) { libc.Xfree(tls, m) }

12
vendor/modernc.org/sqlite/nodmesg.go generated vendored Normal file
View File

@@ -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{}) {}

10
vendor/modernc.org/sqlite/norlimit.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
// Copyright 2021 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 windows
// +build windows
package sqlite // import "modernc.org/sqlite"
func setMaxOpenFiles(n int) error { return nil }

227
vendor/modernc.org/sqlite/pre_update_hook.go generated vendored Normal file
View File

@@ -0,0 +1,227 @@
package sqlite
import (
"errors"
"fmt"
"sync"
"unsafe"
"modernc.org/libc"
"modernc.org/libc/sys/types"
sqlite3 "modernc.org/sqlite/lib"
)
var (
xPreUpdateHandlers = struct {
mu sync.RWMutex
m map[uintptr]func(SQLitePreUpdateData)
}{
m: make(map[uintptr]func(SQLitePreUpdateData)),
}
xCommitHandlers = struct {
mu sync.RWMutex
m map[uintptr]CommitHookFn
}{
m: make(map[uintptr]CommitHookFn),
}
xRollbackHandlers = struct {
mu sync.RWMutex
m map[uintptr]RollbackHookFn
}{
m: make(map[uintptr]RollbackHookFn),
}
)
type PreUpdateHookFn func(SQLitePreUpdateData)
func (c *conn) RegisterPreUpdateHook(callback PreUpdateHookFn) {
if callback == nil {
xPreUpdateHandlers.mu.Lock()
delete(xPreUpdateHandlers.m, c.db)
xPreUpdateHandlers.mu.Unlock()
sqlite3.Xsqlite3_preupdate_hook(c.tls, c.db, uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(nil)))
return
}
xPreUpdateHandlers.mu.Lock()
xPreUpdateHandlers.m[c.db] = callback
xPreUpdateHandlers.mu.Unlock()
sqlite3.Xsqlite3_preupdate_hook(c.tls, c.db, cFuncPointer(preUpdateHookTrampoline), c.db)
}
type CommitHookFn func() int32
func (c *conn) RegisterCommitHook(callback CommitHookFn) {
if callback == nil {
xCommitHandlers.mu.Lock()
delete(xCommitHandlers.m, c.db)
xCommitHandlers.mu.Unlock()
sqlite3.Xsqlite3_commit_hook(c.tls, c.db, uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(nil)))
return
}
xCommitHandlers.mu.Lock()
xCommitHandlers.m[c.db] = callback
xCommitHandlers.mu.Unlock()
sqlite3.Xsqlite3_commit_hook(c.tls, c.db, cFuncPointer(commitHookTrampoline), c.db)
}
type RollbackHookFn func()
func (c *conn) RegisterRollbackHook(callback RollbackHookFn) {
if callback == nil {
xRollbackHandlers.mu.Lock()
delete(xRollbackHandlers.m, c.db)
xRollbackHandlers.mu.Unlock()
sqlite3.Xsqlite3_rollback_hook(c.tls, c.db, uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(nil)))
return
}
xRollbackHandlers.mu.Lock()
xRollbackHandlers.m[c.db] = callback
xRollbackHandlers.mu.Unlock()
sqlite3.Xsqlite3_rollback_hook(c.tls, c.db, cFuncPointer(rollbackHookTrampoline), c.db)
}
type SQLitePreUpdateData struct {
tls *libc.TLS
pCsr uintptr
Op int32
DatabaseName string
TableName string
OldRowID int64
NewRowID int64
}
// Depth returns the source path of the write, see sqlite3_preupdate_depth()
func (d *SQLitePreUpdateData) Depth() int {
return int(sqlite3.Xsqlite3_preupdate_depth(d.tls, d.pCsr))
}
// Count returns the number of columns in the row
func (d *SQLitePreUpdateData) Count() int {
return int(sqlite3.Xsqlite3_preupdate_count(d.tls, d.pCsr))
}
func (d *SQLitePreUpdateData) row(dest []any, new bool) error {
count := d.Count()
ppValue, err := mallocValue(d.tls)
if err != nil {
return err
}
defer libc.Xfree(d.tls, ppValue)
for i := 0; i < count && i < len(dest); i++ {
val, err := d.value(ppValue, i, new)
if err != nil {
return err
}
err = convertAssign(&dest[i], val)
if err != nil {
return err
}
}
return nil
}
// Old populates dest with the row data to be replaced. This works similar to
// database/sql's Rows.Scan()
func (d *SQLitePreUpdateData) Old(dest ...any) error {
if d.Op == sqlite3.SQLITE_INSERT {
return errors.New("there is no old row for INSERT operations")
}
return d.row(dest, false)
}
// New populates dest with the replacement row data. This works similar to
// database/sql's Rows.Scan()
func (d *SQLitePreUpdateData) New(dest ...any) error {
if d.Op == sqlite3.SQLITE_DELETE {
return errors.New("there is no new row for DELETE operations")
}
return d.row(dest, true)
}
const ptrValSize = types.Size_t(unsafe.Sizeof(&sqlite3.Sqlite3_value{}))
func mallocValue(tls *libc.TLS) (uintptr, error) {
p := libc.Xmalloc(tls, ptrValSize)
if p == 0 {
return 0, fmt.Errorf("out of memory")
}
return p, nil
}
func (d *SQLitePreUpdateData) value(ppValue uintptr, i int, new bool) (any, error) {
var src any
if new {
sqlite3.Xsqlite3_preupdate_new(d.tls, d.pCsr, int32(i), ppValue)
} else {
sqlite3.Xsqlite3_preupdate_old(d.tls, d.pCsr, int32(i), ppValue)
}
ptrValue := *(*uintptr)(unsafe.Pointer(ppValue))
switch sqlite3.Xsqlite3_value_type(d.tls, ptrValue) {
case sqlite3.SQLITE_INTEGER:
src = int64(sqlite3.Xsqlite3_value_int64(d.tls, ptrValue))
case sqlite3.SQLITE_FLOAT:
src = float64(sqlite3.Xsqlite3_value_double(d.tls, ptrValue))
case sqlite3.SQLITE_BLOB:
size := sqlite3.Xsqlite3_value_bytes(d.tls, ptrValue)
blobPtr := sqlite3.Xsqlite3_value_blob(d.tls, ptrValue)
var v []byte
if size != 0 {
v = make([]byte, size)
copy(v, (*libc.RawMem)(unsafe.Pointer(blobPtr))[:size:size])
}
src = v
case sqlite3.SQLITE_TEXT:
src = libc.GoString(sqlite3.Xsqlite3_value_text(d.tls, ptrValue))
case sqlite3.SQLITE_NULL:
src = nil
}
return src, nil
}
func preUpdateHookTrampoline(tls *libc.TLS, handle uintptr, pCsr uintptr, op int32, zDb uintptr, pTab uintptr, iKey1 int64, iReg int32, iBlobWrite int32) {
xPreUpdateHandlers.mu.RLock()
xPreUpdateHandler := xPreUpdateHandlers.m[handle]
xPreUpdateHandlers.mu.RUnlock()
if xPreUpdateHandler == nil {
return
}
data := SQLitePreUpdateData{
tls: tls,
pCsr: pCsr,
Op: op,
DatabaseName: libc.GoString(zDb),
TableName: libc.GoString(pTab),
OldRowID: iKey1,
NewRowID: int64(iReg),
}
xPreUpdateHandler(data)
}
func commitHookTrampoline(tls *libc.TLS, handle uintptr, pCsr uintptr) int32 {
xCommitHandlers.mu.RLock()
xCommitHandler := xCommitHandlers.m[handle]
xCommitHandlers.mu.RUnlock()
if xCommitHandler == nil {
return 0
}
return xCommitHandler()
}
func rollbackHookTrampoline(tls *libc.TLS, handle uintptr, pCsr uintptr) {
xRollbackHandlers.mu.RLock()
xRollbackHandler := xRollbackHandlers.m[handle]
xRollbackHandlers.mu.RUnlock()
if xRollbackHandler == nil {
return
}
xRollbackHandler()
}

42
vendor/modernc.org/sqlite/result.go generated vendored Normal file
View File

@@ -0,0 +1,42 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
type result struct {
lastInsertID int64
rowsAffected int
}
func newResult(c *conn) (_ *result, err error) {
r := &result{}
if r.rowsAffected, err = c.changes(); err != nil {
return nil, err
}
if r.lastInsertID, err = c.lastInsertRowID(); err != nil {
return nil, err
}
return r, nil
}
// LastInsertId returns the database's auto-generated ID after, for example, an
// INSERT into a table with primary key.
func (r *result) LastInsertId() (int64, error) {
if r == nil {
return 0, nil
}
return r.lastInsertID, nil
}
// RowsAffected returns the number of rows affected by the query.
func (r *result) RowsAffected() (int64, error) {
if r == nil {
return 0, nil
}
return int64(r.rowsAffected), nil
}

19
vendor/modernc.org/sqlite/rlimit.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// Copyright 2021 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 freebsd
// +build freebsd
package sqlite // import "modernc.org/sqlite"
import (
"golang.org/x/sys/unix"
)
func setMaxOpenFiles(n int64) error {
var rLimit unix.Rlimit
rLimit.Max = n
rLimit.Cur = n
return unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit)
}

297
vendor/modernc.org/sqlite/rows.go generated vendored Normal file
View File

@@ -0,0 +1,297 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"database/sql/driver"
"fmt"
"io"
"math"
"reflect"
"strings"
"time"
sqlite3 "modernc.org/sqlite/lib"
)
type rows struct {
allocs []uintptr
c *conn
columns []string
pstmt uintptr
doStep bool
empty bool
reuseStmt bool // If true, Close() resets instead of finalizing
}
func newRows(c *conn, pstmt uintptr, allocs []uintptr, empty bool) (r *rows, err error) {
r = &rows{c: c, pstmt: pstmt, allocs: allocs, empty: empty}
defer func() {
if err != nil {
r.Close()
r = nil
}
}()
n, err := c.columnCount(pstmt)
if err != nil {
return nil, err
}
r.columns = make([]string, n)
for i := range r.columns {
if r.columns[i], err = r.c.columnName(pstmt, i); err != nil {
return nil, err
}
}
return r, nil
}
// Close closes the rows iterator.
func (r *rows) Close() (err error) {
for _, v := range r.allocs {
r.c.free(v)
}
r.allocs = nil
if r.reuseStmt {
// Reset the statement for reuse instead of finalizing it
if e := r.c.reset(r.pstmt); e != nil {
return e
}
return r.c.clearBindings(r.pstmt)
}
return r.c.finalize(r.pstmt)
}
// Columns returns the names of the columns. The number of columns of the
// result is inferred from the length of the slice. If a particular column name
// isn't known, an empty string should be returned for that entry.
func (r *rows) Columns() (c []string) {
return r.columns
}
// Next is called to populate the next row of data into the provided slice. The
// provided slice will be the same size as the Columns() are wide.
//
// Next should return io.EOF when there are no more rows.
func (r *rows) Next(dest []driver.Value) (err error) {
if r.empty {
return io.EOF
}
rc := sqlite3.SQLITE_ROW
if r.doStep {
if rc, err = r.c.step(r.pstmt); err != nil {
return err
}
}
r.doStep = true
switch rc {
case sqlite3.SQLITE_ROW:
if g, e := len(dest), len(r.columns); g != e {
return fmt.Errorf("sqlite: Next: have %v destination values, expected %v", g, e)
}
for i := range dest {
ct, err := r.c.columnType(r.pstmt, i)
if err != nil {
return err
}
switch ct {
case sqlite3.SQLITE_INTEGER:
v, err := r.c.columnInt64(r.pstmt, i)
if err != nil {
return err
}
if !r.c.intToTime {
dest[i] = v
} else {
// Inspired by mattn/go-sqlite3:
// https://github.com/mattn/go-sqlite3/blob/f76bae4b0044cbba8fb2c72b8e4559e8fbcffd86/sqlite3.go#L2254-L2262
// but we put make this compatibility optional behind a DSN
// query parameter, because this changes API behavior, so an
// opt-in is needed.
switch r.ColumnTypeDatabaseTypeName(i) {
case "DATE", "DATETIME", "TIMESTAMP":
// Check for explicit opt-in first. This fixes the bug for micro/nano users
// without breaking the legacy heuristic for existing users.
switch r.c.integerTimeFormat {
case "unix_micro":
dest[i] = time.UnixMicro(v).UTC()
continue
case "unix_nano":
dest[i] = time.Unix(0, v).UTC()
continue
}
// Legacy Heuristic (mattn/go-sqlite3 compatibility). NOTE: This heuristic
// fails for Millisecond timestamps representing dates before Sept 9, 2001
// (value < 1e12).
// Is it a seconds timestamp or a milliseconds
// timestamp?
if v > 1e12 || v < -1e12 {
// Milliseconds
dest[i] = time.UnixMilli(v).UTC()
} else {
// Seconds
dest[i] = time.Unix(v, 0).UTC()
}
default:
dest[i] = v
}
}
case sqlite3.SQLITE_FLOAT:
v, err := r.c.columnDouble(r.pstmt, i)
if err != nil {
return err
}
dest[i] = v
case sqlite3.SQLITE_TEXT:
v, err := r.c.columnText(r.pstmt, i)
if err != nil {
return err
}
switch r.ColumnTypeDatabaseTypeName(i) {
case "DATE", "DATETIME", "TIMESTAMP":
dest[i], _ = r.c.parseTime(v)
default:
dest[i] = v
}
case sqlite3.SQLITE_BLOB:
v, err := r.c.columnBlob(r.pstmt, i)
if err != nil {
return err
}
dest[i] = v
case sqlite3.SQLITE_NULL:
dest[i] = nil
default:
return fmt.Errorf("internal error: rc %d", rc)
}
}
return nil
case sqlite3.SQLITE_DONE:
return io.EOF
default:
return r.c.errstr(int32(rc))
}
}
// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return
// the database system type name without the length. Type names should be
// uppercase. Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2",
// "CHAR", "TEXT", "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT",
// "JSONB", "XML", "TIMESTAMP".
func (r *rows) ColumnTypeDatabaseTypeName(index int) string {
return strings.ToUpper(r.c.columnDeclType(r.pstmt, index))
}
// RowsColumnTypeLength may be implemented by Rows. It should return the length
// of the column type if the column is a variable length type. If the column is
// not a variable length type ok should return false. If length is not limited
// other than system limits, it should return math.MaxInt64. The following are
// examples of returned values for various types:
//
// TEXT (math.MaxInt64, true)
// varchar(10) (10, true)
// nvarchar(10) (10, true)
// decimal (0, false)
// int (0, false)
// bytea(30) (30, true)
func (r *rows) ColumnTypeLength(index int) (length int64, ok bool) {
t, err := r.c.columnType(r.pstmt, index)
if err != nil {
return 0, false
}
switch t {
case sqlite3.SQLITE_INTEGER:
return 0, false
case sqlite3.SQLITE_FLOAT:
return 0, false
case sqlite3.SQLITE_TEXT:
return math.MaxInt64, true
case sqlite3.SQLITE_BLOB:
return math.MaxInt64, true
case sqlite3.SQLITE_NULL:
return 0, false
default:
return 0, false
}
}
// RowsColumnTypeNullable may be implemented by Rows. The nullable value should
// be true if it is known the column may be null, or false if the column is
// known to be not nullable. If the column nullability is unknown, ok should be
// false.
func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) {
return true, true
}
// RowsColumnTypePrecisionScale may be implemented by Rows. It should return
// the precision and scale for decimal types. If not applicable, ok should be
// false. The following are examples of returned values for various types:
//
// decimal(38, 4) (38, 4, true)
// int (0, 0, false)
// decimal (math.MaxInt64, math.MaxInt64, true)
func (r *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
return 0, 0, false
}
// RowsColumnTypeScanType may be implemented by Rows. It should return the
// value type that can be used to scan types into. For example, the database
// column type "bigint" this should return "reflect.TypeOf(int64(0))".
func (r *rows) ColumnTypeScanType(index int) reflect.Type {
t, err := r.c.columnType(r.pstmt, index)
if err != nil {
return reflect.TypeOf("")
}
switch t {
case sqlite3.SQLITE_INTEGER:
switch strings.ToLower(r.c.columnDeclType(r.pstmt, index)) {
case "boolean":
return reflect.TypeOf(false)
case "date", "datetime", "time", "timestamp":
return reflect.TypeOf(time.Time{})
default:
return reflect.TypeOf(int64(0))
}
case sqlite3.SQLITE_FLOAT:
return reflect.TypeOf(float64(0))
case sqlite3.SQLITE_TEXT:
return reflect.TypeOf("")
case sqlite3.SQLITE_BLOB:
return reflect.TypeOf([]byte(nil))
case sqlite3.SQLITE_NULL:
return reflect.TypeOf(nil)
default:
return reflect.TypeOf("")
}
}
// C documentation
//
// int sqlite3_reset(sqlite3_stmt *pStmt);
func (c *conn) reset(pstmt uintptr) error {
if rc := sqlite3.Xsqlite3_reset(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
return c.errstr(rc)
}
return nil
}

19
vendor/modernc.org/sqlite/rulimit.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// Copyright 2021 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 linux || darwin || netbsd || openbsd
// +build linux darwin netbsd openbsd
package sqlite // import "modernc.org/sqlite"
import (
"golang.org/x/sys/unix"
)
func setMaxOpenFiles(n int64) error {
var rLimit unix.Rlimit
rLimit.Max = uint64(n)
rLimit.Cur = uint64(n)
return unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit)
}

883
vendor/modernc.org/sqlite/sqlite.go generated vendored Normal file
View File

@@ -0,0 +1,883 @@
// Copyright 2017 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:generate go run generator.go -full-path-comments
package sqlite // import "modernc.org/sqlite"
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"math/bits"
"net/url"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"unsafe"
"modernc.org/libc"
"modernc.org/libc/sys/types"
sqlite3 "modernc.org/sqlite/lib"
)
var (
_ driver.Conn = (*conn)(nil)
_ driver.Driver = (*Driver)(nil)
//lint:ignore SA1019 TODO implement ExecerContext
_ driver.Execer = (*conn)(nil)
//lint:ignore SA1019 TODO implement QueryerContext
_ driver.Queryer = (*conn)(nil)
_ driver.Result = (*result)(nil)
_ driver.Rows = (*rows)(nil)
_ driver.RowsColumnTypeDatabaseTypeName = (*rows)(nil)
_ driver.RowsColumnTypeLength = (*rows)(nil)
_ driver.RowsColumnTypeNullable = (*rows)(nil)
_ driver.RowsColumnTypePrecisionScale = (*rows)(nil)
_ driver.RowsColumnTypeScanType = (*rows)(nil)
_ driver.Stmt = (*stmt)(nil)
_ driver.Tx = (*tx)(nil)
_ error = (*Error)(nil)
)
const (
driverName = "sqlite"
ptrSize = unsafe.Sizeof(uintptr(0))
sqliteLockedSharedcache = sqlite3.SQLITE_LOCKED | (1 << 8)
)
func init() {
sql.Register(driverName, newDriver())
sqlite3.PatchIssue199() // https://gitlab.com/cznic/sqlite/-/issues/199
}
// Inspired by mattn/go-sqlite3: https://github.com/mattn/go-sqlite3/blob/ab91e934/sqlite3.go#L210-L226
//
// These time.Parse formats handle formats 1 through 7 listed at https://www.sqlite.org/lang_datefunc.html.
var parseTimeFormats = []string{
"2006-01-02 15:04:05.999999999-07:00",
"2006-01-02T15:04:05.999999999-07:00",
"2006-01-02 15:04:05.999999999",
"2006-01-02T15:04:05.999999999",
"2006-01-02 15:04",
"2006-01-02T15:04",
"2006-01-02",
}
// interruptOnDone sets up a goroutine to interrupt the provided db when the
// context is canceled, and returns a function the caller must defer so it
// doesn't interrupt after the caller finishes.
func interruptOnDone(
ctx context.Context,
c *conn,
done *int32,
) func() {
if done == nil {
var d int32
done = &d
}
// donemu prevents a TOCTOU logical race between checking the done flag and
// calling interrupt in the select statement below.
var donemu sync.Mutex
donech := make(chan struct{})
go func() {
select {
case <-ctx.Done():
// don't call interrupt if we were already done: it indicates that this
// call to exec is no longer running and we would be interrupting
// nothing, or even possibly an unrelated later call to exec.
donemu.Lock()
if atomic.CompareAndSwapInt32(done, 0, 1) {
c.interrupt(c.db)
}
donemu.Unlock()
case <-donech:
}
}()
// the caller is expected to defer this function
return func() {
// set the done flag so that a context cancellation right after the caller
// returns doesn't trigger a call to interrupt for some other statement.
donemu.Lock()
atomic.StoreInt32(done, 1)
donemu.Unlock()
close(donech)
}
}
func getVFSName(query string) (r string, err error) {
q, err := url.ParseQuery(query)
if err != nil {
return "", err
}
for _, v := range q["vfs"] {
if r != "" && r != v {
return "", fmt.Errorf("conflicting vfs query parameters: %v", q["vfs"])
}
r = v
}
return r, nil
}
func applyQueryParams(c *conn, query string) error {
q, err := url.ParseQuery(query)
if err != nil {
return err
}
var a []string
for _, v := range q["_pragma"] {
a = append(a, v)
}
// Push 'busy_timeout' first, the rest in lexicographic order, case insenstive.
// See https://gitlab.com/cznic/sqlite/-/issues/198#note_2233423463 for
// discussion.
sort.Slice(a, func(i, j int) bool {
x, y := strings.TrimSpace(strings.ToLower(a[i])), strings.TrimSpace(strings.ToLower(a[j]))
if strings.HasPrefix(x, "busy_timeout") {
return true
}
if strings.HasPrefix(y, "busy_timeout") {
return false
}
return x < y
})
for _, v := range a {
cmd := "pragma " + v
_, err := c.exec(context.Background(), cmd, nil)
if err != nil {
return err
}
}
if v := q.Get("_time_format"); v != "" {
f, ok := writeTimeFormats[v]
if !ok {
return fmt.Errorf("unknown _time_format %q", v)
}
c.writeTimeFormat = f
}
if v := q.Get("_time_integer_format"); v != "" {
switch v {
case "unix":
case "unix_milli":
case "unix_micro":
case "unix_nano":
default:
return fmt.Errorf("unknown _time_integer_format %q", v)
}
c.integerTimeFormat = v
}
if v := q.Get("_txlock"); v != "" {
lower := strings.ToLower(v)
if lower != "deferred" && lower != "immediate" && lower != "exclusive" {
return fmt.Errorf("unknown _txlock %q", v)
}
c.beginMode = v
}
if v := q.Get("_inttotime"); v != "" {
onoff, err := strconv.ParseBool(v)
if err != nil {
return fmt.Errorf("unknown _inttotime %q, must be 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False",
v)
}
c.intToTime = onoff
}
return nil
}
func unlockNotify(t *libc.TLS, ppArg uintptr, nArg int32) {
for i := int32(0); i < nArg; i++ {
mu := *(*uintptr)(unsafe.Pointer(ppArg))
(*mutex)(unsafe.Pointer(mu)).Unlock()
ppArg += ptrSize
}
}
// 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 collation struct {
zName uintptr
pApp uintptr
enc int32
}
// RegisterCollationUtf8 makes a Go function available as a collation named zName.
// impl receives two UTF-8 strings: left and right.
// The result needs to be:
//
// - 0 if left == right
// - 1 if left < right
// - +1 if left > right
//
// impl must always return the same result given the same inputs.
// Additionally, it must have the following properties for all strings A, B and C:
// - if A==B, then B==A
// - if A==B and B==C, then A==C
// - if A<B, then B>A
// - if A<B and B<C, then A<C.
//
// The new collation will be available to all new connections opened after
// executing RegisterCollationUtf8.
func RegisterCollationUtf8(
zName string,
impl func(left, right string) int,
) error {
return registerCollation(zName, impl, sqlite3.SQLITE_UTF8)
}
// MustRegisterCollationUtf8 is like RegisterCollationUtf8 but panics on error.
func MustRegisterCollationUtf8(
zName string,
impl func(left, right string) int,
) {
if err := RegisterCollationUtf8(zName, impl); err != nil {
panic(err)
}
}
func registerCollation(
zName string,
impl func(left, right string) int,
enc int32,
) error {
if _, ok := d.collations[zName]; ok {
return fmt.Errorf("a collation %q is already registered", zName)
}
// dont free, collations registered on the driver live as long as the program
name, err := libc.CString(zName)
if err != nil {
return err
}
xCollations.mu.Lock()
id := xCollations.ids.next()
xCollations.m[id] = impl
xCollations.mu.Unlock()
d.collations[zName] = &collation{
zName: name,
pApp: id,
enc: enc,
}
return nil
}
type ExecQuerierContext interface {
driver.ExecerContext
driver.QueryerContext
}
type HookRegisterer interface {
RegisterPreUpdateHook(PreUpdateHookFn)
RegisterCommitHook(CommitHookFn)
RegisterRollbackHook(RollbackHookFn)
}
// ConnectionHookFn function type for a connection hook on the Driver. Connection
// hooks are called after the connection has been set up.
type ConnectionHookFn func(
conn ExecQuerierContext,
dsn string,
) 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 {
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.
//
// The new function will be available to all new connections opened after
// executing RegisterScalarFunction.
func RegisterScalarFunction(
zFuncName string,
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) (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
// error.
func MustRegisterScalarFunction(
zFuncName string,
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)
}
}
// MustRegisterDeterministicScalarFunction is like
// RegisterDeterministicScalarFunction but panics on error.
func MustRegisterDeterministicScalarFunction(
zFuncName string,
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)
}
}
// RegisterDeterministicScalarFunction registers a deterministic scalar
// function named zFuncName with nArg arguments. Passing -1 for nArg indicates
// the function is variadic. A deterministic function means that the function
// always gives the same output when the input parameters are the same.
//
// The new function will be available to all new connections opened after
// executing RegisterDeterministicScalarFunction.
func RegisterDeterministicScalarFunction(
zFuncName string,
nArg int32,
xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) (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 registerFunction(
zFuncName string,
impl *FunctionImpl,
) error {
if _, ok := d.udfs[zFuncName]; ok {
return fmt.Errorf("a function named %q is already registered", zFuncName)
}
// dont free, functions registered on the driver live as long as the program
name, err := libc.CString(zFuncName)
if err != nil {
return err
}
var textrep int32 = sqlite3.SQLITE_UTF8
if impl.Deterministic {
textrep |= sqlite3.SQLITE_DETERMINISTIC
}
udf := &userDefinedFunction{
zFuncName: name,
nArg: impl.NArgs,
eTextRep: textrep,
}
if impl.Scalar != nil {
xFuncs.mu.Lock()
id := xFuncs.ids.next()
xFuncs.m[id] = impl.Scalar
xFuncs.mu.Unlock()
udf.scalar = true
udf.pApp = id
} else {
xAggregateFactories.mu.Lock()
id := xAggregateFactories.ids.next()
xAggregateFactories.m[id] = impl.MakeAggregate
xAggregateFactories.mu.Unlock()
udf.pApp = id
}
d.udfs[zFuncName] = udf
return nil
}
// RegisterConnectionHook registers a function to be called after each connection
// is opened. This is called after all the connection has been set up.
func RegisterConnectionHook(fn ConnectionHookFn) {
d.RegisterConnectionHook(fn)
}
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)
if size != 0 {
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),
}
xCollations = struct {
mu sync.RWMutex
m map[uintptr]func(string, string) int
ids idGen
}{
m: make(map[uintptr]func(string, string) int),
}
)
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)
}
}
// sqlite3AllocCString allocates a NUL-terminated copy of s using SQLite's
// memory allocator (sqlite3_malloc). The caller must arrange for SQLite to
// free the returned pointer via sqlite3_free.
func sqlite3AllocCString(tls *libc.TLS, s string) uintptr {
n := len(s) + 1
p := sqlite3.Xsqlite3_malloc(tls, int32(n))
if p == 0 {
return 0
}
mem := (*libc.RawMem)(unsafe.Pointer(p))[:n:n]
copy(mem, []byte(s))
mem[n-1] = 0
return p
}
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)
}
func collationTrampoline(tls *libc.TLS, pApp uintptr, nLeft int32, zLeft uintptr, nRight int32, zRight uintptr) int32 {
xCollations.mu.RLock()
xCollation := xCollations.m[pApp]
xCollations.mu.RUnlock()
left := string(libc.GoBytes(zLeft, int(nLeft)))
right := string(libc.GoBytes(zRight, int(nRight)))
// res is of type int, which can be 64-bit wide
// Since we just need to know if the value is positive, negative, or zero, we can ensure it's -1, 0, +1
res := xCollation(left, right)
switch {
case res < 0:
return -1
case res == 0:
return 0
case res > 0:
return 1
default:
// Should never hit here, make the compiler happy
return 0
}
}
// Limit calls sqlite3_limit, see the docs at
// https://www.sqlite.org/c3ref/limit.html for details.
//
// To get a sql.Conn from a *sql.DB, use (*sql.DB).Conn(). Limits are bound to
// the particular instance of 'c', so getting a new connection only to pass it
// to Limit is possibly not useful above querying what are the various
// configured default values.
func Limit(c *sql.Conn, id int, newVal int) (r int, err error) {
err = c.Raw(func(driverConn any) error {
switch dc := driverConn.(type) {
case *conn:
r = dc.limit(id, newVal)
return nil
default:
return fmt.Errorf("unexpected driverConn type: %T", driverConn)
}
})
return r, err
}

472
vendor/modernc.org/sqlite/stmt.go generated vendored Normal file
View File

@@ -0,0 +1,472 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"context"
"database/sql/driver"
"sync/atomic"
"unsafe"
"modernc.org/libc"
sqlite3 "modernc.org/sqlite/lib"
)
type stmt struct {
c *conn
psql uintptr
pstmt uintptr // The cached SQLite statement handle
}
func newStmt(c *conn, sql string) (*stmt, error) {
p, err := libc.CString(sql)
if err != nil {
return nil, err
}
s := &stmt{c: c, psql: p}
// Attempt to prepare the statement immediately
// We make a copy of the pointer because prepareV2 advances it
psql := p
pstmt, err := c.prepareV2(&psql)
if err != nil {
c.free(p)
return nil, err
}
// Check if there is trailing SQL (indicating a script/multi-statement)
// If *psql (the tail) is 0, we consumed the whole string.
hasTail := *(*byte)(unsafe.Pointer(psql)) != 0
if pstmt != 0 && !hasTail {
// Optimization: Single statement. Cache it.
s.pstmt = pstmt
return s, nil
}
// It is either a script (hasTail) or a comment-only string (pstmt==0).
// For scripts: Finalize now. We will re-parse iteratively in Exec/Query
// to handle the multiple statements correctly using the existing loop logic.
if pstmt != 0 {
if err := c.finalize(pstmt); err != nil {
c.free(p)
return nil, err
}
}
return s, nil
}
// Close closes the statement.
//
// As of Go 1.1, a Stmt will not be closed if it's in use by any queries.
func (s *stmt) Close() (err error) {
if s.pstmt != 0 {
if e := s.c.finalize(s.pstmt); e != nil {
err = e
}
s.pstmt = 0
}
if s.psql != 0 {
s.c.free(s.psql)
s.psql = 0
}
return err
}
// Exec executes a query that doesn't return rows, such as an INSERT or UPDATE.
//
// Deprecated: Drivers should implement StmtExecContext instead (or
// additionally).
func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { //TODO StmtExecContext
return s.exec(context.Background(), toNamedValues(args))
}
// toNamedValues converts []driver.Value to []driver.NamedValue
func toNamedValues(vals []driver.Value) (r []driver.NamedValue) {
r = make([]driver.NamedValue, len(vals))
for i, val := range vals {
r[i] = driver.NamedValue{Value: val, Ordinal: i + 1}
}
return r
}
func (s *stmt) exec(ctx context.Context, args []driver.NamedValue) (r driver.Result, err error) {
var pstmt uintptr
var done int32
if ctx != nil {
if ctxDone := ctx.Done(); ctxDone != nil {
select {
case <-ctxDone:
return nil, ctx.Err()
default:
}
defer interruptOnDone(ctx, s.c, &done)()
}
}
defer func() {
if ctx != nil && atomic.LoadInt32(&done) != 0 {
r, err = nil, ctx.Err()
}
if pstmt != 0 {
// ensure stmt finalized.
e := s.c.finalize(pstmt)
if err == nil && e != nil {
// prioritize original
// returned error.
err = e
}
}
}()
// OPTIMIZED PATH: Single Cached Statement
if s.pstmt != 0 {
err = func() error {
// Bind
n, err := s.c.bindParameterCount(s.pstmt)
if err != nil {
return err
}
if n != 0 {
allocs, err := s.c.bind(s.pstmt, n, args)
if err != nil {
return err
}
// Free allocations after step
if len(allocs) != 0 {
defer func() {
for _, v := range allocs {
s.c.free(v)
}
}()
}
}
// Step
rc, err := s.c.step(s.pstmt)
if err != nil {
return err
}
// Handle Result
switch rc & 0xff {
case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
r, err = newResult(s.c)
default:
return s.c.errstr(int32(rc))
}
return nil
}()
// RESET (Crucial: Do not finalize)
// We must reset the VM to allow reuse.
// We also clear bindings to prevent leaking memory or state to next call.
if resetErr := s.c.reset(s.pstmt); resetErr != nil && err == nil {
err = resetErr
}
if clearErr := s.c.clearBindings(s.pstmt); clearErr != nil && err == nil {
err = clearErr
}
return r, err
}
// FALLBACK PATH: Multi-statement script
for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
if pstmt, err = s.c.prepareV2(&psql); err != nil {
return nil, err
}
if pstmt == 0 {
continue
}
err = func() (err error) {
n, err := s.c.bindParameterCount(pstmt)
if err != nil {
return err
}
if n != 0 {
allocs, err := s.c.bind(pstmt, n, args)
if err != nil {
return err
}
if len(allocs) != 0 {
defer func() {
for _, v := range allocs {
s.c.free(v)
}
}()
}
}
rc, err := s.c.step(pstmt)
if err != nil {
return err
}
switch rc & 0xff {
case sqlite3.SQLITE_DONE, sqlite3.SQLITE_ROW:
r, err = newResult(s.c)
default:
return s.c.errstr(int32(rc))
}
return nil
}()
e := s.c.finalize(pstmt)
pstmt = 0 // done with
if err == nil && e != nil {
// prioritize original
// returned error.
err = e
}
if err != nil {
return nil, err
}
}
return r, err
}
// NumInput returns the number of placeholder parameters.
//
// If NumInput returns >= 0, the sql package will sanity check argument counts
// from callers and return errors to the caller before the statement's Exec or
// Query methods are called.
//
// NumInput may also return -1, if the driver doesn't know its number of
// placeholders. In that case, the sql package will not sanity check Exec or
// Query argument counts.
func (s *stmt) NumInput() (n int) {
return -1
}
// Query executes a query that may return rows, such as a
// SELECT.
//
// Deprecated: Drivers should implement StmtQueryContext instead (or
// additionally).
func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { //TODO StmtQueryContext
return s.query(context.Background(), toNamedValues(args))
}
func (s *stmt) query(ctx context.Context, args []driver.NamedValue) (r driver.Rows, err error) {
var pstmt uintptr
var done int32
if ctx != nil {
if ctxDone := ctx.Done(); ctxDone != nil {
select {
case <-ctxDone:
return nil, ctx.Err()
default:
}
defer interruptOnDone(ctx, s.c, &done)()
}
}
var allocs []uintptr
defer func() {
if ctx != nil && atomic.LoadInt32(&done) != 0 {
if r != nil {
r.Close()
}
r, err = nil, ctx.Err()
} else if r == nil && err == nil {
r, err = newRows(s.c, pstmt, allocs, true)
}
if pstmt != 0 {
// ensure stmt finalized.
e := s.c.finalize(pstmt)
if err == nil && e != nil {
// prioritize original
// returned error.
err = e
}
}
}()
// OPTIMIZED PATH: Single Cached Statement
if s.pstmt != 0 {
// Bind
n, err := s.c.bindParameterCount(s.pstmt)
if err != nil {
return nil, err
}
if n != 0 {
if allocs, err = s.c.bind(s.pstmt, n, args); err != nil {
return nil, err
}
}
// Step
rc, err := s.c.step(s.pstmt)
if err != nil {
// On error, we must free allocs manually because 'newRows' won't take ownership
for _, v := range allocs {
s.c.free(v)
}
s.c.reset(s.pstmt)
s.c.clearBindings(s.pstmt)
return nil, err
}
// Handle Result
switch rc & 0xff {
case sqlite3.SQLITE_ROW:
// Pass reuseStmt=true
if r, err = newRows(s.c, s.pstmt, allocs, false); err != nil {
s.c.reset(s.pstmt)
s.c.clearBindings(s.pstmt)
return nil, err
}
r.(*rows).reuseStmt = true
return r, nil
case sqlite3.SQLITE_DONE:
// No rows. Reset immediately.
// We still return a rows object (empty), but we can reset the stmt now
// because the empty rows object won't call step() again.
// However, standard newRows behavior expects a valid stmt to get columns.
// Let's rely on newRows to read columns, then it returns.
// Actually, if we pass reuseStmt=true to an empty set,
// rows.Close() will eventually reset it.
if r, err = newRows(s.c, s.pstmt, allocs, true); err != nil {
s.c.reset(s.pstmt)
s.c.clearBindings(s.pstmt)
return nil, err
}
r.(*rows).reuseStmt = true
return r, nil
default:
// Error case
for _, v := range allocs {
s.c.free(v)
}
s.c.reset(s.pstmt)
s.c.clearBindings(s.pstmt)
return nil, s.c.errstr(int32(rc))
}
}
// FALLBACK PATH: Multi-statement script
for psql := s.psql; *(*byte)(unsafe.Pointer(psql)) != 0 && atomic.LoadInt32(&done) == 0; {
if pstmt, err = s.c.prepareV2(&psql); err != nil {
return nil, err
}
if pstmt == 0 {
continue
}
err = func() (err error) {
n, err := s.c.bindParameterCount(pstmt)
if err != nil {
return err
}
if n != 0 {
if allocs, err = s.c.bind(pstmt, n, args); err != nil {
return err
}
}
rc, err := s.c.step(pstmt)
if err != nil {
return err
}
switch rc & 0xff {
case sqlite3.SQLITE_ROW:
if r != nil {
r.Close()
}
if r, err = newRows(s.c, pstmt, allocs, false); err != nil {
return err
}
pstmt = 0
return nil
case sqlite3.SQLITE_DONE:
if r == nil {
if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
return err
}
pstmt = 0
return nil
}
// nop
default:
return s.c.errstr(int32(rc))
}
if *(*byte)(unsafe.Pointer(psql)) == 0 {
if r != nil {
r.Close()
}
if r, err = newRows(s.c, pstmt, allocs, true); err != nil {
return err
}
pstmt = 0
}
return nil
}()
e := s.c.finalize(pstmt)
pstmt = 0 // done with
if err == nil && e != nil {
// prioritize original
// returned error.
err = e
}
if err != nil {
return nil, err
}
}
return r, err
}
// ExecContext implements driver.StmtExecContext
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) (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)
}
// C documentation
//
// int sqlite3_clear_bindings(sqlite3_stmt*);
func (c *conn) clearBindings(pstmt uintptr) error {
if rc := sqlite3.Xsqlite3_clear_bindings(c.tls, pstmt); rc != sqlite3.SQLITE_OK {
return c.errstr(rc)
}
return nil
}

20
vendor/modernc.org/sqlite/tpch.sh generated vendored Normal file
View File

@@ -0,0 +1,20 @@
set -e
echo "See http://www.tpc.org/tpc_documents_current_versions/pdf/tpc-h_v2.17.1.pdf for details"
tmp=$(mktemp -d)
cd $tmp
echo "installing modernc.org/sqlite/tpch@latest into $tmp"
GOBIN=$tmp go install modernc.org/sqlite/tpch@latest
echo "generating pseudotext"
./tpch -pseudotext
for sf in 1 10 ; do
for sut in sqlite3 sqlite ; do
echo "$sut: generating a $sf GB test DB"
time -p ./tpch -sut $sut -dbgen -sf $sf
for q in 1 2 ; do
echo -n "$sut: running query $q: "
./tpch -sut $sut -q $q -sf $sf
done
done
done
cd -
rm -rf $tmp

62
vendor/modernc.org/sqlite/tx.go generated vendored Normal file
View File

@@ -0,0 +1,62 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"context"
"database/sql/driver"
"modernc.org/libc"
sqlite3 "modernc.org/sqlite/lib"
)
type tx struct {
c *conn
}
func newTx(ctx context.Context, c *conn, opts driver.TxOptions) (*tx, error) {
r := &tx{c: c}
sql := "begin"
if !opts.ReadOnly && c.beginMode != "" {
sql = "begin " + c.beginMode
}
if err := r.exec(ctx, sql); err != nil {
return nil, err
}
return r, nil
}
// Commit implements driver.Tx.
func (t *tx) Commit() (err error) {
return t.exec(context.Background(), "commit")
}
// Rollback implements driver.Tx.
func (t *tx) Rollback() (err error) {
return t.exec(context.Background(), "rollback")
}
func (t *tx) exec(ctx context.Context, sql string) (err error) {
psql, err := libc.CString(sql)
if err != nil {
return err
}
defer t.c.free(psql)
//TODO use t.conn.ExecContext() instead
if ctx != nil && ctx.Done() != nil {
defer interruptOnDone(ctx, t.c, nil)()
}
if rc := sqlite3.Xsqlite3_exec(t.c.tls, t.c.db, psql, 0, 0, 0); rc != sqlite3.SQLITE_OK {
return t.c.errstr(rc)
}
return nil
}

5
vendor/modernc.org/sqlite/unconvert.sh generated vendored Normal file
View File

@@ -0,0 +1,5 @@
set -evx
until unconvert -fastmath -all ./...
do
unconvert2 -fastmath -apply -all ./...
done

872
vendor/modernc.org/sqlite/vtab.go generated vendored Normal file
View File

@@ -0,0 +1,872 @@
// Copyright 2025 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.
package sqlite // import "modernc.org/sqlite"
import (
"fmt"
"math"
"sync"
"unsafe"
"modernc.org/libc"
sqlite3 "modernc.org/sqlite/lib"
"modernc.org/sqlite/vtab"
)
func init() {
vtab.SetRegisterFunc(registerModule)
}
var (
// vtabModules tracks Go virtual table modules registered via the vtab
// package. Each module is identified by an integer ID used as pAux when
// calling sqlite3_create_module_v2, so that trampolines can recover the
// Go Module implementation.
vtabModules = struct {
mu sync.RWMutex
m map[uintptr]*goModule
ids idGen
// name2id keeps stable IDs per module name to avoid unbounded growth
// across connections.
name2id map[string]uintptr
}{
m: make(map[uintptr]*goModule),
name2id: make(map[string]uintptr),
}
// nativeModules holds sqlite3_module instances for registered modules. We
// keep them in Go memory so their addresses remain stable for the C layer.
nativeModules = struct {
mu sync.RWMutex
m map[string]*sqlite3.Sqlite3_module
}{
m: make(map[string]*sqlite3.Sqlite3_module),
}
// vtabTables maps sqlite3_vtab* (pVtab) to the corresponding Go Table.
vtabTables = struct {
mu sync.RWMutex
m map[uintptr]*goTable
}{
m: make(map[uintptr]*goTable),
}
// vtabCursors maps sqlite3_vtab_cursor* (pCursor) to the corresponding Go
// Cursor.
vtabCursors = struct {
mu sync.RWMutex
m map[uintptr]*goCursor
}{
m: make(map[uintptr]*goCursor),
}
)
// goModule wraps a vtab.Module implementation with its name.
type goModule struct {
name string
impl vtab.Module
}
// goTable wraps a vtab.Table implementation and remembers its module.
type goTable struct {
mod *goModule
impl vtab.Table
}
// goCursor wraps a vtab.Cursor implementation and remembers its table.
type goCursor struct {
table *goTable
impl vtab.Cursor
}
// Use aliases of the underlying lib types so field layouts remain correct.
type cIndexConstraint = sqlite3.Tsqlite3_index_constraint
type cIndexOrderBy = sqlite3.Tsqlite3_index_orderby
type cConstraintUsage = sqlite3.Tsqlite3_index_constraint_usage
// registerModule is installed as the hook for vtab.RegisterModule.
func registerModule(name string, m vtab.Module) error {
if _, exists := d.modules[name]; exists {
return fmt.Errorf("sqlite: module %q already registered", name)
}
d.modules[name] = m
return nil
}
// registerModules installs all globally registered vtab modules on this
// connection by calling sqlite3_create_module_v2 for each one.
func (c *conn) registerModules() error {
for name, mod := range d.modules {
if err := c.registerSingleModule(name, mod); err != nil {
return err
}
}
return nil
}
func (c *conn) registerSingleModule(name string, m vtab.Module) error {
// Allocate or reuse a stable ID for this module name and remember the Go implementation.
vtabModules.mu.Lock()
modID, ok := vtabModules.name2id[name]
if !ok {
modID = vtabModules.ids.next()
vtabModules.name2id[name] = modID
}
vtabModules.m[modID] = &goModule{name: name, impl: m}
vtabModules.mu.Unlock()
nativeModules.mu.Lock()
defer nativeModules.mu.Unlock()
if _, exists := nativeModules.m[name]; exists {
// Module struct already created; nothing more to do for this connection.
return nil
}
// Build a sqlite3_module descriptor with trampolines.
mod := &sqlite3.Sqlite3_module{}
mod.FiVersion = 1
mod.FxCreate = cFuncPointer(vtabCreateTrampoline)
mod.FxConnect = cFuncPointer(vtabConnectTrampoline)
mod.FxBestIndex = cFuncPointer(vtabBestIndexTrampoline)
mod.FxDisconnect = cFuncPointer(vtabDisconnectTrampoline)
mod.FxDestroy = cFuncPointer(vtabDestroyTrampoline)
mod.FxOpen = cFuncPointer(vtabOpenTrampoline)
mod.FxClose = cFuncPointer(vtabCloseTrampoline)
mod.FxFilter = cFuncPointer(vtabFilterTrampoline)
mod.FxNext = cFuncPointer(vtabNextTrampoline)
mod.FxEof = cFuncPointer(vtabEofTrampoline)
mod.FxColumn = cFuncPointer(vtabColumnTrampoline)
mod.FxRowid = cFuncPointer(vtabRowidTrampoline)
mod.FxFindFunction = cFuncPointer(vtabFindFunctionTrampoline)
mod.FxRename = cFuncPointer(vtabRenameTrampoline)
mod.FxUpdate = cFuncPointer(vtabUpdateTrampoline)
mod.FxBegin = cFuncPointer(vtabBeginTrampoline)
mod.FxSync = cFuncPointer(vtabSyncTrampoline)
mod.FxCommit = cFuncPointer(vtabCommitTrampoline)
mod.FxRollback = cFuncPointer(vtabRollbackTrampoline)
mod.FxSavepoint = cFuncPointer(vtabSavepointTrampoline)
mod.FxRelease = cFuncPointer(vtabReleaseTrampoline)
mod.FxRollbackTo = cFuncPointer(vtabRollbackToTrampoline)
nativeModules.m[name] = mod
// Prepare C string for module name.
zName, err := libc.CString(name)
if err != nil {
return err
}
defer libc.Xfree(c.tls, zName)
// Register the module with this connection.
if rc := sqlite3.Xsqlite3_create_module_v2(c.tls, c.db, zName, uintptr(unsafe.Pointer(mod)), modID, 0); rc != sqlite3.SQLITE_OK {
return fmt.Errorf("create_module %q: %w", name, c.errstr(rc))
}
return nil
}
// vtabCreateTrampoline is the xCreate callback. It invokes the corresponding
// Go vtab.Module.Create method, declares a default schema based on argv, and
// allocates a sqlite3_vtab.
func vtabCreateTrampoline(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) int32 {
gm := lookupGoModule(pAux)
if gm == nil {
setVtabError(tls, pzErr, fmt.Sprintf("vtab: unknown module id %d", pAux))
return sqlite3.SQLITE_ERROR
}
args := extractVtabArgs(tls, argc, argv)
ctx := vtab.NewContext(func(schema string) error {
zSchema, err := libc.CString(schema)
if err != nil {
return err
}
defer libc.Xfree(tls, zSchema)
if rc := sqlite3.Xsqlite3_declare_vtab(tls, db, zSchema); rc != sqlite3.SQLITE_OK {
return fmt.Errorf("declare_vtab failed: rc=%d", rc)
}
return nil
})
tbl, err := gm.impl.Create(ctx, args)
if err != nil {
setVtabError(tls, pzErr, err.Error())
return sqlite3.SQLITE_ERROR
}
sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab{})
p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
if p == 0 {
setVtabError(tls, pzErr, "vtab: out of memory")
return sqlite3.SQLITE_NOMEM
}
mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
for i := range mem {
mem[i] = 0
}
*(*uintptr)(unsafe.Pointer(ppVtab)) = p
gt := &goTable{mod: gm, impl: tbl}
vtabTables.mu.Lock()
vtabTables.m[p] = gt
vtabTables.mu.Unlock()
return sqlite3.SQLITE_OK
}
// vtabConnectTrampoline is the xConnect callback. It mirrors
// vtabCreateTrampoline but calls Module.Connect.
func vtabConnectTrampoline(tls *libc.TLS, db uintptr, pAux uintptr, argc int32, argv uintptr, ppVtab uintptr, pzErr uintptr) int32 {
gm := lookupGoModule(pAux)
if gm == nil {
setVtabError(tls, pzErr, fmt.Sprintf("vtab: unknown module id %d", pAux))
return sqlite3.SQLITE_ERROR
}
args := extractVtabArgs(tls, argc, argv)
ctx := vtab.NewContext(func(schema string) error {
zSchema, err := libc.CString(schema)
if err != nil {
return err
}
defer libc.Xfree(tls, zSchema)
if rc := sqlite3.Xsqlite3_declare_vtab(tls, db, zSchema); rc != sqlite3.SQLITE_OK {
return fmt.Errorf("declare_vtab failed: rc=%d", rc)
}
return nil
})
tbl, err := gm.impl.Connect(ctx, args)
if err != nil {
setVtabError(tls, pzErr, err.Error())
return sqlite3.SQLITE_ERROR
}
sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab{})
p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
if p == 0 {
setVtabError(tls, pzErr, "vtab: out of memory")
return sqlite3.SQLITE_NOMEM
}
mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
for i := range mem {
mem[i] = 0
}
*(*uintptr)(unsafe.Pointer(ppVtab)) = p
gt := &goTable{mod: gm, impl: tbl}
vtabTables.mu.Lock()
vtabTables.m[p] = gt
vtabTables.mu.Unlock()
return sqlite3.SQLITE_OK
}
// vtabBestIndexTrampoline maps sqlite3_index_info to vtab.IndexInfo and
// delegates to Table.BestIndex. It also mirrors constraint and ORDER BY
// information into the Go structure.
func vtabBestIndexTrampoline(tls *libc.TLS, pVtab uintptr, pInfo uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
idx := (*sqlite3.Sqlite3_index_info)(unsafe.Pointer(pInfo))
info := &vtab.IndexInfo{}
// Populate Constraints from sqlite3_index_info.aConstraint.
if idx.FnConstraint > 0 && idx.FaConstraint != 0 {
n := int(idx.FnConstraint)
cs := make([]vtab.Constraint, 0, n)
base := idx.FaConstraint
sz := unsafe.Sizeof(cIndexConstraint{})
for i := 0; i < n; i++ {
c := (*cIndexConstraint)(unsafe.Pointer(base + uintptr(i)*sz))
op := vtab.OpUnknown
switch int32(c.Fop) {
case sqlite3.SQLITE_INDEX_CONSTRAINT_EQ:
op = vtab.OpEQ
case sqlite3.SQLITE_INDEX_CONSTRAINT_GT:
op = vtab.OpGT
case sqlite3.SQLITE_INDEX_CONSTRAINT_LE:
op = vtab.OpLE
case sqlite3.SQLITE_INDEX_CONSTRAINT_LT:
op = vtab.OpLT
case sqlite3.SQLITE_INDEX_CONSTRAINT_GE:
op = vtab.OpGE
case sqlite3.SQLITE_INDEX_CONSTRAINT_MATCH:
op = vtab.OpMATCH
case sqlite3.SQLITE_INDEX_CONSTRAINT_NE:
op = vtab.OpNE
case sqlite3.SQLITE_INDEX_CONSTRAINT_IS:
op = vtab.OpIS
case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNOT:
op = vtab.OpISNOT
case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNULL:
op = vtab.OpISNULL
case sqlite3.SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
op = vtab.OpISNOTNULL
case sqlite3.SQLITE_INDEX_CONSTRAINT_LIKE:
op = vtab.OpLIKE
case sqlite3.SQLITE_INDEX_CONSTRAINT_GLOB:
op = vtab.OpGLOB
case sqlite3.SQLITE_INDEX_CONSTRAINT_REGEXP:
op = vtab.OpREGEXP
case sqlite3.SQLITE_INDEX_CONSTRAINT_FUNCTION:
op = vtab.OpFUNCTION
case sqlite3.SQLITE_INDEX_CONSTRAINT_LIMIT:
op = vtab.OpLIMIT
case sqlite3.SQLITE_INDEX_CONSTRAINT_OFFSET:
op = vtab.OpOFFSET
}
cs = append(cs, vtab.Constraint{
Column: int(c.FiColumn),
Op: op,
Usable: c.Fusable != 0,
ArgIndex: -1, // 0-based; -1 means ignore
Omit: false,
})
}
info.Constraints = cs
}
// Populate OrderBy from sqlite3_index_info.aOrderBy.
if idx.FnOrderBy > 0 && idx.FaOrderBy != 0 {
n := int(idx.FnOrderBy)
obs := make([]vtab.OrderBy, 0, n)
base := idx.FaOrderBy
sz := unsafe.Sizeof(cIndexOrderBy{})
for i := 0; i < n; i++ {
ob := (*cIndexOrderBy)(unsafe.Pointer(base + uintptr(i)*sz))
obs = append(obs, vtab.OrderBy{
Column: int(ob.FiColumn),
Desc: ob.Fdesc != 0,
})
}
info.OrderBy = obs
}
// Populate ColUsed and idxFlags for module visibility.
if idx.FcolUsed != 0 {
info.ColUsed = uint64(idx.FcolUsed)
}
if idx.FidxFlags != 0 {
info.IdxFlags = int(idx.FidxFlags)
}
if err := gt.impl.BestIndex(info); err != nil {
// Report error via zErrMsg on pVtab.
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
// Propagate any ArgIndex assignments back into aConstraintUsage so that
// SQLite will populate xFilter's argv[] accordingly.
if idx.FnConstraint > 0 && idx.FaConstraintUsage != 0 && len(info.Constraints) > 0 {
n := int(idx.FnConstraint)
base := idx.FaConstraintUsage
sz := unsafe.Sizeof(cConstraintUsage{})
for i := 0; i < n && i < len(info.Constraints); i++ {
cu := (*cConstraintUsage)(unsafe.Pointer(base + uintptr(i)*sz))
argIndex := info.Constraints[i].ArgIndex
if argIndex >= 0 {
// Go ArgIndex is 0-based; SQLite wants 1-based.
cu.FargvIndex = int32(argIndex + 1)
}
if info.Constraints[i].Omit {
cu.Fomit = 1
}
}
}
// Guard against int32 overflow: SQLite expects idxNum as int32.
if info.IdxNum < math.MinInt32 || info.IdxNum > math.MaxInt32 {
setVtabZErrMsg(tls, pVtab, fmt.Sprintf("vtab: IdxNum %d out of int32 range", info.IdxNum))
return sqlite3.SQLITE_ERROR
}
idx.FidxNum = int32(info.IdxNum)
if info.IdxStr != "" {
// Allocate using SQLite allocator because needToFreeIdxStr=1 instructs
// SQLite to free the string with sqlite3_free.
z := sqlite3AllocCString(tls, info.IdxStr)
if z != 0 {
idx.FidxStr = z
idx.FneedToFreeIdxStr = 1
}
}
if info.OrderByConsumed {
idx.ForderByConsumed = 1
}
if info.IdxFlags != 0 {
idx.FidxFlags = int32(info.IdxFlags)
}
if info.EstimatedCost != 0 {
idx.FestimatedCost = info.EstimatedCost
}
if info.EstimatedRows != 0 {
idx.FestimatedRows = sqlite3.Sqlite3_int64(info.EstimatedRows)
}
return sqlite3.SQLITE_OK
}
// vtabDisconnectTrampoline is xDisconnect. It frees the sqlite3_vtab and
// calls Table.Disconnect.
func vtabDisconnectTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt != nil {
_ = gt.impl.Disconnect()
vtabTables.mu.Lock()
delete(vtabTables.m, pVtab)
vtabTables.mu.Unlock()
}
sqlite3.Xsqlite3_free(tls, pVtab)
return sqlite3.SQLITE_OK
}
// vtabDestroyTrampoline is xDestroy. Currently identical to Disconnect.
func vtabDestroyTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt != nil {
_ = gt.impl.Destroy()
vtabTables.mu.Lock()
delete(vtabTables.m, pVtab)
vtabTables.mu.Unlock()
}
sqlite3.Xsqlite3_free(tls, pVtab)
return sqlite3.SQLITE_OK
}
// vtabOpenTrampoline is xOpen. It allocates an empty sqlite3_vtab_cursor and
// creates a Go Cursor via Table.Open.
func vtabOpenTrampoline(tls *libc.TLS, pVtab uintptr, ppCursor uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
curImpl, err := gt.impl.Open()
if err != nil {
return sqlite3.SQLITE_ERROR
}
sz := unsafe.Sizeof(sqlite3.Sqlite3_vtab_cursor{})
p := sqlite3.Xsqlite3_malloc(tls, int32(sz))
if p == 0 {
return sqlite3.SQLITE_NOMEM
}
mem := (*libc.RawMem)(unsafe.Pointer(p))[:sz:sz]
for i := range mem {
mem[i] = 0
}
*(*uintptr)(unsafe.Pointer(ppCursor)) = p
// Link cursor back to its vtab so error reporting can set zErrMsg.
cur := (*sqlite3.Sqlite3_vtab_cursor)(unsafe.Pointer(p))
cur.FpVtab = pVtab
gc := &goCursor{table: gt, impl: curImpl}
vtabCursors.mu.Lock()
vtabCursors.m[p] = gc
vtabCursors.mu.Unlock()
return sqlite3.SQLITE_OK
}
// vtabCloseTrampoline is xClose. It frees the sqlite3_vtab_cursor and calls
// Cursor.Close.
func vtabCloseTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc != nil {
_ = gc.impl.Close()
vtabCursors.mu.Lock()
delete(vtabCursors.m, pCursor)
vtabCursors.mu.Unlock()
}
sqlite3.Xsqlite3_free(tls, pCursor)
return sqlite3.SQLITE_OK
}
// vtabFilterTrampoline is xFilter.
func vtabFilterTrampoline(tls *libc.TLS, pCursor uintptr, idxNum int32, idxStr uintptr, argc int32, argv uintptr) int32 {
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc == nil {
return sqlite3.SQLITE_ERROR
}
var idxStrGo string
if idxStr != 0 {
idxStrGo = libc.GoString(idxStr)
}
vals := functionArgs(tls, argc, argv)
if err := gc.impl.Filter(int(idxNum), idxStrGo, vals); err != nil {
// Set zErrMsg on the associated vtab for better diagnostics.
if pCursor != 0 {
cur := (*sqlite3.Sqlite3_vtab_cursor)(unsafe.Pointer(pCursor))
if cur.FpVtab != 0 {
setVtabZErrMsg(tls, cur.FpVtab, err.Error())
}
}
return sqlite3.SQLITE_ERROR
}
return sqlite3.SQLITE_OK
}
// vtabNextTrampoline is xNext.
func vtabNextTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
_ = tls
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc == nil {
return sqlite3.SQLITE_ERROR
}
if err := gc.impl.Next(); err != nil {
return sqlite3.SQLITE_ERROR
}
return sqlite3.SQLITE_OK
}
// vtabEofTrampoline is xEof.
func vtabEofTrampoline(tls *libc.TLS, pCursor uintptr) int32 {
_ = tls
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc == nil || gc.impl.Eof() {
return 1
}
return 0
}
// vtabColumnTrampoline is xColumn.
func vtabColumnTrampoline(tls *libc.TLS, pCursor uintptr, ctx uintptr, iCol int32) int32 {
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc == nil {
sqlite3.Xsqlite3_result_null(tls, ctx)
return sqlite3.SQLITE_OK
}
val, err := gc.impl.Column(int(iCol))
if err != nil {
// Report via result error on the context.
z, cerr := libc.CString(err.Error())
if cerr == nil {
defer libc.Xfree(tls, z)
sqlite3.Xsqlite3_result_error(tls, ctx, z, -1)
sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
} else {
sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
}
return sqlite3.SQLITE_ERROR
}
if err := functionReturnValue(tls, ctx, val); err != nil {
// Include a descriptive error message for easier debugging
// (e.g., unsupported type conversions).
if err != nil {
z, cerr := libc.CString(err.Error())
if cerr == nil {
defer libc.Xfree(tls, z)
sqlite3.Xsqlite3_result_error(tls, ctx, z, -1)
}
}
sqlite3.Xsqlite3_result_error_code(tls, ctx, sqlite3.SQLITE_ERROR)
return sqlite3.SQLITE_ERROR
}
return sqlite3.SQLITE_OK
}
// vtabRowidTrampoline is xRowid.
func vtabRowidTrampoline(tls *libc.TLS, pCursor uintptr, pRowid uintptr) int32 {
_ = tls
vtabCursors.mu.RLock()
gc := vtabCursors.m[pCursor]
vtabCursors.mu.RUnlock()
if gc == nil {
*(*int64)(unsafe.Pointer(pRowid)) = 0
return sqlite3.SQLITE_OK
}
rowid, err := gc.impl.Rowid()
if err != nil {
*(*int64)(unsafe.Pointer(pRowid)) = 0
return sqlite3.SQLITE_ERROR
}
*(*int64)(unsafe.Pointer(pRowid)) = rowid
return sqlite3.SQLITE_OK
}
func lookupGoModule(id uintptr) *goModule {
vtabModules.mu.RLock()
defer vtabModules.mu.RUnlock()
return vtabModules.m[id]
}
func extractVtabArgs(tls *libc.TLS, argc int32, argv uintptr) []string {
args := make([]string, argc)
for i := int32(0); i < argc; i++ {
cstr := *(*uintptr)(unsafe.Pointer(argv + uintptr(i)*unsafe.Sizeof(uintptr(0))))
args[i] = libc.GoString(cstr)
}
return args
}
func setVtabError(tls *libc.TLS, pzErr uintptr, msg string) {
if pzErr == 0 {
return
}
z := sqlite3AllocCString(tls, msg)
if z == 0 {
return
}
*(*uintptr)(unsafe.Pointer(pzErr)) = z
}
// setVtabZErrMsg sets pVtab->zErrMsg to a newly allocated C string containing
// msg. SQLite will free this pointer.
func setVtabZErrMsg(tls *libc.TLS, pVtab uintptr, msg string) {
if pVtab == 0 {
return
}
vt := (*sqlite3.Sqlite3_vtab)(unsafe.Pointer(pVtab))
if vt.FzErrMsg != 0 {
sqlite3.Xsqlite3_free(tls, vt.FzErrMsg)
vt.FzErrMsg = 0
}
z := sqlite3AllocCString(tls, msg)
if z == 0 {
return
}
vt.FzErrMsg = z
}
// Optional vtab callbacks
// vtabFindFunctionTrampoline is xFindFunction. We currently do not expose a
// Go surface for per-table SQL functions; report not found (return 0).
func vtabFindFunctionTrampoline(tls *libc.TLS, pVtab uintptr, nArg int32, zName uintptr, pxFunc uintptr, ppArg uintptr) int32 {
_ = tls
_ = pVtab
_ = nArg
_ = zName
if pxFunc != 0 {
*(*uintptr)(unsafe.Pointer(pxFunc)) = 0
}
if ppArg != 0 {
*(*uintptr)(unsafe.Pointer(ppArg)) = 0
}
return 0 // not found
}
// vtabRenameTrampoline is xRename. Calls Table.Rename if implemented.
func vtabRenameTrampoline(tls *libc.TLS, pVtab uintptr, zNew uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
name := libc.GoString(zNew)
if r, ok := gt.impl.(interface{ Rename(string) error }); ok {
if err := r.Rename(name); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
// vtabUpdateTrampoline is xUpdate. Not supported by default; report read-only.
func vtabUpdateTrampoline(tls *libc.TLS, pVtab uintptr, argc int32, argv uintptr, pRowid uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
upd, ok := gt.impl.(interface {
Insert(cols []vtab.Value, rowid *int64) error
Update(oldRowid int64, cols []vtab.Value, newRowid *int64) error
Delete(oldRowid int64) error
})
if !ok {
return sqlite3.SQLITE_READONLY
}
// DELETE: argc == 1; argv[0]=oldRowid
if argc == 1 {
valPtr := *(*uintptr)(unsafe.Pointer(argv))
oldRowid := int64(0)
if sqlite3.Xsqlite3_value_type(tls, valPtr) != sqlite3.SQLITE_NULL {
oldRowid = int64(sqlite3.Xsqlite3_value_int64(tls, valPtr))
}
if err := upd.Delete(oldRowid); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
return sqlite3.SQLITE_OK
}
// INSERT or UPDATE: argc == N+2. argv[0]=oldRowid (NULL for insert),
// argv[1..N]=column values, argv[N+1]=newRowid (or desired rowid for insert, may be NULL).
if argc < 3 {
return sqlite3.SQLITE_MISUSE
}
nCols := argc - 2
// Extract column values
colsPtr := argv + uintptr(1)*sqliteValPtrSize
cols := functionArgs(tls, nCols, colsPtr)
// Determine old/new rowid
oldPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(0)*sqliteValPtrSize))
newPtr := *(*uintptr)(unsafe.Pointer(argv + uintptr(argc-1)*sqliteValPtrSize))
oldIsNull := sqlite3.Xsqlite3_value_type(tls, oldPtr) == sqlite3.SQLITE_NULL
newIsNull := sqlite3.Xsqlite3_value_type(tls, newPtr) == sqlite3.SQLITE_NULL
if oldIsNull {
// INSERT
var rid int64
if !newIsNull {
rid = int64(sqlite3.Xsqlite3_value_int64(tls, newPtr))
}
if err := upd.Insert(cols, &rid); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
if pRowid != 0 {
*(*int64)(unsafe.Pointer(pRowid)) = rid
}
return sqlite3.SQLITE_OK
}
// UPDATE
oldRowid := int64(sqlite3.Xsqlite3_value_int64(tls, oldPtr))
var newRid int64
if !newIsNull {
newRid = int64(sqlite3.Xsqlite3_value_int64(tls, newPtr))
}
if err := upd.Update(oldRowid, cols, &newRid); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
if pRowid != 0 && newRid != 0 {
*(*int64)(unsafe.Pointer(pRowid)) = newRid
}
return sqlite3.SQLITE_OK
}
// Transactional callbacks
func vtabBeginTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Begin() error }); ok {
if err := tr.Begin(); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabSyncTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Sync() error }); ok {
if err := tr.Sync(); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabCommitTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Commit() error }); ok {
if err := tr.Commit(); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabRollbackTrampoline(tls *libc.TLS, pVtab uintptr) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Rollback() error }); ok {
if err := tr.Rollback(); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabSavepointTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Savepoint(int) error }); ok {
if err := tr.Savepoint(int(i)); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabReleaseTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ Release(int) error }); ok {
if err := tr.Release(int(i)); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}
func vtabRollbackToTrampoline(tls *libc.TLS, pVtab uintptr, i int32) int32 {
vtabTables.mu.RLock()
gt := vtabTables.m[pVtab]
vtabTables.mu.RUnlock()
if gt == nil {
return sqlite3.SQLITE_ERROR
}
if tr, ok := gt.impl.(interface{ RollbackTo(int) error }); ok {
if err := tr.RollbackTo(int(i)); err != nil {
setVtabZErrMsg(tls, pVtab, err.Error())
return sqlite3.SQLITE_ERROR
}
}
return sqlite3.SQLITE_OK
}

53
vendor/modernc.org/sqlite/vtab/doc.go generated vendored Normal file
View File

@@ -0,0 +1,53 @@
// Package vtab defines a Go-facing API for implementing SQLite virtual table
// modules on top of the modernc.org/sqlite driver.
//
// It is intentionally small and generic so that external projects can
// implement virtual tables without depending on the translated C internals.
package vtab
// API notes
//
// - Schema declaration: Modules must call Context.Declare from within Create
// or Connect to declare the virtual table schema (a CREATE TABLE statement).
// The driver no longer auto-declares based on USING(...) args to support
// dynamic schemas (e.g., CSV headers).
//
// - Constraint operators: ConstraintOp includes OpUnknown for operators that
// are not recognized. The driver maps common SQLite operators including EQ,
// NE, GT, GE, LT, LE, MATCH, IS/ISNOT, ISNULL/ISNOTNULL, LIKE, GLOB, REGEXP,
// FUNCTION, LIMIT, and OFFSET.
//
// - ArgIndex: Set as 0-based in Go to indicate which position in argv[] should
// receive a constraint value. The driver adds +1 when communicating with
// SQLite (which is 1-based). Use -1 (default) to ignore.
//
// - Omit: Set Constraint.Omit to ask SQLite to not re-evaluate that constraint
// in the parent query if the virtual table fully handles it.
//
// - ColUsed: IndexInfo.ColUsed provides a bitmask of columns referenced by the
// query. Bit N indicates column N is used.
//
// - IdxFlags: IndexInfo.IdxFlags allows modules to set planning flags.
// Currently, IndexScanUnique (mirrors SQLITE_INDEX_SCAN_UNIQUE) indicates
// the plan will visit at most one row. This can help the optimizer.
//
// Optional interfaces
//
// - Updater: Implement on your Table to support writes via xUpdate.
// Insert(cols, *rowid), Update(oldRowid, cols, *newRowid), Delete(oldRowid).
// The trampoline maps SQLite xUpdates calling convention to these methods.
//
// - Renamer: Implement Rename(newName string) on your Table to handle xRename.
// If unimplemented, rename is treated as a no-op.
//
// - Transactional: Implement Begin/Sync/Commit/Rollback/Savepoint/Release/
// RollbackTo as needed. Unimplemented methods are treated as no-ops.
// These callbacks let writable or advanced modules coordinate with SQLite
// transaction boundaries.
//
// Re-entrancy cautions
// - Avoid executing SQL on the same connection from within vtab methods
// (Create/Connect/BestIndex/Filter/etc.). SQLite virtual table callbacks run
// inside the engine and issuing re-entrant SQL on the same connection can
// lead to deadlocks or undefined behavior. If a module requires issuing SQL,
// consider using a separate connection and document the concurrency model.

245
vendor/modernc.org/sqlite/vtab/vtab.go generated vendored Normal file
View File

@@ -0,0 +1,245 @@
package vtab
import (
"database/sql"
"database/sql/driver"
"errors"
)
// Value is the value type passed to and from virtual table cursors. It
// aliases database/sql/driver.Value to avoid exposing low-level details to
// module authors while remaining compatible with the driver.
type Value = driver.Value
// Context carries information that a Module may need when creating or
// connecting a table instance. It intentionally does not expose *sql.DB to
// avoid leaking database/sql internals into the vtab API. Additional fields
// may be added in the future as needed.
type Context struct {
declare func(string) error
}
// Declare must be called by a module from within Create or Connect to declare
// the schema of the virtual table. The provided SQL must be a CREATE TABLE
// statement describing the exposed columns.
//
// The engine installs this callback so that the declaration is executed in the
// correct context. Calling Declare outside of Create/Connect may fail.
func (c Context) Declare(schema string) error {
if c.declare == nil {
return errors.New("vtab: declare not available in this context")
}
return c.declare(schema)
}
// NewContext is used by the engine to create a Context bound to the current
// xCreate/xConnect call. External modules should not need to call this.
func NewContext(declare func(string) error) Context { return Context{declare: declare} }
// Module represents a virtual table module, analogous to sqlite3_module in
// the SQLite C API. Implementations are responsible for creating and
// connecting table instances.
type Module interface {
// Create is called to create a new virtual table. args corresponds to the
// argv array passed to xCreate in the SQLite C API: it contains the module
// name, the database name, the table name, and module arguments.
Create(ctx Context, args []string) (Table, error)
// Connect is called to connect to an existing virtual table. Its
// semantics mirror xConnect in the SQLite C API.
Connect(ctx Context, args []string) (Table, error)
}
// Table represents a single virtual table instance (the Go analogue of
// sqlite3_vtab and its associated methods).
type Table interface {
// BestIndex allows the virtual table to inform SQLite about which
// constraints and orderings it can efficiently support. The IndexInfo
// structure mirrors sqlite3_index_info.
BestIndex(info *IndexInfo) error
// Open creates a new cursor for scanning the table.
Open() (Cursor, error)
// Disconnect is called to disconnect from a table instance (xDisconnect).
Disconnect() error
// Destroy is called when a table is dropped (xDestroy).
Destroy() error
}
// Renamer can be implemented by a Table to handle xRename.
type Renamer interface {
Rename(newName string) error
}
// Transactional can be implemented by a Table to handle transaction-related
// callbacks. Methods are optional; unimplemented methods are treated as no-op.
type Transactional interface {
Begin() error
Sync() error
Commit() error
Rollback() error
Savepoint(i int) error
Release(i int) error
RollbackTo(i int) error
}
// Cursor represents a cursor over a virtual table (sqlite3_vtab_cursor).
type Cursor interface {
// Filter corresponds to xFilter. idxNum and idxStr are the chosen index
// number and string; vals are the constraint arguments.
Filter(idxNum int, idxStr string, vals []Value) error
// Next advances the cursor to the next row (xNext).
Next() error
// Eof reports whether the cursor is past the last row (xEof != 0).
Eof() bool
// Column returns the value of the specified column in the current row
// (xColumn).
Column(col int) (Value, error)
// Rowid returns the current rowid (xRowid).
Rowid() (int64, error)
// Close closes the cursor (xClose).
Close() error
}
// Updater can be implemented by a Table to support writes via xUpdate.
//
// Semantics follow SQLite's xUpdate:
// - Delete: Delete(oldRowid) is called.
// - Insert: Insert(cols, rowid) is called. *rowid may contain a desired rowid
// (if provided by SQL) and should be set to the final rowid of the new row.
// - Update: Update(oldRowid, cols, newRowid) is called. *newRowid may be set
// to the final rowid of the updated row when changed.
type Updater interface {
Insert(cols []Value, rowid *int64) error
Update(oldRowid int64, cols []Value, newRowid *int64) error
Delete(oldRowid int64) error
}
// ConstraintOp describes the operator used in a constraint on a virtual
// table column. It loosely mirrors the op field of sqlite3_index_constraint.
type ConstraintOp int
const (
// OpUnknown indicates an operator that is not recognized or not mapped.
// Modules should treat this conservatively.
OpUnknown ConstraintOp = iota
OpEQ
OpGT
OpLE
OpLT
OpGE
OpMATCH // "MATCH" operator (e.g. for FTS or KNN semantics)
OpNE
OpIS
OpISNOT
OpISNULL
OpISNOTNULL
OpLIKE
OpGLOB
OpREGEXP
OpFUNCTION
OpLIMIT
OpOFFSET
)
// Constraint describes a single WHERE-clause constraint that SQLite is
// considering pushing down to the virtual table.
type Constraint struct {
Column int
Op ConstraintOp
Usable bool
// ArgIndex selects which position in argv[] (0-based) should contain the
// RHS value for this constraint when Filter is called. Set to -1 to ignore.
ArgIndex int
// Omit requests SQLite to omit the corresponding constraint from the
// parent query if the virtual table fully handles it.
Omit bool
}
// OrderBy describes a single ORDER BY term for a query involving a virtual
// table.
type OrderBy struct {
Column int
Desc bool
}
// IndexInfo holds information about constraints and orderings for a virtual
// table query. It is the Go analogue of sqlite3_index_info.
type IndexInfo struct {
Constraints []Constraint
OrderBy []OrderBy
// IdxNum selects the query plan chosen in BestIndex. This value is passed
// back to Cursor.Filter. Note: SQLite stores this as a 32-bit signed
// integer (int32). Implementations must ensure IdxNum fits within the
// int32 range; values outside of int32 will cause an error in the driver
// to avoid silent truncation.
IdxNum int64
IdxStr string
// IdxFlags provides extra information about the chosen plan.
// Set to IndexScanUnique to indicate the plan visits at most one row.
IdxFlags int
OrderByConsumed bool
EstimatedCost float64
EstimatedRows int64
// ColUsed is a bitmask indicating which columns are used by the query.
// Bit N is set if column N is referenced.
ColUsed uint64
}
// Index flag values for IndexInfo.IdxFlags.
const (
// IndexScanUnique mirrors SQLITE_INDEX_SCAN_UNIQUE and indicates that the
// chosen plan will visit at most one row.
IndexScanUnique = 1
)
// ErrNotImplemented is returned by RegisterModule when the underlying engine
// has not yet installed a registration hook. External projects can depend on
// the vtab API surface before the low-level bridge to sqlite3_create_module
// is fully wired; once the engine sets the hook via SetRegisterFunc,
// RegisterModule will forward calls to it.
var ErrNotImplemented = errors.New("vtab: RegisterModule not wired into engine")
// registerHook is installed by the engine package via SetRegisterFunc. It is
// invoked by RegisterModule to perform the actual module registration.
var registerHook func(name string, m Module) error
// SetRegisterFunc is intended to be called by the engine package to provide
// the concrete implementation of module registration. External callers
// should use RegisterModule instead.
func SetRegisterFunc(fn func(name string, m Module) error) { registerHook = fn }
// RegisterModule registers a virtual table module with the provided *sql.DB.
//
// Registration applies to new connections only. Existing open connections will
// not be updated to include newly registered modules.
//
// Registration is performed when opening a new connection. If the underlying
// sqlite3_create_module_v2 call fails, opening the connection fails and returns
// that error. This fail-fast behavior prevents partially-initialized
// connections when a module cannot be installed.
//
// The db parameter is currently unused by the engine; it is available so
// module implementations can capture it if they need a *sql.DB for their own
// internal queries.
func RegisterModule(db *sql.DB, name string, m Module) error {
_ = db
if registerHook == nil {
return ErrNotImplemented
}
if name == "" {
return errors.New("vtab: module name must be non-empty")
}
if m == nil {
return errors.New("vtab: module implementation is nil")
}
return registerHook(name, m)
}