sqlite

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2026 License: BSD-3-Clause Imports: 23 Imported by: 0

README

go-again/sqlite

Go Reference

A CGo-free SQLite driver for Go, built as a drop-in replacement for both github.com/mattn/go-sqlite3 and the glebarez/sqlite gorm dialector. Built on top of modernc.org/sqlite, which transpiles the SQLite C amalgamation to Go via ccgo.

Native first-class support for vector search (sqlite-vec) and full-text search (FTS5).

import (
    "database/sql"
    _ "github.com/go-again/sqlite"
)

db, _ := sql.Open("sqlite3", "file:my.db?_pragma=foreign_keys(1)")

Why

  • No C compiler needed. Builds inside golang:alpine and on GCP Cloud Build.
  • One driver, three personalities: register as "sqlite3" (mattn-style) and "sqlite" (modernc-style) at the same time.
  • All the things mattn exposed — SQLiteDriver.ConnectHook, Conn.RegisterFunc/RegisterAggregator/RegisterCollation, RegisterUpdateHook/RegisterAuthorizer/SetTrace, LoadExtension, Backup, Serialize/Deserialize, GetLimit/SetLimit — but pure Go.
  • Typed Go APIs for vector search and FTS5, with iter.Seq2 streaming and optional log/slog + Recorder observability.

Why CGo-free matters

If you've never hit it, this whole section sounds like premature paranoia. If you have, you know what it cost:

  • Alpine / scratch / distroless images: mattn requires gcc and musl headers at build time. The Go cross-compile story for those targets is hostile to CGo — you either ship a fat base image or move the build into a multi-stage Dockerfile and pull in alpine-sdk for the build stage. go-again/sqlite builds in FROM golang:1.25-alpine with no apk add.
  • go build cross-compile: GOOS=linux GOARCH=arm64 go build from macOS just works here. With mattn you need a cross C toolchain (osxcross, zig-as-CC, or a remote build runner) and the bug surface from cross-linking a vendored amalgamation is its own time sink.
  • CI providers that disallow CGo: GCP Cloud Build's lightweight tier doesn't ship gcc. AWS CodeBuild gets confused about glibc ABIs when CGo is on. Several Lambda runtimes ship without a working linker. This package compiles in all of them.
  • go test -race: works the same as any pure-Go package. mattn's race detector integration historically broke on each major SQLite bump.
  • Reproducible builds: the entire driver is Go source. No vendored amalgamation to diff, no auto-generated build flags, no ccache surprises.

The cost: a constant-factor perf gap on hot UDF / per-row callback paths (see Performance below). For 95% of applications this is invisible.

Package layout

Import path What it gives you
github.com/go-again/sqlite The driver. Registers "sqlite" and "sqlite3" names.
github.com/go-again/sqlite/gorm gorm.Dialector for gorm.io/gorm.
github.com/go-again/sqlite/vec sqlite-vec extension + typed Table API.
github.com/go-again/sqlite/fts Typed FTS5 Index[K, V] with tokenizers, query builder, snippet/highlight.
github.com/go-again/sqlite/vfs Expose any io/fs.FS (incl. embed.FS) as a read-only SQLite VFS.

Quick starts

Mattn drop-in

Change one line:

- import _ "github.com/mattn/go-sqlite3"
+ import _ "github.com/go-again/sqlite"

Everything else — sql.Open("sqlite3", ...), the _* DSN flags, custom- driver registration via &sqlite3.SQLiteDriver{Extensions, ConnectHook}, Conn.RegisterFunc, errors.Is(err, sqlite.ErrConstraintUnique) — works unchanged.

See examples/mattn-compat/.

gorm
import (
    "gorm.io/gorm"
    sqlite "github.com/go-again/sqlite/gorm"
)

db, _ := gorm.Open(sqlite.Open("file:my.db?_pragma=foreign_keys(1)"), &gorm.Config{})

sqlite.Open(dsn) and sqlite.New(sqlite.Config{...}) are both provided so either glebarez or the official go-gorm/sqlite import-paths can be swapped in.

See examples/gorm/.

import (
    _ "github.com/go-again/sqlite"
    "github.com/go-again/sqlite/vec"
)

tbl, _ := vec.Create(ctx, db, "docs", 8, vec.Options{Metric: vec.Cosine})
tbl.BatchInsert(ctx, items)
for m, err := range tbl.KNN(ctx, query, 5) {
    if err != nil { return err }
    fmt.Println(m.Rowid, m.Distance)
}

See examples/vec-search/.

import (
    _ "github.com/go-again/sqlite"
    "github.com/go-again/sqlite/fts"
)

idx, _ := fts.New[int64, string](ctx, db, "docs", fts.Options{
    Tokenizer: fts.Porter{Base: fts.Unicode61{RemoveDiacritics: 2}},
})
idx.Insert(ctx, fts.Attr[int64, string]{Key: 1, Value: "the quick brown fox"})

matches, _ := idx.SearchSlice(ctx, fts.Term("fox"),
    fts.WithRanking(),
    fts.WithSnippet("value", "[", "]", "…", 8))

See examples/fts-search/.

embed.FS-backed read-only databases
import "github.com/go-again/sqlite/vfs"

//go:embed seed.db
var seed embed.FS

name, _, _ := vfs.New(seed)
db, _ := sql.Open("sqlite3", "file:seed.db?vfs="+name+"&mode=ro")

See examples/vfs-embed/.

Migration table

If you're coming from:

Old import New import Notes
_ "github.com/mattn/go-sqlite3" _ "github.com/go-again/sqlite" sql.Open("sqlite3", ...) keeps working.
_ "modernc.org/sqlite" _ "github.com/go-again/sqlite" sql.Open("sqlite", ...) keeps working.
"github.com/glebarez/sqlite" "github.com/go-again/sqlite/gorm" sqlite.Open(dsn) keeps working.
"github.com/go-gorm/sqlite" "github.com/go-again/sqlite/gorm" sqlite.New(sqlite.Config{...}) keeps working.

