Dixie is capped (max_inflight 2, queue_depth 8, queue_wait 20s) and never queued on llama-server. Streaming chat, thinking off, 45s fallback to clean. Digest and chunk-embedding caches are content-addressed SQLite (Honcho context is not cached). Recover uses the guarded Fetcher. guardian-star is refused in code.
68 KiB
Changelog
Entries for v1.38.1 through v1.44.1 and for v1.49.1 were added on 2026-09-05, reconstructed from the git history and the merge requests they cite; they were missing at release time.
-
2026-09-15 v1.59.0:
- Bump the pinned
modernc.org/libcto v1.75.7 and re-vendorlib/andvec/frommodernc.org/libsqlite3v1.14.5 andmodernc.org/libsqlite_vecv0.5.0, which were transpiled against it. As always, downstreamgo.modfiles must pin the samemodernc.org/libcversion as this repository'sgo.mod; see the package documentation and GitLab issue #177. The transpiled SQLite is unchanged: still 3.53.4, byte-identical to v1.58.0 on all 20 targets. The change is beneath it. On the Linux targets libc v1.75.7 replaces the transpiled muslmemcpy,memmove,memset,memcmp,strcspnandfabs, loops moving at most four bytes per step, with native Go routines backed by the runtime's vectorizedmemmoveandmemclrand by thebytespackage; on every targetstrlenis now a word-at-a-time scan, orbytes.IndexByteon the 64-bit architectures. On the three CPU-bound workloads in the new Performance section of the package documentation, measured on linux/amd64 against the same SQLite 3.53.4 compiled from C with the same options, this driver went from 3.0x, 2.2x and 1.6x the CPU time of the C build to 2.0x, 1.9x and 1.3x. The other operating systems already used a native Gomemcpyandmemmoveand see no such change.vec/stays at sqlite-vec v0.1.9; its re-vendor, from a transpile made with newer modernc.org/cc and modernc.org/ccgo, differs only in unreferenced macro constants and in one bounds check spelled withINT8_MAXinstead of its value, so nothing changes in behavior there either. - Hand user-defined function and aggregate callbacks a pooled
*FunctionContextinstead of allocating a fresh one per call. After the[]driver.Valuepooling of #226 this was the last driver-side heap allocation per invocation: one 16-byte object for everyScalar,Step,WindowInverse,WindowValueandFinalcall. The context now also carries the invocation'ssqlite3_context, so accessor methods can be added to it later without touching the trampolines. Like the argument slice, it is valid only for the duration of the callback and must not be retained past its return; the documentation onFunctionContextand on the callbacks now says so. On the 1000-row, 3-argument noop scalar UDF benchmark this removes a further 1000 allocs/op (5756 to 4756, and 3756 to 2756 withVolatileArgs) and 16 KB/op; on the reporter's reproducer from #226 it removes about 12% of the remaining allocations (25.3M to 22.4M allocs/op, 553 MB to 505 MB per iteration). - Updates GitLab issue #226. See GitLab merge request #137.
- Add regression tests for the pooled context: two functions evaluated in one statement must receive two different
sqlite3_contextvalues and every callback's context must belong to the invoking connection, checked on two connections held at once and without dereferencing the context, so that a stale one is reported rather than faulted on; eight connections held at once calling a function from their own goroutines, and a function that runs a statement invoking another function, both meant for the race detector. See GitLab merge request #138, thanks Ian Chechin! - Add a Performance section to the package documentation. It records the measured CPU-time ratios of this driver against the same SQLite compiled from C, that they hold under concurrency, where the gap comes from, and the two consequences for applications: index the columns that
ORDER BY,GROUP BYandWHEREuse, because a query that is merely sluggish in C can cross a deadline here, and bound thedatabase/sqlpool withSetMaxOpenConns, because a periodic query that outlasts its period piles up connections without bound. Prompted by a report that attributed a 103 s query to the driver spilling a temporary b-tree in Go; the workload showed no spill and about 2x the CPU cost of C, the wall time being unbounded overlap of periodic polls.
- Bump the pinned
-
2026-09-01 v1.58.0:
- Upgrade to SQLite 3.53.4. Upstream's own fix for the journal-rollback data-corruption bug is part of this release, so the local super-journal patch v1.56.0 introduced — and promised to drop once upstream shipped theirs — is dropped; recovery behavior is unchanged. This also bumps the pinned
modernc.org/libcto v1.75.6; as always, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins (see GitLab issue #177). - Add opt-in support for Linux Open File Description (OFD) locks on database files. A POSIX record lock is owned by the (process, inode) pair, so the kernel drops every lock the process holds on a database file whenever any descriptor of that file is closed: an
os.Open/Closefor a hash, a backup check or a metadata probe anywhere in the process — third-party libraries included — silently strips SQLite's transaction locks and leaves the file unprotected against other processes. With OFD locking enabled, the locks belong to the open file description that placed them and survive such a close. Off by default, and staying off until the mode has real-world mileage: without opting in, locking behavior is byte-for-byte that of previous releases. Enable it by settingMODERNC_SQLITE_OFD_LOCK=1in the environment the process starts with (any value but the empty string or one starting with0; read once, at library initialization), or from Go with the newOFDLocking(true), which overrides the variable and must run before the first connection is opened;OFDLockingEnabledreports the mode in effect. The switch is deliberately process-wide rather than a DSN parameter: POSIX and OFD locks taken by one process are different owners to the kernel and genuinely conflict, so every connection to a database file inside one process must use the same kind, and a per-DSN knob would advertise a granularity the kernel does not offer (see the discussion in #255). Because the two kinds do not release one another, the mode is frozen at the process's first lock attempt: later attempts to change it return the newErrOFDLockingTooLate, while querying, and setting the value already in effect, keep working. On kernels older than 3.15, and on filesystems that reject OFD locks, the first lock attempt falls back to POSIX locks for good andOFDLockingreturns the newErrOFDLockingUnavailablefrom then on, which is also howOFDLockingEnabledturning false reports the fallback; the same error is returned on every platform but Linux, where the API exists but OFD locks do not. Two boundaries to note: the immunity covers the locks on the database file itself, while WAL's-shmcoordination stays on POSIX locks; and code in the same process that takes fcntl record locks of its own on a database file — which used to never conflict with SQLite's, while quietly destroying them — now conflicts with them loudly instead. The C side —F_OFD_SETLKrouting through a designated per-inode locking descriptor that preserves upstream'sunixInodeInfosemantics (last-unlocker release, PENDING piggybacking,unix-excl), guarded to__linux__— ships in the transpiled sources via libsqlite3!3 and its follow-up hardening, with the OFD lock constants from libc!33; the review rounds, the/proc/locksmeasurements behind the design, and the Tcl lock/WAL gate that runs both modes are recorded in GitLab issue #255 and those merge requests. - Add the accompanying regression tests. The four OFD scenarios contributed in merge request #136 — lock survival across a rogue
os.Close, the interleaved-readers lock lifecycle, the read-only-first designated-descriptor migration, and the failed-first-lock cleanup — run in a re-executed child process withMODERNC_SQLITE_OFD_LOCK=1, since the mode is process-wide and frozen at the first lock so the suite's own process cannot switch; a positive control asserts the variable really switched the mode on before each scenario runs, and the two scenarios whose invariants hold under both modes also run in the parent process's inherited mode.TestOFDLockingSetterexercises the Go call path end to end in a clean child — off by default, enabled before the first connection, the kernel-visibleOFDLCKrecord in/proc/locksas the positive control, frozen after the first lock — and on every other platform the switch is asserted to report itself unavailable. - Resolves GitLab issue #255. See GitLab merge request #136, thanks Nathan Herring (@technosloth), and thanks Gani Georgiev (@ganigeorgiev) for pressing the opt-in default!
- Upgrade to SQLite 3.53.4. Upstream's own fix for the journal-rollback data-corruption bug is part of this release, so the local super-journal patch v1.56.0 introduced — and promised to drop once upstream shipped theirs — is dropped; recovery behavior is unchanged. This also bumps the pinned
-
2026-08-19 v1.57.0:
- Add an opt-in
_defensiveDSN query parameter that turns on SQLite's defensive mode for the connection, disabling the SQL-level features that let ordinary statements deliberately corrupt the database file. When_defensive=1(or anystrconv.ParseBooltrue value) is supplied, the driver callssqlite3_db_configwithSQLITE_DBCONFIG_DEFENSIVEimmediately aftersqlite3_open_v2and before every other parameter is applied, so the PRAGMAs the driver itself runs, the_pragmalist, and every statement the caller prepares are all subject to it. On such a connectionPRAGMA writable_schema=ON,PRAGMA journal_mode=OFFandPRAGMA schema_version=Nbecome silent no-ops, and writes to a virtual table's shadow tables (fts5's_data,_idxand so on) and tosqlite_dbpagefail with "table ... may not be modified"; reading those tables, ordinary use of the virtual tables that own them, andVACUUMare unaffected. The flag has no PRAGMA equivalent, sosqlite3_db_config— and therefore a DSN parameter — is the only way to reach it short of dropping tomodernc.org/sqlite/lib. The value is parsed beforesqlite3_open_v2, so an invalid one fails the connection without creating the database file, and the parameter must appear at most once: a repeated_defensiveis an error rather than letting the first value silently win. Absence of the parameter, or_defensive=0, leaves SQLite's default behavior unchanged; existing DSNs continue to work byte-for-byte. Two limits are worth stating plainly, since the name invites more confidence than the flag earns. Defensive mode is a hardening measure, not a sandbox for hostile database files: it is one of several steps SQLite recommends for that purpose, and this build compiles with neitherSQLITE_TRUSTED_SCHEMA=0norSQLITE_DQS=0and exposes no authorizer. And it is a property of the connection, not of the database file — a second handle opened on the same file without the parameter is unrestricted. - Reject the one DSN combination defensive mode would otherwise swallow in silence.
_defensive=1together with_journal_mode=OFF(or_journal=OFF) now fails the connection instead of opening one in which neither parameter was honoured: SQLite turnsPRAGMA journal_mode=OFFinto a no-op that still reports success, so the driver would have accepted the mode, executed it, and left the journal untouched without telling anyone. The check runs in the validation phase introduced in v1.55.0, before any statement executes, so a rejected DSN cannot leave the database half-configured._pragmaremains the exception it has always been:_pragma=journal_mode(OFF)alongside_defensive=1still runs and is still silently ignored by SQLite. Only DSNs using_defensivecan be affected, and that parameter is new, so no DSN that opened before changes behavior. - See GitHub pull request #6, thanks wsman!
- Ship the sqlite-vec license notice this module has been missing.
modernc.org/sqlite/vechas bundled the transpiled sqlite-vec sources since v1.47.0, but the module carried only its own BSD-3-ClauseLICENSEand the public-domain SQLite notice. sqlite-vec is Copyright (c) 2024 Alex Garcia, dual-licensed Apache-2.0 OR MIT and used here under MIT, whose terms require the copyright and permission notice to accompany substantial portions of the software — which 2.8 MB of transpiledvec/plainly is. The notice now ships asLICENSE-SQLITE_VECin the module root, byte-identical to theLICENSE-MITin the upstream v0.1.9 archive and named after the filemodernc.org/libsqlite_vecextracts it into. Attribution was never absent —vec's package documentation has named the extension, pinned the version and linked upstream — but the license text itself was, and the omission was ours:vendor_libs/main.gocopied the per-target transpiles and nothing else. It now copies the notice alongside them and fails the vendoring run if it cannot, so amake vendorcan no longer quietly drop it. Thevecpackage documentation gained a License section recording that the package is under a different license from the rest of this module. - The SQLite notice is renamed from
SQLITE-LICENSEtoLICENSE-SQLITE; update any direct links to it. Its contents are unchanged and SQLite remains public domain. The name now matches both the newLICENSE-SQLITE_VECbeside it and theLICENSE-<upstream>convention every other modernc.org repository follows, but it is more than cosmetic:go mod vendorselects the files it copies into a downstreamvendor/tree by matching each name against a fixed list of prefixes —LICENSEamong them — so a name merely ending inLICENSEwas never propagated. Both bundled notices now travel with the code into vendored builds, which is where the MIT terms onvec/keep applying. No code changes; no behavior changes. - Let a caller-constructed
Driverregister its own functions, collations and virtual table modules.Driverhas always held four categories of registration state, but onlyRegisterConnectionHookcould put anything on a constructed one: functions and collations were reachable through the package-level API alone, and modules through the package-level driver only, which left themodulesfield written and read through that instance and so process-global state wearing a per-instance field.Drivernow hasRegisterFunction,RegisterScalarFunction,RegisterDeterministicScalarFunction,RegisterCollationUtf8andRegisterModule, plusMust*variants of the first four, each registering on thatDriveralone; the methods are safe to call concurrently, and the zeroDriveris ready to use as-is.vtab.RegisterModulealso honours itsdbargument now: a non-nildbregisters on the driver backing it when that driver implements the newvtab.ModuleRegisterer, while a nildbkeeps targeting the driver this package registers assqlite. One existing pattern changes behavior, narrowly and loudly:vtab.RegisterModule(db, ...)wheredbwas opened on a caller-constructedDriverused to discard thedbargument and land on thesqlitedriver, reaching every connection in the process; it now lands on the constructed driver alone, so asql.Open("sqlite")connection that used to resolve such a module getsno such moduleinstead. The same pattern is also the one way an existing program could hold one module name on both a constructedDriverand the package-level one: there the first of the two registrations used to win and the second was refused as already registered, whereas now the package-level implementation wins on the constructedDriver's connections regardless of the order they ran in. Reaching that case at all means the program ignored an error the older version returned. Two smaller deviations round out the list:Driver.RegisterModulereports no error for such a collision, andvtab.RegisterModulenow validates its name and module arguments before the not-implemented check, so a call with an empty name that returnedvtab: RegisterModule not wired into engineoutside this driver returnsvtab: module name must be non-emptyinstead. Everything else is additive against v1.56.0: the package-level registration functions target the same driver they always did, connections still receive every module registered through the package-level path whicheverDriveropened them, and adbopened on thesqlitedriver resolves to that same driver. The isolating change discussed in GitLab issue #254 is deliberately not made here. - See GitLab merge request #135, thanks Ian Chechin!
- Promote
freebsd/386,freebsd/armandnetbsd/amd64to fully supported platforms. All three are now listed in the package documentation's platform table, which had carried seventeen entries while this module shipped, cross-built and tested twenty. They arrived as experimental in v1.53.0 —netbsd/amd64reviving a port that had been broken for years,freebsd/386replacing a stale, effectively untested SQLite 3.41 transpile, andfreebsd/armentirely new — and were deliberately kept out of that table until they had accumulated real-world exposure, with promotion promised once "a period of broader real-world testing … elapses without surprises". That period has elapsed: all three have been in the builder test matrix and inmake build_all_targetssince v1.53.0, all three pass the full test suite on this release's commit alongside the seventeen platforms already listed, and no open issue reports a defect in any of them. The twonetbsd/amd64build failures filed before the revival, GitLab issue #202 and GitLab issue #234, no longer reproduce at this commit:Xsqlite3_is_interruptedis present in the sources that target selects, and themu.enter/mu.leavesymbols that broke the build are gone. Documentation only — the transpiled sources underlib/are byte-for-byte what v1.56.0 shipped, and nothing about how these targets behave changes.
- Add an opt-in
-
2026-08-03 v1.56.0:
- Re-vendor the transpiled SQLite sources, picking up
modernc.org/libsqlite3's fix for an upstream data-corruption bug in SQLite 3.53.3's journal rollback. The SQLite version is unchanged at 3.53.3; what changes is that the amalgamation is now patched before it is transpiled. 3.53.3 reworkedreadSuperJournal()to return the super-journal name through achar**out-parameter, andpager_playback()now tests that pointer where it used to testzSuper[0]. A crash during the commit of a multi-database (ATTACH) transaction can leave the super-journal name and its checksum zeroed while the name length and the trailing magic survive; the checksum is a plain byte sum, so an all-zero name still validates andreadSuperJournal()hands back a non-NULL pointer to an empty string.pager_playback()then callssqlite3OsAccess(pVfs, "", SQLITE_ACCESS_EXISTS), gets ENOENT, and deletes the hot journal without playing it back — leaving the database corrupted. This is not a transpilation artifact: a plain gcc build of the stock 3.53.3 amalgamation fails on the same bytes while 3.53.2 recovers them, and it is what has been making upstream's owntest/crash.testfail intermittently, in roughly 2% of runs, on every platform. The patch restores the pre-3.53.3 behaviour of reporting a(nul)super-journal name and will be dropped once upstream ships its own fix. Every supported target carries it. - Two targets change beyond that patch. On
linux/s390xthe regenerated transpile allocates C bit-fields MSB-first, as the big-endian platform ABI requires, rather than LSB-first; this comes frommodernc.org/cc/v4v4.29.1 and touches bit-field accesses throughout the SQLite core, s390x being this module's only big-endian target. Onlinux/riscv64the transpile was regenerated on a host running GCC 11.4.0 where the previous one used GCC 13.3.0, which drops a handful of unexported compiler-predefined macro constants (the__FLT16_*family,__DBL_IS_IEC_60559__and friends) and changes theCOMPILER=gcc-13.3.0entryPRAGMA compile_optionsreports toCOMPILER=gcc-11.4.0; no SQLite code generation differs. Every other target's generated code is byte-identical to v1.55.0 apart from the journal-rollback patch above. - Bump the pinned
modernc.org/libcto v1.74.4, and the remaining dependencies to their current releases. v1.74.2 and v1.74.3 are retracted upstream — afreeaddrinfolock leak that deadlocks name resolution — and v1.74.4 is the fix. As always, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins (see GitLab issue #177). - Documentation sweep.
openbsd/amd64andopenbsd/arm64join the supported platforms table in the package documentation: both have been in the builder test matrix since January and are cross-built bymake build_all_targets, but had never been listed. ThevfsDSN query parameter — which names a VFS registered with SQLite, such as one returned byvfs.New— is now documented alongside the other DSN parameters onDriver.Open. The "Debug and development versions" section no longer describes aGO_GENERATEenvironment variable and ago generatethat this repository has not had sincegenerator.gomoved tomodernc.org/libsqlite3; it now points at that repository andmake vendorinstead, and the stale//go:generatedirective naming the removed file is dropped with it.modernc.org/sqlite/vecandmodernc.org/sqlite/vfsgained the package doc comments they were missing, so both finally carry a synopsis on pkg.go.dev. Documentation only; no behavior changes. - Add
NewConnector, returning adatabase/sql/driver.Connectorfor use withsql.OpenDB. It opens the same connectionssql.Open("sqlite", dsn)does, from the same registered driver, so every function, collation, connection hook and virtual table module registered through this package applies to them. It exists for callers that need to interpose on the physical connectionsdatabase/sqlopens — tracing, metrics, connection-scoped setup — whichsql.Opengives no access to: such a caller can embed the returnedConnector, overrideConnect, and pass its own wrapper tosql.OpenDB. Previously the only way to reach the registered driver was thedb, _ := sql.Open("sqlite", ""); drv := db.Driver(); db.Close()idiom, which works only becausesql.Opendoes not connect and this driver does not implementdriver.DriverContext; and the only way to get a wrapper into a*sql.DBwassql.Register, which is process-global, panics on a name it has already seen, and cannot be undone, so a library had to invent a unique driver name per configuration.sql.OpenDBregisters nothing. Constructing a&sqlite.Driver{}is not an alternative — its fields are unexported, so it carries none of the registrations.NewConnectorchecks the DSN only as far as it can without opening a database — a query string that does not parse, and conflictingvfsparameters; everything else continues to be validated when the connection is opened, so an unknown parameter or an out-of-range value is reported byConnectrather than at construction. Nothing about the existingsql.Openpath changes:*Driverdeliberately still does not implementdriver.DriverContext, sosql.Openremains lazy and DSN errors continue to surface where they always have. A runnable sample is inexamples/connector. Resolves GitLab issue #253, thanks Alessandro Segala (@ItalyPaleAle)! - Document that a caller-constructed
sqlite.Driveris not the driver this package registers as"sqlite". Its fields are unexported, so it starts with no functions, collations or connection hooks and the only way to give it any is its ownRegisterConnectionHookmethod; the package-levelRegister*functions always apply to the registered driver. Connections such aDriveropens therefore run without the package-level functions and collations — and because a registered function silently replaces a SQLite built-in of the same name, aDriveryou construct can evaluateupper(x),date(x)and the like differently from one opened throughsql.Open. Virtual table modules are the one exception: they are held process-globally and reach everyDriver. Constructing one remains supported for the private-hook pattern — a driver registered under a name of its own withsql.Registerso its connection hooks apply only to its own connections — and is otherwise best avoided in favour ofsql.OpenorNewConnector. Documentation only; no behavior changes.
- Re-vendor the transpiled SQLite sources, picking up
-
2026-07-20 v1.55.0:
- Add
github.com/mattn/go-sqlite3-compatible shorthand DSN query parameters to ease migration from that driver:_busy_timeout/_timeout,_foreign_keys/_fk,_journal_mode/_journal,_synchronous/_sync,_auto_vacuum/_vacuum, and_query_only, each setting the correspondingly named PRAGMA. Values are validated against the same setmattn/go-sqlite3accepts (case-insensitive) and an unrecognized value fails the connection with an error, so a typo such as_synchronous=fu1lor_foreign_keys=yes_pleaseis reported rather than silently downgrading durability or dropping foreign-key enforcement. The keys are applied in a fixed order independent of their order in the DSN —_busy_timeoutand_auto_vacuumbefore any_pragmavalues (auto_vacuummust be set before the database is first written), the rest after, and_query_onlylast — and where a key and its alias are both supplied the alias wins, matchingmattn/go-sqlite3; selection is by presence rather than by value, so supplying the alias empty (_foreign_keys=on&_fk=) suppresses the PRAGMA rather than deferring to the primary key, again matching that driver. Behavior change to note: prior releases ignored these keys entirely, so a DSN carried over from amattn/go-sqlite3setup changes in two ways. A recognized key that previously did nothing now takes effect —_foreign_keys=onbegins enforcing constraints against data that may already violate them,_journal_mode=walpersistently converts the database file, and_query_only=1makes the connection read-only. And a value outside the accepted set now fails the connection with an error where the same DSN previously opened successfully — for example a duration-style_busy_timeout=5sor_timeout=5000ms, neither of which is the integer that key requires. Review such DSNs before upgrading._pragmais unchanged and no pre-existing parameter changes meaning, though see the following entry for a change in when all of them are validated. - See GitLab merge request #134, thanks Toni Spets (@beeper-hifi) and Ian Chechin!
- Validate every DSN query parameter before applying any of them. Parameters were previously checked as each was reached, so a DSN whose later parameter was rejected had already executed the PRAGMAs ahead of it. Because
PRAGMA journal_modeandPRAGMA auto_vacuumare persistent changes to the database file, a DSN such asfile:x.db?_journal_mode=wal&_synchronous=bogusfailed the connection and yet leftx.dbconverted to WAL. A failedOpennow leaves the database as it found it. This covers the pre-existing_txlock,_timezone,_time_format,_time_integer_format,_inttotimeand_texttotimeparameters as well as the shorthand keys above: all of them were validated only after the_pragmalist had already run, so the same DSN shape — a valid_pragma=journal_mode=walalongside a misspelled_txlock— converted the file before reporting the error. Only the values accepted for each parameter are unchanged; a DSN that opened successfully before still opens, and one that failed still fails with the same error._pragmaremains the sole exception, since its values are executed verbatim and cannot be checked in advance: a malformed_pragmais still rejected by SQLite as it runs, after any earlier_pragmain the list has taken effect.
- Add
-
2026-07-15 v1.54.0:
- Upgrade to SQLite 3.53.3. This also bumps the pinned
modernc.org/libcto v1.74.1; as always, downstream modules must pin the exact samemodernc.org/libcversion this module'sgo.modpins (see GitLab issue #177). - Under the opt-in
_texttotimeDSN parameter, best-effort parse date-shaped TEXT values from columns SQLite reports with an empty declared type — aggregates and expressions over a date column (MAX(d),COALESCE(d, ...),upper(d),d || ''), subqueries, and typeless real columns (CREATE TABLE t(x)) — intotime.Time, instead of delivering them as a raw string thatScancannot store into a*time.Time. The existing declaredDATE/DATETIME/TIME/TIMESTAMPpath is unchanged; this only adds the empty-decltype case. The conversion is strictly best-effort: a value that does not parse as a time falls through to the original string, so noScanthat worked before can newly fail.ColumnTypeScanTypecontinues to reportstringfor empty-decltype columns, since the declared type cannot prove the column is temporal. Without_texttotimethe behavior is byte-for-byte unchanged. Resolves GitLab issue #248. - See GitLab merge request #133, thanks Ian Chechin!
- Upgrade to SQLite 3.53.3. This also bumps the pinned
-
2026-06-21 v1.53.0:
- Add experimental
netbsd/amd64support, resolving the long-standing build break in GitLab issue #246. This target is intentionally not yet listed among the supported platforms in the package documentation: the port had been broken for years and is only now revived, and there is as yet no real-world experience running it under production workloads. Green CI is not the same as battle-tested — so while the full test suite (including thepcacheandvecpackages and the-raceconcurrency test) passes on NetBSD 10.1 / Go 1.26.3, and the entire upstream toolchain (libc,cc,ccgo,libz,libtcl8.6,libsqlite3,libsqlite_vec) is green on the NetBSD CI builder, the target is offered for evaluation only. If you run NetBSD, please exercise it with your own workloads and report back via #246; the intent is to promote it to a fully supported platform after a period of broader real-world testing (on the order of a month) elapses without surprises. - Implementation notes: the previously shipped
lib/sqlite_netbsd_amd64.gowas a stale old-generator transpile that no longer compiled (themu.enter/mu.leavebreak in #246); it is replaced by a fresh new-generator transpile consistent with every other platform, andmodernc.org/sqlite/vec(sqlite-vec) is vendored and auto-registers on netbsd. Correct operation requires the matching pinnedmodernc.org/libc, which carries two NetBSD-specific fixes found during this work: themmap(2)PAD-argument ABI (without it, concurrent WAL access faults with SIGBUS in the WAL-index shared memory) and a workingabort(3)(the prior stub left SQLite's crash-recoverywritecrashtest unable to terminate by signal). As usual, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins. - See GitLab merge request #82, thanks Leonardo Taccari (@iamleot) and Thomas Klausner (@wiz)!
- Add experimental
freebsd/386andfreebsd/armsupport. As with thenetbsd/amd64target above, these two 32-bit FreeBSD ports are intentionally not yet listed among the supported platforms in the package documentation:freebsd/386previously shipped a stale, effectively untested SQLite 3.41 transpile, andfreebsd/armis entirely new, so neither has real-world production mileage yet. Both are now freshly transpiled at SQLite 3.53.2 consistent with every other platform, build cleanly, and pass the full test suite (core, WAL/concurrency, and thevecpackage) on the FreeBSD CI builders; they are offered for evaluation only. If you run 32-bit FreeBSD, please exercise these targets with your own workloads and report back — the intent is to promotefreebsd/386,freebsd/arm, andnetbsd/amd64to fully supported platforms in a future release cycle, once a period of broader real-world testing elapses without surprises. - Implementation notes: correct operation on
freebsd/armrequires the matching pinnedmodernc.org/libc(v1.73.4), which fixes the per-archmmap(2)off_tencoding for 32-bit FreeBSD; without it the WAL shared-memory mapping faults with SIGBUS under concurrent access, the same class of bug found on the netbsd port. As usual, downstream modules must pin the exactmodernc.org/libcversion this module'sgo.modpins. - See GitLab merge request #119, thanks Olivier Cochard-Labbé (@ocochard)!
- Add a Go-facing wrapper for
SQLITE_CONFIG_PCACHE2.PageCacheis the factory andCachethe per-database instance, both idiomatic Go interfaces;Pageexposes the rawBufandExtrapointers that SQLite reads through the C pcache contract.RegisterPageCacheandMustRegisterPageCacheinstall the module process-globally before the firstsql.Open; subsequent Open calls are gated through a one-shotXsqlite3_config(SQLITE_CONFIG_PCACHE2)so a too-late Register returnsErrPageCacheTooLaterather than silently falling through to the built-in pcache1. The binding owns thesqlite3_pcache_pagestub and re-consults the implementation on every Fetch, reusing the stub only when the returnedPagevalue is unchanged, which keeps a bounded/evicting purgeable cache safe by construction. - See GitLab merge request #126, thanks Ian Chechin!
- Add
modernc.org/sqlite/pcache, the reference page-cache implementation that accompanies the #126SQLITE_CONFIG_PCACHE2wrapper.pcache.Newreturns a*Poolsatisfying thePageCacheinterface; register it once withsqlite.MustRegisterPageCache(pcache.New())and every connection opened afterwards draws its pages from it. EachPool.Createmints a fresh per-databaseCache: a bounded, LRU-evicting page store that honours thePRAGMA cache_sizesoft cap and releases the least-recently-unpinned page when it must make room. Page memory — theBufandExtrabuffers SQLite reads through — is allocated withlibc.Xmalloc/libc.Xcallocand therefore lives off the Go heap, which keeps SQLite's interior pointer arithmetic on the page extras from tripping the race detector's checkptr enforcement.Pool.Statsreports aggregate lifetime counters (hits, misses, allocs, evictions, rekeys, truncates, caches) across every cache a Pool has created, so hit/miss/eviction behaviour is observable without instrumenting individual caches. Cross-connection page sharing is out of scope for now; eachCreatereturns an independent per-database cache. - Validated end-to-end against the #126 stress workload (
cache_size=16, 4000 BLOB rows with DELETE andincremental_vacuum,integrity_checkclean under-race) and benchmarked for the memory-utilization goal tracked in GitLab issue #204. - See GitLab merge request #127, thanks Ian Chechin!
- Tighten the
modernc.org/sqlite/pcachereference implementation per cznic's !127 review follow-ups. AddsStats.EasyRefusals, a per-Pool counter for the cases whereFetchCreateEasyreturns nil at cap; SQLite reacts to a refusal by spilling dirty pages and retrying withFetchCreateForce, so the new field is a direct proxy for the I/O pressure the strict Easy contract imposes vs pcache1's recycle-without-spill behavior.BenchmarkPoolEvictionChurnwas reworked to drive a rotating-residue DELETE (k % 3 = i % 3) and re-insert a matching batch each cycle so the spill pressure recurs andeasy-refusals/opscales withb.Ninstead of capping at the seed's one-time first-cycle cost; both existing benchmarks now reporteasy-refusals/opalongside the page-allocs/evictions metrics.Stats.Evictionsdocumentation was tightened to match the actual behavior (counts LRU eviction,Unpin(discard=true),Shrinkreleases, andUnpin(discard=false)trimming back to target after aFetchCreateForceovercommit; bulk frees fromTruncate,Rekeycollisions, andDestroyare not counted). TheTestPoolRoundTripIntegritycomment claiming the workload exercisesxRekey~15 times has been corrected; the SQL surface does not reliably emit xRekey here, and that codepath is covered by the unit tests instead. - See GitLab merge request #130, thanks Ian Chechin!
- Make
modernc.org/sqlite/pcache-race-clean under SQLite'scache=sharedmode. The pool already runs correctly under shared-cache because every callback into a givenCacheis serialised internally by SQLite'ssqlite3BtreeEnteron theBtSharedmutex; verified empirically with a lock-free in-flight probe (max-in-flight = 1 on the canonical two-connection workload, 4 on a positive control with goroutines hitting the cache directly). However the Go race detector does not recognise SQLite's libc mutex as a happens-before edge and reports false-positive races onFetchvsUnpinreads/writes of the per-cache state, which surfaces asDATA RACEfailures for any user who registers the pool and runs their suite under-race. Async.Mutexon thecachetype is now taken on every public method (SetSize,PageCount,Fetch,Unpin,Rekey,Truncate,Destroy,Shrink), always. On the common non-shared-cache path the lock is uncontended (one atomic CAS per Lock/Unlock pair, negligible next to the SQLite work it bookends); on the shared-cache path it just rubber-stamps the order SQLite'sBtSharedmutex already established. A newe2e_test.goTestSharedCacheTwoConns_Integritydrives twosql.Connagainst the samecache=sharedURI with concurrent writers and assertsPRAGMA integrity_check = okunder-race; passes cleanly with the lock, would surface the false-positive without it. Design notes live inpcache/sharing.go. - See GitLab merge request #131, thanks Ian Chechin!
- Add a Go wrapper for
sqlite3_db_status, the per-connection runtime counters (cache hit/miss/write/spill rates, schema and prepared-statement memory, lookaside usage, deferred foreign keys).DBStatusis an interface implemented by the driver connection and reached through thedatabase/sqlescape hatch(*sql.Conn).Raw(), mirroring the existingFileControlsurface;DBStatusOpis a distinct typed enum of theSQLITE_DBSTATUS_*verbs so a counter from a different op family will not compile in its place.Status(op, reset)returns the(current, high)pair and optionally resets the counter. This also letsmodernc.org/sqlite/pcachemeasure real I/O instead of theEasyRefusalsproxy: the newBenchmarkPoolSpillIOreads the pager-levelSQLITE_DBSTATUS_CACHE_SPILL/_CACHE_WRITEcounters, which the pager maintains identically for pcache1 and the pool, making the pcache1-vs-pool comparison cznic raised on the !127 review a genuine apples-to-apples measurement. On the rotating-residue eviction-churn workload atcache_size=16the pool spills ~3.5x more than pcache1 (cache-spill/op 31.96 vs 8.96) for ~3% more page writes (cache-write/op 450 vs 436) at identical hit/miss, quantifying the I/O cost of the strict Easy contract thatEasyRefusalsonly proxied. - See GitLab merge request #132, thanks Ian Chechin!
- Add an opt-in
_dqsDSN query parameter that disables SQLite's double-quoted string literal compatibility quirk on a per-connection basis. When_dqs=0(or anystrconv.ParseBoolfalse value) is supplied, the driver callssqlite3_db_configwithSQLITE_DBCONFIG_DQS_DDLandSQLITE_DBCONFIG_DQS_DMLset to off before any statement is prepared, so a double-quoted identifier that fails to resolve raises a parse error instead of silently falling back to a string literal. Absence of the parameter, or_dqs=1, leaves SQLite's default behavior unchanged; existing DSNs continue to work byte-for-byte. Resolves GitLab issue #61. - See GitLab merge request #128, thanks Ian Chechin!
- Add an opt-in
_error_rcDSN query parameter for clearer error reporting on open-time failures. When_error_rc=1(or anystrconv.ParseBooltrue value) is supplied, error strings synthesised from a(rc, db)pair only appendsqlite3_errmsg(db)whensqlite3_extended_errcode(db)is consistent with the operation rc (full match first, primary code&0xffas fallback). On mismatch the canonicalsqlite3_errstr(rc)is used alone, so an open-timeSQLITE_CANTOPENno longer carries the temporary handle's stale "out of memory" errmsg. Absence of the parameter, or_error_rc=0, preserves the legacy "errstr: errmsg" form byte-for-byte; existing callers that parse error strings are unaffected. The driver's*Error.Code()returns the same SQLite result code in both modes. Parsed beforesqlite3_open_v2so open-time errors are covered. Resolves GitLab issue #230. - See GitLab merge request #129, thanks Ian Chechin!
- Add experimental
-
2026-06-06 v1.52.0:
- Upgrade to SQLite 3.53.2.
- Add
Backup.RemainingandBackup.PageCount, thin wrappers around the existingsqlite3_backup_remainingandsqlite3_backup_pagecountC symbols. Together they expose the per-Stepprogress counters that the underlying backup object already maintains, enabling progress reporting during online backups without dropping tomodernc.org/sqlite/libdirectly. - See GitLab merge request #122, thanks Ian Chechin!
- Drop the redundant second copy in
(*conn).columnText, the path that backs everyRows.Scaninto a Gostringfor a TEXT column. The value's bytes are still copied once out of SQLite-owned memory into a fresh Go buffer; that buffer is then reinterpreted as the result string withunsafe.Stringrather than copied a second time by the implicitstring([]byte)conversion. This removes one allocation per TEXT value per row and roughly halves the bytes allocated on that path; on the newBenchmarkColumnTextScancases it is ~13–20% faster for payloads of 256 B and larger, with no measurable change for very short strings. Purely internal: no API or behavioral change, and the returned string never aliases SQLite's buffer. - See GitLab merge request #123, thanks Ian Chechin!
- Cache each result column's declared type once per result set in
newRowsinstead of recomputing it on every row. The TEXT branch ofRows.NextcallsColumnTypeDatabaseTypeNamefor every TEXT column on every row (independent of any DSN flag), which previously did alibc.GoString+strings.ToUppereach time; that lookup is now a single index into a cached, pre-uppercased[]string, andColumnTypeScanTypereads the same cache and drops its per-callstrings.ToLower. The declared type is fixed for the lifetime of a prepared statement, so the C round-trip is paid once per column rather than once per column per row, removing exactly 1 alloc + 8 B per TEXT column per row from theNexthot path. The newBenchmarkTextToTimeScancases show ~7% faster on a 1000-row DATETIME SELECT under_texttotime=1. Purely internal:ColumnTypeDatabaseTypeNameandColumnTypeScanTypereturn identical values, no API or behavioral change. - See GitLab merge request #124, thanks Ian Chechin!
- Cache, per result column, the
parseTimeFormatsindex that first parsed a TEXT-stored DATE/DATETIME/TIMESTAMP value, and try that format first on later rows instead of re-walking the list from the top.(*conn).parseTimepreviously rantime.Parsedown the format list on every such row; for the canonical SQLite TEXT datetime format every row paid two failedtime.Parseattempts — each allocating a*time.ParseError— before the match. On a 1000-row DATETIME TEXT SELECT this cuts ~50% of allocs/op and ~57% of B/op and is ~37% faster. The fall-through chain is preserved exactly: the seven formats are mutually exclusive, so the cached hint can never select a different match than the in-order scan, and the parseddriver.Valueis identical to before. Purely internal: no API or behavioral change. - See GitLab merge request #125, thanks Ian Chechin!
-
2026-05-28 v1.51.0:
- Pool the
[]driver.Valueslice passed to scalar/aggregate UDF callbacks and to vtabFilter/Insert/Updatecallbacks, eliminating the dominant per-row allocation on UDF-heavy queries. Benchmarks on a 1000-row, 3-arg noop scalar UDF show ~40% fewer bytes/op and ~15% fewer allocs/op. - Document the matching "arguments are not valid past return" contract on
vtab.Cursor.Filterandvtab.Updater.Insert/Update, consistent with the existing rule forFunctionImpl.Scalar/AggregateFunction.Step/WindowInverse. - Resolves GitLab issue #226. See GitLab merge request #114, thanks Ian Chechin!
- Add
FileControl.FileControlDataVersion, a wrapper aroundSQLITE_FCNTL_DATA_VERSIONfor observing pager-cache data-version changes, including those made on the same connection. Useful as a primitive for application-level cache invalidation. - Exposed via the idiomatic
database/sqlescape hatch(*sql.Conn).Raw(), consistent with the existingFileControlPersistWAL. - See GitLab merge request #115, thanks Ian Chechin!
- Fix a regression where in-memory connections (
:memory:,file::memory:, shared-cache memory URIs) were discarded bydatabase/sqlafter a context-cancelled query, taking the entire in-memory store with them. The fix for #198 had added ansqlite3_is_interruptedcheck to the connection validator that mistakenly applied to in-memory connections too, re-introducing the bug originally fixed by !74. File-backed connections keep the existing behaviour and are still discarded after an interrupt. - Resolves GitLab issue #196. See GitLab merge request #116, thanks Ian Chechin!
- Add an opt-in
FunctionImpl.VolatileArgsflag that hands TEXT and BLOB arguments to scalar and aggregate UDF callbacks as zero-copy views (unsafe.String/unsafe.Slice) over SQLite's own value buffers, eliminating the per-argumentlibc.GoString/make([]byte)copy that the #226 slice-pooling left as the remaining per-row allocation. On the same 1000-row, 3-arg (INTEGER/TEXT/BLOB) noop scalar UDF this removes a further ~35% of allocs/op and ~11% of bytes/op on top of #226. - The views are valid only for the duration of the callback and must not be retained past return or across rows; a callback that needs to keep a value must copy it. With
VolatileArgsunset (the default) arguments keep the existing copied, caller-owned semantics, so the flag is fully backward compatible; it has no effect on integer, float, time, or NULL arguments. - See GitLab merge request #120, thanks Ian Chechin!
- Extend the opt-in
VolatileArgszero-copy TEXT/BLOB argument access from #120 to the virtual-tableCursor.Filter(xFilter) andUpdater.Insert/Update(xUpdate) callbacks. Avtab.Moduleopts in by implementing the new optionalvtab.VolatileArgsOpterinterface (VolatileArgs() bool); the flag is read once at module registration and shared by every table created from it. On a vtab call carrying one TEXT and one BLOB argument this removes 2 allocs/op (onelibc.GoString, onemake([]byte)) on each of the Filter and Update paths. - The same safety contract as #120 applies: the views are valid only for the duration of the callback and must not be retained past return or across rows; a callback that needs to keep a value must copy it. Modules that do not implement
VolatileArgsOpter(the default for all existing modules) are byte-for-byte unchanged, and the flag has no effect on integer, float, time, or NULL arguments. - See GitLab merge request #121, thanks Ian Chechin!
- Pool the
-
2026-05-10 v1.50.1:
- Upgrade to SQLite 3.53.1.
-
2026-04-24 v1.50.0:
- Upgrade to sqlite-vec v0.1.9.
- Introduce
ColumnInfo, enabling dynamic query builders and ORMs to retrieve underlying SQLite C-API metadata (OriginName,TableName,DatabaseName, andDeclType). - This feature is exposed via the idiomatic
database/sqlescape hatch(*sql.Conn).Raw(), avoiding custom statement handles and keeping the standard library workflow intact. - See GitLab merge request #113, thanks Josh Bleecher Snyder!
-
2026-04-17 v1.49.1: Documentation only: update the per-platform SQLite version table in
doc.goto 3.53.0, the version shipped since v1.49.0. No code changes. -
2026-04-17 v1.49.0: Upgrade to SQLite 3.53.0.
- Added
-DSQLITE_ENABLE_DBPAGE_VTABto the transpilation. See "The SQLITE_DBPAGE Virtual Table" for details.
- Added
-
2026-04-06 v1.48.2:
- Fix ABI mapping mismatch in the pre-update hook trampoline that caused silent truncation of large 64-bit RowIDs.
- Ensure the Go trampoline signature correctly aligns with the public
sqlite3_preupdate_hookC API, preventing data corruption for high-entropy keys (e.g., Snowflake IDs). - See GitLab merge request #98, thanks Josh Bleecher Snyder!
- Fix the memory allocator used in
(*conn).Deserialize. - Replace
tls.Allocwithsqlite3_malloc64to prevent internal allocator corruption. This ensures the buffer is safely owned by SQLite, which may resize or free it due to theSQLITE_DESERIALIZE_RESIZEABLEandSQLITE_DESERIALIZE_FREEONCLOSEflags. - Prevent a memory leak by properly freeing the allocated buffer if fetching the main database name fails before handing ownership to SQLite.
- See GitLab merge request #100, thanks Josh Bleecher Snyder!
- Fix
(*conn).Deserializeto explicitly rejectnilor empty byte slices. - Prevent silent database disconnection and connection pool corruption caused by SQLite's default behavior when
sqlite3_deserializereceives a 0-length buffer. - See GitLab merge request #101, thanks Josh Bleecher Snyder!
- Fix
commitHookTrampolineandrollbackHookTrampolinesignatures by removing the unusedpCsrparameter. - Aligns internal hook callbacks accurately with the underlying SQLite C API, cleaning up the code to prevent potential future confusion or bugs.
- See GitLab merge request #102, thanks Josh Bleecher Snyder!
- Fix
checkptrinstrumentation failures duringgo test -racewhen registering and using virtual tables (vtab). - Allocate
sqlite3_moduleinstances using the C allocator (libc.Xcalloc) instead of the Go heap. This ensures transpiled C code can safely perform pointer operations on the struct without tripping Go's pointer checks. - See GitLab merge request #103, thanks Josh Bleecher Snyder!
- Fix data race on
mutex.idin themutexTrynon-recursive path. - Ensure consistent atomic writes (
atomic.StoreInt32) to prevent data races with atomic loads inmutexHeldandmutexNotheldduring concurrent execution. - See GitLab merge request #104, thanks Josh Bleecher Snyder!
- Fix resource leak in
(*Backup).Commitwhere the destination connection was not closed on error. - Ensure
dstConnis properly closed whensqlite3_backup_finishfails, preventing file descriptor, TLS, and memory leaks. - See GitLab merge request #105, thanks Josh Bleecher Snyder!
- Fix
Execto fully drain rows when encounteringSQLITE_ROW, preventing silent data loss in DML statements. - Previously,
Execaborted after the first row, meaningINSERT,UPDATE, orDELETEstatements with aRETURNINGclause would fail to process subsequent rows. The execution path now correctly loops untilSQLITE_DONEand properly respects context cancellations during the drain loop, fully aligning with native Csqlite3_execsemantics. - See GitLab merge request #106, thanks Josh Bleecher Snyder!
- Fix "Shadowed err value (stmt.go)".
- See GitLab issue #249, thanks Emrecan BATI!
- Fix silent omission of virtual table savepoint callbacks by correctly setting the sqlite3_module version.
- See GitLab merge request #107, thanks Josh Bleecher Snyder!
- Fix
vfsReadto properly handle partial and fragmented reads fromio.Reader. - Replace
f.Readwithio.ReadFullto ensure the buffer is fully populated, preventing prematureSQLITE_IOERR_SHORT_READerrors on valid mid-stream partial reads. Unread tail bytes at EOF are now efficiently zero-filled using the built-inclearfunction. - See GitLab merge request #108, thanks Josh Bleecher Snyder!
- Refactor internal error formatting to safely handle uninitialized or closed database pointers.
- Prevent a misleading "out of memory" error message when an operation fails and the underlying SQLite database handle is
NULL(db == 0). - See GitLab merge request #109, thanks Josh Bleecher Snyder!
- Fix error handling in database backup and restore initialization (
sqlite3_backup_init). - Ensure error codes and messages are accurately read from the destination database handle rather than hardcoding the source or remote handle. This prevents swallowed errors or mismatched "not an error" messages when a backup or restore operation fails to start.
- See GitLab merge request #111, thanks Josh Bleecher Snyder!
- Fix database handle and C-heap memory leaks when
sqlite3_open_v2fails. - Ensure
sqlite3_close_v2is called on the partially allocated database handle during a failed open, and explicitly closelibc.TLSinnewConnto prevent resource leakage. - Prevent misleading "out of memory" error messages on failed connections by correctly extracting the exact error string from the allocated handle before it is closed.
- See GitLab merge request #112, thanks Josh Bleecher Snyder!
-
2026-04-03 v1.48.1:
- Fix memory leaks and double-free vulnerabilities in the multi-statement query execution path.
- Ensure bind-parameter allocations are reliably freed via strict ownership transfer if an error occurs mid-loop or if multiple statements bind parameters.
- Fix a resource leak where a subsequent statement's error could orphan a previously generated
rowsobject without closing it, leaking the prepared statement handle. - See GitLab merge request #96, thanks Josh Bleecher Snyder!
-
2026-03-27 v1.48.0:
- Add
_timezoneDSN query parameter to apply IANA timezones (e.g., "America/New_York") to both reads and writes. - Writes will convert
time.Timevalues to the target timezone before formatting as a string. - Reads will interpret timezone-less strings as being in the target timezone.
- Does not impact
_inttotimeinteger values, which will always safely evaluate as UTC. - Add support for
_time_format=datetimeURI parameter to formattime.Timevalues identically to SQLite's nativedatetime()function andCURRENT_TIMESTAMP(YYYY-MM-DD HH:MM:SS). - See GitLab merge request #94 and GitLab merge request #95, thanks Josh Bleecher Snyder!
- Add
-
2026-03-17 v1.47.0: Add CGO-free version of the vector extensions from https://github.com/asg017/sqlite-vec. See
vec_test.gofor example usage. From the GitHub project page:- Important: sqlite-vec is a pre-v1, so expect breaking changes!
- Store and query float, int8, and binary vectors in vec0 virtual tables
- Written in pure C, no dependencies, runs anywhere SQLite runs (Linux/MacOS/Windows, in the browser with WASM, Raspberry Pis, etc.)
- Store non-vector data in metadata, auxiliary, or partition key columns
- See GitLab merge request #93, thanks Zhenghao Zhang!
-
2026-03-16 v1.46.2: Upgrade to SQLite 3.51.3.
-
2026-02-17 v1.46.1:
- Ensure connection state is reset if Tx.Commit fails. Previously, errors like SQLITE_BUSY during COMMIT could leave the underlying connection inside a transaction, causing errors when the connection was reused by the database/sql pool. The driver now detects this state and forces a rollback internally.
- Fixes GitHub issue #2, thanks Edoardo Spadolini!
-
2026-02-17 v1.46.0:
- Enable ColumnTypeScanType to report time.Time instead of string for TEXT columns declared as DATE, DATETIME, TIME, or TIMESTAMP via a new
_texttotimeURI parameter. - See GitHub pull request #1, thanks devhaozi!
- Enable ColumnTypeScanType to report time.Time instead of string for TEXT columns declared as DATE, DATETIME, TIME, or TIMESTAMP via a new
-
2026-02-09 v1.45.0:
- Introduce vtab subpackage (modernc.org/sqlite/vtab) exposing Module, Table, Cursor, and IndexInfo API for Go virtual tables.
- Wire vtab registration into the driver: vtab.RegisterModule installs modules globally and each new connection calls sqlite3_create_module_v2.
- Implement vtab trampolines for xCreate/xConnect/xBestIndex/xDisconnect/xDestroy/xOpen/xClose/xFilter/xNext/xEof/xColumn/xRowid.
- Map SQLite’s sqlite3_index_info into vtab.IndexInfo, including constraints, ORDER BY terms, and constraint usage (ArgIndex → xFilter argv[]).
- Add an in‑repo dummy vtab module and test (module_test.go) that validates registration, basic scanning, and constraint visibility.
- See GitLab merge request #90, thanks Adrian Witas!
-
2026-01-19 v1.44.3: Resolves GitLab issue #243.
-
2026-01-18 v1.44.2: Upgrade to SQLite 3.51.2.
-
2026-01-15 v1.44.1: Bump the pinned
modernc.org/libcto v1.67.6. Its memory-safestrlenfixes the AddressSanitizer global-buffer-overflow in the transpiled window-function name arrays reported in GitLab merge request #88, which was closed in favour of that upstream fix, thanks Matt Topol! -
2026-01-13 v1.44.0: Upgrade to SQLite 3.51.1.
-
2026-01-08 v1.43.0:
- Add
IsReadOnly(schema string) (bool, error)on the driver connection, a wrapper aroundsqlite3_db_readonly, reachable through(*sql.Conn).Raw(). Resolves GitLab issue #242. - Honour
_time_integer_format=unix_microandunix_nanowhen reading integer time values back with_inttotime=true; previously only the seconds/milliseconds heuristic applied. Resolves GitLab issue #240. - Make the mutex implementation in
lib/mutex.gomore robust. - Re-vendor the transpiled library from
modernc.org/libsqlite3v1.11.0; the SQLite version stays 3.50.4. - Add openbsd/amd64 and openbsd/arm64 to the targets exercised by the builders (see GitLab issue #237).
- Add
-
2025-12-28 v1.42.2: Fix a TOCTOU race in query interruption: a cancelled context could interrupt an unrelated, later query on the same connection. Resolves GitLab issue #241. See GitLab merge request #86, thanks Josh Bleecher Snyder!
-
2025-12-27 v1.42.1: Revert to the v1.41.0 state (SQLite 3.50.4) and retract v1.42.0 in
go.mod. -
2025-12-27 v1.42.0: Upgrade to SQLite 3.51.1. Retracted the same day as accidentally broken, see the
retractdirective ingo.mod; v1.42.1 reverts it and v1.44.0 carries the working 3.51.1 upgrade. -
2025-12-08 v1.41.0:
- Add the
modernc.org/sqlite/vtabsubpackage, a Go virtual-table API (Module,Table,Cursor,IndexInfo,vtab.RegisterModule) bridged to the engine and validated by an in-tree dummy module. See GitLab merge request #84, thanks Adrian Witas! - Optimize prepared statements: reuse the prepared SQLite statement handle across executions instead of preparing it again. Updates GitLab issue #236.
- Fix the build on 32-bit targets.
- Add the
-
2025-11-12 v1.40.1: Close the
Rowsof a query whose context was cancelled after the statement had already produced them; suchRowswere previously leaked, which kept a read transaction open, starved WAL checkpoints and let the WAL grow without bound. See GitLab merge request #81, thanks Silvio Moioli! -
2025-10-17 v1.40.0: Add pre-update, commit and rollback hooks:
RegisterPreUpdateHook,RegisterCommitHookandRegisterRollbackHookon the driver connection, plus theSQLitePreUpdateDatatype (Depth,Count,Old,New), reachable through(*sql.Conn).Raw(). Updates GitLab issue #125. See GitLab merge request #80, thanks Walter Wanderley! -
2025-10-10 v1.39.1: Upgrade to SQLite 3.50.4.
-
2025-08-11 v1.39.0:
- Add the
_time_integer_formatDSN parameter (unix,unix_milli,unix_micro,unix_nano):time.Timevalues are bound as integers in that unit instead of as text, so timestamps fitINTEGERcolumns,STRICTtables included. Resolves GitLab issue #216. See GitLab merge request #77, thanks Guénaël Muller! - Add the
_inttotimeDSN parameter: when enabled,INTEGERvalues read from columns declaredDATE,DATETIMEorTIMESTAMPare converted totime.Time(seconds, or milliseconds for magnitudes above 1e12), matching mattn/go-sqlite3, so scanning them into a*time.Timeno longer fails. Resolves GitLab issue #214. See GitLab merge request #76, thanks Harald Albrecht! - Add a VFS unit test. See GitLab merge request #78, thanks Harald Albrecht!
- Add the
-
2025-07-28 v1.38.2: Upgrade to SQLite 3.50.3, this time including the regenerated library that v1.38.1 lacked.
-
2025-07-25 v1.38.1: Update dependencies. Intended as the upgrade to SQLite 3.50.3, but the regenerated library was not included, so the shipped SQLite version is still 3.50.1. Superseded by v1.38.2.
-
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).