DSN flag compatibility

Every _* DSN flag mattn supported is translated transparently — usually into the equivalent PRAGMA. The _strict=1 opt-in turns any unknown flag into an error, helpful during migration to flush typos out.

Flag (aliases) Underlying action
_pragma=foo(1) PRAGMA foo=1 (multi-value)
_foreign_keys / _fk PRAGMA foreign_keys=
_busy_timeout / _timeout PRAGMA busy_timeout=
_journal_mode / _journal PRAGMA journal_mode=
_synchronous / _sync PRAGMA synchronous=
_locking_mode / _locking PRAGMA locking_mode=
_secure_delete PRAGMA secure_delete=
_recursive_triggers / _rt PRAGMA recursive_triggers=
_cache_size PRAGMA cache_size=
_auto_vacuum / _vacuum PRAGMA auto_vacuum=
_defer_foreign_keys / _defer_fk PRAGMA defer_foreign_keys=
_ignore_check_constraints PRAGMA ignore_check_constraints=
_case_sensitive_like / _cslike PRAGMA case_sensitive_like=
_query_only PRAGMA query_only=
_writable_schema PRAGMA writable_schema=
_loc aliased to _timezone (auto → Local)
_time_format, _time_integer_format, _inttotime, _texttotime, _timezone inherited from modernc
_txlock sets transaction begin mode
cache, mode, immutable, vfs URI-level, passed through
_auth* rejected — userauth was removed upstream
_strict=1 unknown flags become hard errors

Build-tag mapping

Mattn used build tags to enable SQLite compile-time features. In go-again, those features are already enabled by default (modernc compiles SQLite with them), so the build tags become no-ops:

mattn build tag go-again status
sqlite_fts5 always on
sqlite_json (JSON1) always on
sqlite_math_functions always on
sqlite_rtree, sqlite_geopoly always on
sqlite_dbstat always on
sqlite_preupdate_hook always on, accessible via (*Conn).RegisterPreUpdateHook
sqlite_userauth dropped (deprecated upstream)
sqlite_unlock_notify inherited from modernc
sqlite_vtable always on, see modernc.org/sqlite/vtab

SQLite version

Inherited from modernc.org/sqlite — currently 3.53.1.

Performance

The underlying engine is modernc.org/sqlite, whose maintainer publishes benchmark numbers against the major C-bound drivers at The SQLite Drivers Benchmarks Game. Numbers vary by workload, but the broad picture is consistent:

  • Bulk read / scan paths are within single-digit-percent of mattn.
  • Bulk insert under WAL is comparable.
  • UDF-heavy workloads where Go callbacks fire on every row pay a measurable constant factor (the ccgo-transpiled call paths go through more indirection than mattn's CGo binding). For a no-op authorizer installed alongside a tiny SELECT, this package's overhead measures ~3% time and +5 allocs/op on Apple M4 — see BenchmarkAuthorizer_NoOp in bench_test.go.
  • Connection open is faster here than mattn because there's no dlopen / dlsym / extension-resolution dance.

If you care about exact numbers for your workload, the go test -bench=. -benchmem -count=5 recipe is the right primary source of truth — micro-benchmarks lifted off someone else's hardware lie often.

The cost-of-doing-business: we cannot beat a hand-tuned C+CGo binding on hot UDF paths, and we don't try to. For workloads that fit "use SQL, let SQLite do the heavy lifting," the choice is mostly about deployment convenience (see "Why CGo-free matters" above), not about throughput.

Coexistence with mattn/go-sqlite3

By default this package registers "sqlite3" — the same name mattn uses. If you need both drivers in the same binary (gradual migration, fallback for an extension you only have as a mattn-compiled .so, etc.), register this one under a custom name and leave "sqlite3" to mattn:

import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3" // claims "sqlite3"
    sqlite "github.com/go-again/sqlite"
)

func init() {
    // Pick any name; opens through it route to the pure-Go driver.
    sql.Register("sqlite-pure", &sqlite.SQLiteDriver{})
}

Then use sql.Open("sqlite-pure", dsn) for routes that should use this driver, and sql.Open("sqlite3", dsn) for routes that should still go through mattn. There is no shared state, so the choice is per-*sql.DB.

The blank-import-only pattern (which auto-registers our driver under "sqlite3" and panics on import-time conflict) is incompatible with co-importing mattn. If you need that combination, drop the blank import and use the named registration shown above.

See TestCoexistence_CustomNameAlongsideMattn in compat_test.go for an executable example.

Observability

Both the typed sub-packages ship a Wrap(..., WithLogger, WithRecorder) decorator. The Recorder interface differs per package (vec records dimension and k; fts records the FTS5 MATCH expression) — bring your own metrics/tracing library.

idx := fts.Wrap(rawIndex,
    fts.WithLogger(slog.Default()),
    fts.WithRecorder(myMetricsAdapter))

The core driver exposes lower-level hooks for the same purpose: (*Conn).SetTrace, RegisterUpdateHook, RegisterCommitHook, RegisterRollbackHook, RegisterPreUpdateHook, RegisterAuthorizer.

libc version pinning

The transpiled SQLite C in modernc.org/sqlite/lib is closely tied to a specific modernc.org/libc version. Your downstream go.mod must use the same modernc.org/libc version pinned by this module, otherwise the generated C-side ABI drifts and SQLite behaves erratically. The pin is maintained automatically when you go mod tidy against this module.

To inspect what we pin: just libc-pin (or go list -m modernc.org/libc).

Development

A justfile ships at the repo root with recipes for the common operations. Install just (e.g. brew install just) and then:

just                  # default: build + test + lint (fast pre-commit gate)
just test             # full suite across every package
just test-one PATTERN # focus on a single test/regex
just test-race        # -race detector
just bench            # all benchmarks
just lint             # vet + staticcheck + golangci-lint
just examples         # smoke-test every example
just cross-build      # compile-only matrix across every CI target
just ci               # full CI sequence locally
just --list           # everything else

If you don't want to install just, the underlying commands are vanilla Go tooling — go test ./..., go vet ./..., go build ./.... The justfile is convenience, not a build dependency.

Testing

130 tests across the five packages cover:

  • driver registration under both names, DSN flag translation matrix (including the _mutex-honesty path that refuses NOMUTEX rather than silently lying)
  • reflective UDFs (every Go scalar type, variadics, (T, error)), aggregators, collations
  • update / authorizer / trace / preupdate / commit / rollback hooks
  • backup (Step/Remaining/PageCount), serialize/deserialize round-trip
  • error code + extended code + errors.Is
  • gorm: Dialector, Migrator, DDL parser, transaction commit/rollback, unique-violation translation, plus integration tests proving the side-by-side composition with vfs / vec / fts
  • vec: L2 / Cosine metrics (Dot via the SQL path), JSON + binary encoding parity, KNN streaming with early break, dim-mismatch validation
  • fts: Porter / Unicode61 / Trigram tokenizers, phrase adjacency, BM25 ranking, snippet/highlight, external-content mode, multi-column index
  • both Observable wrappers: Recorder fires once per op, error propagation, no-op when no options
  • vfs: round-trip from a real on-disk SQLite file into a fstest.MapFS

This is what we run. We do not claim to run gorm.io/gorm's full upstream test suite. The local gorm tests exercise every Dialector / Migrator path we care about for our dialector.

Run them with just test (or go test ./...).

License

BSD-style, matching modernc.org/sqlite. See LICENSE.

Acknowledgements

  • modernc.org/sqlite — Jan Mercl's pure-Go SQLite transpilation, without which this library would not exist.
  • mattn/go-sqlite3 — the C-based driver whose API we mirror.
  • glebarez/sqlite — the gorm dialector this package's gorm sub-package is ported from.
  • asg017/sqlite-vec — the vector search extension bundled by modernc.org/sqlite/vec and re-exported here.
  • zalgonoise/fts — the typed FTS5 wrapper shape we expanded on.

Documentation

Overview

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.53.1
darwin	arm64   3.53.1
freebsd	amd64   3.53.1
freebsd	arm64   3.53.1
linux	386     3.53.1
linux	amd64   3.53.1
linux	arm     3.53.1
linux	arm64   3.53.1
linux	loong64 3.53.1
linux	ppc64le 3.53.1
linux	riscv64 3.53.1
linux	s390x   3.53.1
windows	386     3.53.1
windows	amd64   3.53.1
windows	arm64   3.53.1

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

Index

Constants

View Source
const (
	SQLITE_INSERT = sqlite3.SQLITE_INSERT
	SQLITE_UPDATE = sqlite3.SQLITE_UPDATE
	SQLITE_DELETE = sqlite3.SQLITE_DELETE
)

SQLite operation codes re-exported for use by hook callbacks. These match the upstream SQLITE_* constants.

View Source
const (
	SQLITE_OK     = sqlite3.SQLITE_OK
	SQLITE_DENY   = sqlite3.SQLITE_DENY
	SQLITE_IGNORE = sqlite3.SQLITE_IGNORE
)

Authorizer return codes.

View Source
const (
	SQLITE_CREATE_INDEX        = sqlite3.SQLITE_CREATE_INDEX
	SQLITE_CREATE_TABLE        = sqlite3.SQLITE_CREATE_TABLE
	SQLITE_CREATE_TEMP_INDEX   = sqlite3.SQLITE_CREATE_TEMP_INDEX
	SQLITE_CREATE_TEMP_TABLE   = sqlite3.SQLITE_CREATE_TEMP_TABLE
	SQLITE_CREATE_TEMP_TRIGGER = sqlite3.SQLITE_CREATE_TEMP_TRIGGER
	SQLITE_CREATE_TEMP_VIEW    = sqlite3.SQLITE_CREATE_TEMP_VIEW
	SQLITE_CREATE_TRIGGER      = sqlite3.SQLITE_CREATE_TRIGGER
	SQLITE_CREATE_VIEW         = sqlite3.SQLITE_CREATE_VIEW
	SQLITE_CREATE_VTABLE       = sqlite3.SQLITE_CREATE_VTABLE
	SQLITE_DROP_INDEX          = sqlite3.SQLITE_DROP_INDEX
	SQLITE_DROP_TABLE          = sqlite3.SQLITE_DROP_TABLE
	SQLITE_DROP_TEMP_INDEX     = sqlite3.SQLITE_DROP_TEMP_INDEX
	SQLITE_DROP_TEMP_TABLE     = sqlite3.SQLITE_DROP_TEMP_TABLE
	SQLITE_DROP_TEMP_TRIGGER   = sqlite3.SQLITE_DROP_TEMP_TRIGGER
	SQLITE_DROP_TEMP_VIEW      = sqlite3.SQLITE_DROP_TEMP_VIEW
	SQLITE_DROP_TRIGGER        = sqlite3.SQLITE_DROP_TRIGGER
	SQLITE_DROP_VIEW           = sqlite3.SQLITE_DROP_VIEW
	SQLITE_DROP_VTABLE         = sqlite3.SQLITE_DROP_VTABLE
	SQLITE_PRAGMA              = sqlite3.SQLITE_PRAGMA
	SQLITE_READ                = sqlite3.SQLITE_READ
	SQLITE_SELECT              = sqlite3.SQLITE_SELECT
	SQLITE_TRANSACTION         = sqlite3.SQLITE_TRANSACTION
	SQLITE_ATTACH              = sqlite3.SQLITE_ATTACH
	SQLITE_DETACH              = sqlite3.SQLITE_DETACH
	SQLITE_ALTER_TABLE         = sqlite3.SQLITE_ALTER_TABLE
	SQLITE_REINDEX             = sqlite3.SQLITE_REINDEX
	SQLITE_ANALYZE             = sqlite3.SQLITE_ANALYZE
	SQLITE_FUNCTION            = sqlite3.SQLITE_FUNCTION
	SQLITE_SAVEPOINT           = sqlite3.SQLITE_SAVEPOINT
	SQLITE_COPY                = sqlite3.SQLITE_COPY
	SQLITE_RECURSIVE           = sqlite3.SQLITE_RECURSIVE
)

Authorizer action codes (a subset matching mattn).

View Source
const (
	SQLITE_ERROR      = sqlite3.SQLITE_ERROR
	SQLITE_BUSY       = sqlite3.SQLITE_BUSY
	SQLITE_LOCKED     = sqlite3.SQLITE_LOCKED
	SQLITE_CONSTRAINT = sqlite3.SQLITE_CONSTRAINT
	SQLITE_MISUSE     = sqlite3.SQLITE_MISUSE
	SQLITE_NOTFOUND   = sqlite3.SQLITE_NOTFOUND
	SQLITE_FULL       = sqlite3.SQLITE_FULL
	SQLITE_DONE       = sqlite3.SQLITE_DONE
	SQLITE_ROW        = sqlite3.SQLITE_ROW
)

Result code constants (subset).

View Source
const (
	SQLITE_CONSTRAINT_CHECK      = sqlite3.SQLITE_CONSTRAINT_CHECK
	SQLITE_CONSTRAINT_FOREIGNKEY = sqlite3.SQLITE_CONSTRAINT_FOREIGNKEY
	SQLITE_CONSTRAINT_NOTNULL    = sqlite3.SQLITE_CONSTRAINT_NOTNULL
	SQLITE_CONSTRAINT_PRIMARYKEY = sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY
	SQLITE_CONSTRAINT_TRIGGER    = sqlite3.SQLITE_CONSTRAINT_TRIGGER
	SQLITE_CONSTRAINT_UNIQUE     = sqlite3.SQLITE_CONSTRAINT_UNIQUE
	SQLITE_CONSTRAINT_ROWID      = sqlite3.SQLITE_CONSTRAINT_ROWID
)

Extended constraint result codes (mattn-compatible aliases).

View Source
const (
	SQLITE_LIMIT_LENGTH              = sqlite3.SQLITE_LIMIT_LENGTH
	SQLITE_LIMIT_SQL_LENGTH          = sqlite3.SQLITE_LIMIT_SQL_LENGTH
	SQLITE_LIMIT_COLUMN              = sqlite3.SQLITE_LIMIT_COLUMN
	SQLITE_LIMIT_EXPR_DEPTH          = sqlite3.SQLITE_LIMIT_EXPR_DEPTH
	SQLITE_LIMIT_COMPOUND_SELECT     = sqlite3.SQLITE_LIMIT_COMPOUND_SELECT
	SQLITE_LIMIT_VDBE_OP             = sqlite3.SQLITE_LIMIT_VDBE_OP
	SQLITE_LIMIT_FUNCTION_ARG        = sqlite3.SQLITE_LIMIT_FUNCTION_ARG
	SQLITE_LIMIT_ATTACHED            = sqlite3.SQLITE_LIMIT_ATTACHED
	SQLITE_LIMIT_LIKE_PATTERN_LENGTH = sqlite3.SQLITE_LIMIT_LIKE_PATTERN_LENGTH
	SQLITE_LIMIT_VARIABLE_NUMBER     = sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER
	SQLITE_LIMIT_TRIGGER_DEPTH       = sqlite3.SQLITE_LIMIT_TRIGGER_DEPTH
	SQLITE_LIMIT_WORKER_THREADS      = sqlite3.SQLITE_LIMIT_WORKER_THREADS
)

SQLITE_LIMIT_* identifiers used with Conn.GetLimit / Conn.SetLimit.

View Source
const (
	// DriverName is the modernc.org/sqlite-compatible driver name.
	DriverName = "sqlite"
	// DriverNameMattn is the github.com/mattn/go-sqlite3-compatible driver name.
	// Registered so existing mattn code that opens with sql.Open("sqlite3", ...)
	// keeps working unchanged.
	DriverNameMattn = "sqlite3"
)

Driver names registered with the database/sql package.

Variables

View Source
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)",
	}
)

Functions

func Deserialize

func Deserialize(ctx context.Context, db *sql.DB, buf []byte) error

Deserialize is a top-level helper that loads buf into the main database of a pool connection borrowed from db. Note: after Deserialize, subsequent pool connections see the new content only for the same physical connection — for most callers, set db.SetMaxOpenConns(1) before calling Deserialize so the loaded image is the only conn the pool ever returns.

func Limit

func Limit(c *sql.Conn, id int, newVal int) (r int, err error)

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 MustRegisterCollationUtf8

func MustRegisterCollationUtf8(
	zName string,
	impl func(left, right string) int,
)

MustRegisterCollationUtf8 is like RegisterCollationUtf8 but panics on error.

func MustRegisterDeterministicScalarFunction

func MustRegisterDeterministicScalarFunction(
	zFuncName string,
	nArg int32,
	xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
)

MustRegisterDeterministicScalarFunction is like RegisterDeterministicScalarFunction but panics on error.

func MustRegisterFunction

func MustRegisterFunction(
	zFuncName string,
	impl *FunctionImpl,
)

MustRegisterFunction is like RegisterFunction but panics on error.

func MustRegisterScalarFunction

func MustRegisterScalarFunction(
	zFuncName string,
	nArg int32,
	xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
)

MustRegisterScalarFunction is like RegisterScalarFunction but panics on error.

func RegisterCollationUtf8

func RegisterCollationUtf8(
	zName string,
	impl func(left, right string) int,
) error

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 RegisterConnectionHook

func RegisterConnectionHook(fn ConnectionHookFn)

RegisterConnectionHook registers a function to be called after each connection is opened. This is called after all the connection has been set up.

func RegisterDeterministicScalarFunction

func RegisterDeterministicScalarFunction(
	zFuncName string,
	nArg int32,
	xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) (err error)

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 RegisterFunction

func RegisterFunction(
	zFuncName string,
	impl *FunctionImpl,
) error

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 RegisterScalarFunction

func RegisterScalarFunction(
	zFuncName string,
	nArg int32,
	xFunc func(ctx *FunctionContext, args []driver.Value) (driver.Value, error),
) (err error)

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 Serialize

func Serialize(ctx context.Context, db *sql.DB) ([]byte, error)

Serialize is a top-level helper that calls (*Conn).Serialize on a fresh pool connection borrowed from db. It is the simplest way to dump an in-memory DB to bytes without manually using db.Conn().Raw(...).

Types

type AggregateFunction

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

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.

type AuthorizerFn

type AuthorizerFn = func(op int, arg1, arg2, dbName, triggerName string) int

AuthorizerFn is the type for an authorizer callback installed via Conn.RegisterAuthorizer. The function is called for every statement compilation step. Return one of:

  • SQLITE_OK: allow the action
  • SQLITE_IGNORE: treat the column as NULL or skip the action silently
  • SQLITE_DENY: reject the statement compilation with an error

op is one of the SQLITE_* authorizer-action constants (see constants.go). arg1, arg2 are op-specific (e.g. table name, column name). dbName is the schema name (typically "main"). triggerName is the name of the trigger or view causing the access; empty for top-level statements.

Mattn-compatibility note: matches mattn's SQLiteConn.RegisterAuthorizer.

type Backup

type Backup struct {
	// contains filtered or unexported fields
}

Backup object is used to manage progress and cleanup an online backup. It is returned by NewBackup or NewRestore.

func (*Backup) Close

func (b *Backup) Close() error

Close releases all resources associated with the Backup. It is equivalent to Finish but the dstConn (if any) is not implicitly closed — mirroring the way mattn's SQLiteBackup.Close behaves.

On the factory-built backups (those returned by (*Conn).Backup), dstConn is nil so Close behaves identically to Finish minus the dst.Close() call.

func (*Backup) Commit

func (b *Backup) Commit() (driver.Conn, error)

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 (*Backup) Finish

func (b *Backup) Finish() error

Finish releases all resources associated with the Backup object. The Backup object is invalid and may not be used following a call to Finish.

When the Backup was produced by NewBackup or NewRestore, the destination connection it implicitly opened is also closed. When the Backup was produced by (*Conn).Backup (the mattn-compat factory), the destination connection is owned by the caller and is not closed here.

func (*Backup) PageCount

func (b *Backup) PageCount() int

PageCount returns the total number of pages in the source database at the most recent completed Step.

Mattn-compatibility API.

func (*Backup) Remaining

func (b *Backup) Remaining() int

Remaining returns the number of pages still to be copied at the most recent completed Step. Returns 0 when the backup is complete.

Mattn-compatibility API.

func (*Backup) Step

func (b *Backup) Step(n int32) (bool, error)

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.

type ColumnInfo

type ColumnInfo struct {
	// Name is the column's name, from sqlite3_column_name.
	Name string
	// DeclType is the declared column type, from sqlite3_column_decltype.
	DeclType string
	// DatabaseName is the name of the source database, from sqlite3_column_database_name.
	// Empty if the column does not resolve to an unambiguous reference to a single database column,
	// such as expressions, function calls, or constants.
	DatabaseName string
	// TableName is the name of the source table, from sqlite3_column_table_name.
	// Empty if the column does not resolve to an unambiguous reference to a single database column,
	// such as expressions, function calls, or constants.
	TableName string
	// OriginName is the name of the source column name, from sqlite3_column_origin_name.
	// Empty if the column does not resolve to an unambiguous reference to a single database column,
	// such as expressions, function calls, or constants.
	OriginName string
}

ColumnInfo describes one output column of a prepared SQL statement.

See https://www.sqlite.org/c3ref/column_database_name.html for more details.

type CommitHookFn

type CommitHookFn func() int32

type Conn

type Conn = conn

Conn is the SQLite database connection type. It is exposed for use inside mattn-style ConnectHook callbacks and for low-level operations such as custom function registration, hooks, backup, and serialize/deserialize.

Conn is identical to the underlying connection struct used by the driver; the alias gives the type an exported name without renaming the internal receiver across every method definition.

func (*Conn) Backup

func (dst *Conn) Backup(destSchema string, src *Conn, srcSchema string) (*Backup, error)

Backup creates a backup-handle that copies the database identified by srcSchema on src into the database identified by destSchema on the receiver. Step the returned *Backup to make progress and call Finish (or Close) to release resources.

Mattn-compatibility API: equivalent to SQLiteConn.Backup, which copies schema "main" by default but accepts any attached schema name.

// Typical mattn pattern: backup live DB to a new on-disk file.
destDB, _ := sql.Open("sqlite3", "backup.db")
destConn, _ := destDB.Conn(ctx)
destConn.Raw(func(dc any) error {
    dst := dc.(*sqlite.Conn)
    bk, err := dst.Backup("main", src, "main")
    if err != nil { return err }
    for {
        done, err := bk.Step(100)
        if err != nil { return err }
        if !done { break }
    }
    return bk.Finish()
})

func (*Conn) EnableLoadExtension

func (c *Conn) EnableLoadExtension(on bool) error

EnableLoadExtension toggles the sqlite3_load_extension C API on or off for this connection. SQLite requires this to be enabled before LoadExtension can be called; it is disabled by default for security.

Mattn compatibility: equivalent to enabling the extension flag before calling LoadExtension.

func (*Conn) GetLimit

func (c *Conn) GetLimit(id int) int

GetLimit returns the current value of one of the SQLite per-connection limits (SQLITE_LIMIT_*). It does not modify the limit.

Mattn-compatibility API equivalent to SQLiteConn.GetLimit.

func (*Conn) LoadExtension

func (c *Conn) LoadExtension(libPath, entry string) error

LoadExtension loads the SQLite extension at libPath into this connection, optionally calling the named entry point (pass "" for the default). The extension flag must be enabled first via EnableLoadExtension(true) unless the connection was opened by a Driver whose Extensions field was non-empty.

Mattn compatibility: equivalent to mattn's SQLiteConn.LoadExtension.

Platform note: success depends on dynamic-loader support in modernc.org/libc. As of v1.72.x, libc's Xdlopen (darwin) and XLoadLibraryW (windows) shims are not implemented and abort the process with "TODOTODO" the moment they're reached — which happens even on the disabled-extensions error path. linux and freebsd are fine. The test suite skips both LoadExtension tests on darwin and windows for that reason; the positive path is platform-dependent.

func (*Conn) RegisterAggregator

func (c *Conn) RegisterAggregator(name string, impl any, pure bool) error

RegisterAggregator registers a Go type with Step and Done methods as a SQLite aggregate function for this connection only.

Mattn-compatibility API: the impl argument must be a function that returns a new instance of an aggregate type. Each invocation of the aggregate at SQL query time creates one instance via impl(), then calls its Step(...) for each row and its Done() at the end. Step's argument types follow the same rules as RegisterFunc; Done returns the aggregate value, optionally with an error.

Setting pure=true marks the aggregate as deterministic.

func (*Conn) RegisterAuthorizer

func (c *Conn) RegisterAuthorizer(fn AuthorizerFn)

RegisterAuthorizer installs an authorization callback consulted for every access to schema objects during statement compilation. Passing a nil callback removes any previously installed authorizer.

Per-connection registration. Mattn-compatibility API.

func (*Conn) RegisterCollation

func (c *Conn) RegisterCollation(name string, cmp func(a, b string) int) error

RegisterCollation registers a Go comparator as a named SQLite collation for this connection only. The comparator must obey the standard sort contract: negative if a < b, zero if a == b, positive if a > b.

Mattn-compatibility API equivalent to SQLiteConn.RegisterCollation.

func (*Conn) RegisterFunc

func (c *Conn) RegisterFunc(name string, impl any, pure bool) error

RegisterFunc registers a Go function as a SQLite scalar function for this connection only.

Mattn-compatibility API: the function impl may have any signature whose argument and return types are supported. Supported argument types are int*, uint*, float64, bool, string, []byte, time.Time, and any (which receives the value as the corresponding Go type from the SQLite value). The function may return a single value, or (value, error). The last argument may be variadic.

Setting pure=true marks the function as deterministic (SQLITE_DETERMINISTIC), allowing SQLite to use it inside indexes and to fold its result for repeated invocations with identical arguments.

The function is registered on this connection only, mirroring mattn's per-connection registration model.

func (*Conn) RegisterUpdateHook

func (c *Conn) RegisterUpdateHook(fn UpdateHookFn)

RegisterUpdateHook installs a callback that fires after every INSERT, UPDATE, or DELETE on a rowid table. Passing a nil callback removes any previously installed hook.

Per-connection registration. Mattn-compatibility API.

func (*Conn) SerializeSchema

func (c *Conn) SerializeSchema(schema string) ([]byte, error)

SerializeSchema returns a serialization of the schema named on this connection. Pass schema = "main" or empty for the main database.

Convenience wrapper around the existing *conn.Serialize method that hides the schema argument from callers who only need the default.

func (*Conn) SetLimit

func (c *Conn) SetLimit(id, newVal int) int

SetLimit sets the given SQLITE_LIMIT_* identifier to newVal and returns the previous value. Pass -1 for newVal to leave the limit unchanged (use GetLimit if that's all you want).

Mattn-compatibility API equivalent to SQLiteConn.SetLimit.

func (*Conn) SetTrace

func (c *Conn) SetTrace(cfg *TraceConfig) error

SetTrace installs (or removes, when cfg.Callback is nil or cfg.EventMask is zero) a tracing callback driven by sqlite3_trace_v2.

Per-connection registration. Mattn-compatibility API.

type ConnectionHookFn

type ConnectionHookFn func(
	conn ExecQuerierContext,
	dsn string,
) error

ConnectionHookFn function type for a connection hook on the Driver. Connection hooks are called after the connection has been set up.

type Driver

type Driver struct {
	// Extensions is a list of SQLite extension shared-library paths to load
	// into every new connection via sqlite3_load_extension. Loaded after the
	// connection is opened but before user ConnectHook fires. Mattn-compatible.
	Extensions []string

	// ConnectHook, if non-nil, is invoked once for every newly-opened
	// connection, after Extensions are loaded and after the modernc-style
	// connection hooks run. Mattn-compatible.
	ConnectHook func(*Conn) error
	// contains filtered or unexported fields
}

Driver implements database/sql/driver.Driver.

Registration functions and methods must be called before the first call to Open.

For drop-in compatibility with github.com/mattn/go-sqlite3, the type alias SQLiteDriver and the public fields Extensions and ConnectHook are provided so existing mattn code that does

sql.Register("custom", &sqlite3.SQLiteDriver{
    Extensions:  []string{"my_ext"},
    ConnectHook: func(c *sqlite3.SQLiteConn) error { ... },
})

continues to work unchanged with this package.

func (*Driver) Open

func (d *Driver) Open(name string) (conn driver.Conn, err error)

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. The currently supported values are (1) "sqlite" for YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM (format 4 from https://www.sqlite.org/lang_datefunc.html#time_values with sub-second precision and timezone specifier) and (2) "datetime" for YYYY-MM-DD HH:MM:SS (format 3, matching the output of SQLite's datetime() function). 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).

_texttotime: Enable ColumnTypeScanType to report time.Time instead of string for TEXT columns declared as DATE, DATETIME, TIME, or TIMESTAMP.

_timezone: A timezone to use for all time reads and writes, such as "UTC". The value is parsed by time.LoadLocation. Writes will convert to the timezone before formatting as a string; it does not impact _inttotime integer values, as they always use UTC. Reads will interpret timezone-less strings as being in this timezone. Values that are in a known timezone, such as a string with a timezone specifier or an integer with _inttotime (specified to be in UTC), will be converted to this timezone.

_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 (*Driver) RegisterConnectionHook

func (d *Driver) RegisterConnectionHook(fn ConnectionHookFn)

RegisterConnectionHook registers a function to be called after each connection is opened. This is called after all the connection has been set up.

type ErrNo

type ErrNo int

Mattn-compatible error code aliases (mattn exposes these as ErrNo values). Code that does `if err.Code() == sqlite.ErrConstraintUnique` continues to work after switching imports.

func (ErrNo) Error

func (e ErrNo) Error() string

Error makes ErrNo satisfy the error interface so it can be used as a target for errors.Is. Equality is the primary-code match implemented in Error.Is.

type ErrNoExtended

type ErrNoExtended int

Extended constraint error code aliases (mattn-compatible).

func (ErrNoExtended) Error

func (e ErrNoExtended) Error() string

Error makes ErrNoExtended satisfy the error interface so it can be used as a target for errors.Is.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error represents a SQLite library error.

The Code accessor returns the primary SQLite result code (low byte). For the full extended code (e.g. SQLITE_CONSTRAINT_UNIQUE = SQLITE_CONSTRAINT | (8 << 8)), use ExtendedCode.

Mattn-compatibility note: mattn's Error struct exposes Code/ExtendedCode as exported fields of type ErrNo / ErrNoExtended; this struct surfaces them as methods to keep field-level compatibility cross-driver. Code that does `if e.Code() == sqlite.SQLITE_CONSTRAINT` works the same as mattn's `if e.Code == sqlite3.ErrConstraint` (compare against ErrConstraint type-cast).

func (*Error) Code

func (e *Error) Code() int

Code returns the primary SQLite result code for this error (low byte of the extended code). Compare against the SQLITE_* constants.

func (*Error) Error

func (e *Error) Error() string

Error implements error.

func (*Error) ExtendedCode

func (e *Error) ExtendedCode() int

ExtendedCode returns the extended SQLite result code for this error (e.g. SQLITE_CONSTRAINT_UNIQUE). Compare against ErrConstraint* constants or the SQLITE_CONSTRAINT_* family.

func (*Error) Is

func (e *Error) Is(target error) bool

Is implements errors.Is. An Error matches another Error if their primary codes match. It also matches a bare ErrNo or ErrNoExtended.

type ExecQuerierContext

type ExecQuerierContext interface {
	driver.ExecerContext
	driver.QueryerContext
}

type FileControl

type FileControl interface {
	// Set or query SQLITE_FCNTL_PERSIST_WAL, returns set mode or query result
	FileControlPersistWAL(dbName string, mode int) (int, error)
	// Query SQLITE_FCNTL_DATA_VERSION, returns the pager-cache data version
	// for dbName. The value changes whenever the contents of the database
	// file change, which makes it suitable for cache-invalidation use cases.
	// See
	// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntldataversion.
	FileControlDataVersion(dbName string) (uint32, error)
}

Access to sqlite3_file_control

type FunctionContext

type FunctionContext struct {
	// contains filtered or unexported fields
}

FunctionContext represents the context user defined functions execute in. Fields and/or methods of this type may get addedd in the future.

type FunctionImpl

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

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.

type HookRegisterer

type HookRegisterer interface {
	RegisterPreUpdateHook(PreUpdateHookFn)
	RegisterCommitHook(CommitHookFn)
	RegisterRollbackHook(RollbackHookFn)
}

type PreUpdateHookFn

type PreUpdateHookFn func(SQLitePreUpdateData)

type Result

type Result = result

Result is the SQLite Exec result, exposed for advanced use.

type RollbackHookFn

type RollbackHookFn func()

type Rows

type Rows = rows

Rows is the SQLite result set type, exposed for advanced use.

type SQLiteBackup

type SQLiteBackup = Backup

SQLiteBackup is an alias for Backup. Mattn compatibility.

type SQLiteConn

type SQLiteConn = Conn

SQLiteConn is an alias for Conn. Mattn compatibility.

type SQLiteDriver

type SQLiteDriver = Driver

SQLiteDriver is an alias for Driver. Mattn compatibility.

type SQLiteError

type SQLiteError = Error

SQLiteError is an alias for Error. Mattn compatibility.

type SQLitePreUpdateData

type SQLitePreUpdateData struct {
	Op           int32
	DatabaseName string
	TableName    string
	OldRowID     int64
	NewRowID     int64
	// contains filtered or unexported fields
}

func (*SQLitePreUpdateData) Count

func (d *SQLitePreUpdateData) Count() int

Count returns the number of columns in the row

func (*SQLitePreUpdateData) Depth

func (d *SQLitePreUpdateData) Depth() int

Depth returns the source path of the write, see sqlite3_preupdate_depth()

func (*SQLitePreUpdateData) New

func (d *SQLitePreUpdateData) New(dest ...any) error

New populates dest with the replacement row data. This works similar to database/sql's Rows.Scan()

func (*SQLitePreUpdateData) Old

func (d *SQLitePreUpdateData) Old(dest ...any) error

Old populates dest with the row data to be replaced. This works similar to database/sql's Rows.Scan()

type SQLiteResult

type SQLiteResult = result

SQLiteResult is an alias for Result. Mattn compatibility.

type SQLiteRows

type SQLiteRows = rows

SQLiteRows is an alias for Rows. Mattn compatibility.

type SQLiteStmt

type SQLiteStmt = stmt

SQLiteStmt is an alias for Stmt. Mattn compatibility.

type SQLiteTx

type SQLiteTx = tx

SQLiteTx is an alias for Tx. Mattn compatibility.

type Stmt

type Stmt = stmt

Stmt is the SQLite prepared statement type, exposed for advanced use.

type TraceConfig

type TraceConfig struct {
	// EventMask is an OR'd set of TraceStmt | TraceProfile | TraceRow | TraceClose.
	// Pass 0 to disable tracing entirely.
	EventMask TraceEvent

	// Callback is invoked for every matching event.
	Callback TraceFn

	// WantExpandedSQL, when true, asks sqlite to expand bound parameters into
	// the SQL text passed to the callback. Slightly more expensive.
	WantExpandedSQL bool
}

TraceConfig configures Conn.SetTrace.

type TraceEvent

type TraceEvent uint

TraceEvent identifies the kind of event reported to a trace callback.

Trace event mask constants. OR these together to filter which events fire.

type TraceFn

type TraceFn = func(TraceInfo) int

TraceFn is the signature of a trace callback. Return non-zero from a row-callback to abort the running query (SQLite contract).

type TraceInfo

type TraceInfo struct {
	// EventCode is the firing event: TraceStmt, TraceProfile, TraceRow, or
	// TraceClose.
	EventCode TraceEvent

	// Statement is the unexpanded SQL text passed to sqlite3_prepare* for
	// stmt/profile events. Empty for row/close events.
	Statement string

	// ExpandedSQL is the SQL with bound parameters substituted, populated for
	// stmt/profile events when the TraceConfig requested it.
	ExpandedSQL string

	// Duration is the wall-clock execution time captured for profile events.
	Duration time.Duration
}

TraceInfo carries a single trace event delivered to a TraceFn.

type Tx

type Tx = tx

Tx is the SQLite transaction type, exposed for advanced use.

type UpdateHookFn

type UpdateHookFn = func(op int, dbName, table string, rowid int64)

UpdateHookFn is the type for an UPDATE/INSERT/DELETE notification hook installed via Conn.RegisterUpdateHook.

op is one of sqlite.SQLITE_INSERT, SQLITE_UPDATE, or SQLITE_DELETE. dbName is the schema name (typically "main"). table is the affected table name. rowid is the rowid of the inserted/updated/deleted row.

Mattn-compatibility note: mattn's callback signature uses int for op.

Directories

Path Synopsis
examples
fts-search command
fts-search example: typed FTS5 API with Porter stemming, BM25 ranking, and snippet/highlight extraction.
fts-search example: typed FTS5 API with Porter stemming, BM25 ranking, and snippet/highlight extraction.
gorm command
gorm example: shows the minimal change to migrate from github.com/Tryanks/gorm-sqlite (or glebarez/sqlite) to github.com/go-again/sqlite/gorm.
gorm example: shows the minimal change to migrate from github.com/Tryanks/gorm-sqlite (or glebarez/sqlite) to github.com/go-again/sqlite/gorm.
gorm-fts command
gorm-fts example: side-by-side pattern for combining gorm-managed schema with FTS5 full-text search.
gorm-fts example: side-by-side pattern for combining gorm-managed schema with FTS5 full-text search.
gorm-vec command
gorm-vec example: side-by-side pattern for combining gorm-managed schema with sqlite-vec virtual tables.
gorm-vec example: side-by-side pattern for combining gorm-managed schema with sqlite-vec virtual tables.
gorm-vfs command
gorm-vfs example: open a gorm.DB against a SQLite database that lives entirely inside an embed.FS-style read-only filesystem.
gorm-vfs example: open a gorm.DB against a SQLite database that lives entirely inside an embed.FS-style read-only filesystem.
mattn-compat command
Mattn-compat example: shows that swapping the blank import from "github.com/mattn/go-sqlite3" to "github.com/go-again/sqlite" needs no other code changes.
Mattn-compat example: shows that swapping the blank import from "github.com/mattn/go-sqlite3" to "github.com/go-again/sqlite" needs no other code changes.
modernc-compat command
modernc-compat example: shows that swapping the blank import from "modernc.org/sqlite" to "github.com/go-again/sqlite" needs no other code changes.
modernc-compat example: shows that swapping the blank import from "modernc.org/sqlite" to "github.com/go-again/sqlite" needs no other code changes.
vec-search command
vec-search example: typed sqlite-vec API.
vec-search example: typed sqlite-vec API.
vfs-embed command
vfs-embed example: bundle a SQLite database inside an embed.FS and open it read-only via the vfs sub-package.
vfs-embed example: bundle a SQLite database inside an embed.FS and open it read-only via the vfs sub-package.
Package fts is a typed, generics-aware wrapper around SQLite's FTS5 full-text-search virtual table, layered on top of github.com/go-again/sqlite.
Package fts is a typed, generics-aware wrapper around SQLite's FTS5 full-text-search virtual table, layered on top of github.com/go-again/sqlite.
Package vec adds first-class vector-search support to github.com/go-again/sqlite by bundling the sqlite-vec extension and a small Go API layered on top of it.
Package vec adds first-class vector-search support to github.com/go-again/sqlite by bundling the sqlite-vec extension and a small Go API layered on top of it.
Package vfs exposes any Go io/fs.FS implementation as a read-only SQLite VFS, so an embed.FS or zip-backed FS can be opened as a database without touching the real filesystem.
Package vfs exposes any Go io/fs.FS implementation as a read-only SQLite VFS, so an embed.FS or zip-backed FS can be opened as a database without touching the real filesystem.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL