Loading
Commits on Source 12
-
cznic authored
Documentation, one new validation rule, and test coverage on top of wsman's GitHub PR #6. No change to what _defensive itself does. conn.go: the comment above the db_config calls had been generalized to "connection-level sqlite3_db_config options are applied before applyQueryParams because the SQLite contract requires sqlite3_db_config(SQLITE_DBCONFIG_DQS_*) to be set before any statement is prepared". That contract is DQS-specific and does not extend to DEFENSIVE, which may be toggled at any point in a connection's life; defensive goes first because the PRAGMAs that follow must run under the restriction, which is a choice, not an API requirement. Restore the DQS comment verbatim on the DQS call and give _defensive its own rationale. sqlite.go: reject _defensive=1 together with _journal_mode=OFF (or _journal=OFF). SQLite turns PRAGMA journal_mode=OFF into a no-op that still reports success under defensive mode, so the combination previously opened a connection in which neither parameter had been honoured and nothing was reported. The check sits in the validation phase from v1.55.0, before any statement executes, so a rejected DSN still cannot leave the database half-configured. _pragma stays the documented exception: _pragma =journal_mode(OFF) alongside _defensive=1 runs and is silently ignored by SQLite. Only DSNs using _defensive can be affected and that parameter is new, so no DSN that opened before changes behavior. driver.go: expand the _defensive documentation to the depth of its _dqs and _error_rc neighbours -- what the mode observably does (writable_schema=ON, journal_mode=OFF and schema_version=N become silent no-ops; shadow-table and sqlite_dbpage writes error; reads, ordinary virtual table use and VACUUM are unaffected), the new _journal_mode conflict, and the two limits the name invites callers to overlook: it is a hardening measure rather than a sandbox for hostile files (this build has neither SQLITE_TRUSTED_SCHEMA=0 nor SQLITE_DQS=0 and there is no authorizer), and it is a property of the connection, not of the database file. defensive_test.go: rename TestUnmodifiedBehaviorIsNotAnADEDefensiveControl, whose "ADE" is an acronym from the contributor's downstream and means nothing here, to TestDefensiveAbsentOrFalseIsBaseline, and TestUnprotectedPoolIsA NegativeControl to TestDefensiveOffPoolIsANegativeControl so every test in the file groups under the feature. Add TestDefensiveRejectsJournalModeOff for the new rule, TestDefensiveDSNForms for the file: URI shape -- which keeps its query string all the way into sqlite3_open_v2, so SQLite parses _defensive too and must ignore it -- plus :memory: and shared-cache memory URIs, TestDefensiveLeavesOrdinaryUseIntact for the other half of the contract (fts5 create/insert/MATCH, foreign keys, VACUUM, integrity_check and every other DSN parameter that could collide, with direct fts5 shadow-table and sqlite_dbpage writes refused), and TestDefensiveIsPerConnection to pin the documented scope. Also adopt the file's `package sqlite // import ...` form. CHANGELOG.md: document both the parameter and the new conflict rule.
-
cznic authored
TestConcurrentGoroutines re-invokes itself under -race and treats anything the recursive run prints other than two known "cannot run here" messages as a failure. With CGO_ENABLED=0 the go tool refuses with "-race requires cgo; enable cgo by setting CGO_ENABLED=1", which matched neither, so the whole suite failed on an environment where the check simply cannot run -- and a CGo-free driver is a natural thing to build and test with cgo disabled. Accept that message alongside the existing two and skip, as the test already does for a toolchain without race support and for an unsupported VMA range. Nothing changes when cgo is available: the recursive -race run still executes and still has to pass. Found while reviewing GitHub PR #6, whose author hit it in a CGO_ENABLED=0 lane; unrelated to that change.
-
cznic authored
vec/ has carried the transpiled sqlite-vec sources since v1.47.0, but the module shipped only its own BSD-3-Clause LICENSE and the public-domain SQLite notice. sqlite-vec is Copyright (c) 2024 Alex Garcia and dual-licensed Apache-2.0 OR MIT; modernc.org/libsqlite_vec's generator elects MIT, whose terms require the copyright and permission notice to accompany substantial portions of the software. 2.8 MB of transpiled vec/ is a substantial portion. Attribution was never absent -- vec's package documentation names the extension, pins v0.1.9 and links upstream -- but the license text was. LICENSE-SQLITE_VEC: the notice, byte-identical to LICENSE-MIT in the upstream v0.1.9 archive and to the file libsqlite_vec extracts it into. vendor_libs/main.go: the omission was mechanical -- the tool copied the per-target transpiles and nothing else, so a plain cp of the notice would have survived only until the next `make vendor`. Copy it alongside the sources it belongs to, and treat a missing source as fatal: shipping the code without the notice is worse than not vendoring at all. SQLITE-LICENSE -> LICENSE-SQLITE, contents unchanged. This matches the new file beside it and the LICENSE-<upstream> convention the rest of the modernc.org repositories follow, but it is not only cosmetic. `go mod vendor` picks the metadata files it copies into a downstream vendor/ tree by matching each name against a fixed prefix list (cmd/go/internal/modcmd/vendor.go, metaPrefixes) that includes LICENSE, so a name merely ending in LICENSE was never propagated. Both notices now reach vendored builds, which is where the MIT terms on vec/ keep applying. Direct links to the old path will break. vec/patches.go: a License section on the package documentation, so an importer of vec sees on pkg.go.dev that this package is under a different license from the rest of the module. Found by an SBOM audit of the published module. Co-Authored-By:Claude Opus 5 (1M context) <noreply@anthropic.com>
-
cznic authored
The vendoring reads one full per-target file at a time from ../libsqlite3 and ../libsqlite_vec, which assumes those checkouts ship expanded. They do today, but either may adopt the deduplicated layout that modernc.org/wa2c already ships (modernc.org/builder's NW autogen; see NW_GENERALIZATION_HANDOFF.md there) — and then those per-target files hold only each target's residue, so vendoring them would silently drop most of the package. Detect it instead of remembering it later. srcDir applies undup's own rule (base.go or base_g_*.go present means folded) and: - returns an expanded checkout as is: no copy, no subprocess, exactly the path this tool has always taken; - copies a deduplicated one to a temp directory and expands it THERE, never in place — expanding the sibling would leave that checkout dirty and tempt a "restore" that discards whatever else is uncommitted in it. go.mod and go.sum travel with the copy because undup resolves each unaliased import's package name by running "go list" inside the directory it expands. The undup pin is passed in from the Makefile, so the repo keeps one version of record wherever undup is invoked, and expansion that leaves shared files behind is a hard error naming the pin — that is what a version too old for the layout looks like. Also adds -libsqlite3 / -libsqlite_vec flags so this can be exercised against scratch copies without touching the real checkouts. Verified both ways: output byte-identical to the previous binary on today's expanded checkouts (38/38 files); and from deduplicated copies of both siblings, a complete vendoring whose lib/ and vec/ build for linux/{amd64,s390x}, darwin/arm64, windows/{amd64,386}, freebsd/386 and netbsd/amd64. Expect one-time textual churn whenever a sibling does flip: undup reconstructs declarations in its own order and recomputes imports, dropping ccgo's `var _ = math.Pi` and friends along with the imports they exist to keep. Same package, different bytes. Co-Authored-By:Claude Opus 5 (1M context) <noreply@anthropic.com>
-
cznic authored
TestDBPageVtab's comment about -DSQLITE_ENABLE_DBPAGE_VTAB carried a trailing space, which made all_test.go the one hand-written file in the tree that gofmt -l reports. Comment text only; nothing else changes. Noticed by Ian Chechin while preparing GitLab merge request #135, which does not touch this file. Co-Authored-By:
Claude Opus 5 (1M context) <noreply@anthropic.com>
-
cznic authored
The test registered its driver under the fixed name "sqlite_conn_hook_test". sql.Register panics on a name it has already seen and offers no way to undo a registration, so the second iteration of go test -count=2 took the whole test binary down with "sql: Register called twice for driver sqlite_conn_hook_test" -- not a failure of the code under test, and it hid whatever the remaining iterations would have found. Derive the name from an atomic counter instead, so each invocation registers its own driver, and close the sql.DB the test opens while here: it was leaked once per iteration. Nothing changes for a single run. Ian Chechin's driver_register_test.go in GitLab merge request #135 solves the same problem with a uniqueDriverName helper; the two can be folded together once that lands. Co-Authored-By:
Claude Opus 5 (1M context) <noreply@anthropic.com>
-
Ian Chechin authored
Driver holds four categories of registration state but only connection hooks could be put on a constructed one. Functions and collations were reachable through the package-level API alone, and modules through the package-level driver only, so a constructed Driver was half-built: its modules field was written and read through the package-level instance, making it process-global state wearing a per-instance field. This is the additive half of #254, with one narrow, loud exception spelled out below: - registerFunction and registerCollation become methods on *Driver. The package-level RegisterFunction, RegisterScalarFunction, RegisterDeterministicScalarFunction and RegisterCollationUtf8 keep targeting the package-level driver, spelled explicitly now rather than by relying on the receiver named d shadowing the package variable of the same name. newDriver is renamed defaultDriver, since it read like a constructor but returns the singleton. - Driver gains RegisterFunction, RegisterScalarFunction, RegisterDeterministicScalarFunction, RegisterCollationUtf8 and RegisterModule, plus Must* variants of the first four, each registering on that Driver alone. The zero Driver stays usable: the maps are created on demand, since a constructed &Driver{} has nil maps where the package-level instance is built with make. A mutex on Driver makes concurrent registrations safe, so a *Driver can be handed out for several packages to fill from their init functions. - A connection now receives the union of the modules registered on the package-level driver and those registered on the Driver that opened it. The package-level set is applied unconditionally, which is what every connection has received since module support was added, so the isolating change #254 warns about is not made here. A name present in both resolves to the package-level implementation. - The ID handed to sqlite3_create_module_v2 as pAux is allocated per (Driver, name) pair, not per name. It is what every trampoline dispatches on, and a per-name ID would make two Drivers registering the same module name share one entry, with the last registration winning process-wide and retroactively, on connections already open. - vtab.RegisterModule honours its db argument: a non-nil db registers on the driver backing it when that driver implements the new vtab.ModuleRegisterer, and a nil db keeps targeting the driver this package registers as "sqlite". For a db opened on "sqlite" the two are the same driver, so the outcome is unchanged. The exception: vtab.RegisterModule(db, ...) where db was opened on a caller-constructed Driver used to discard the db argument and land on the "sqlite" driver, reaching every connection in the process. It now lands on the constructed driver alone, so a sql.Open("sqlite") connection that used to resolve such a module gets "no such module" instead. That same call is also the one route by which existing code can hold a module name on both a constructed Driver and the package-level one, so the collision rule above is a second, narrower part of the exception rather than a continuation. Before, the first of the two registrations won and the second was refused as already registered; now the package-level implementation wins on the constructed Driver's connections whichever order they ran in. No order-independent rule reproduces the old behavior, and reaching the case at all means the program ignored the error the older version returned. Two smaller deviations round it out: Driver.RegisterModule reports no error for such a collision, and vtab.RegisterModule validates its name and module arguments before the not-implemented check, so a call with an empty name that returned ErrNotImplemented outside this driver now returns "vtab: module name must be non-empty". Tests cover the new registrations, that they reject duplicates, that two constructed Drivers stay isolated from each other and from the package-level driver -- including when both register the same module name, exercised on a connection pinned before the second driver opens one -- that concurrent registrations survive the race detector, that globally registered modules still reach a constructed Driver, and that the db argument selects the driver. The behavior-preserving properties, the same-name case and the concurrency claim were each verified by breaking them deliberately and confirming the test fails. Updates #254
-
Ian Chechin authored
-
cznic authored
All three shipped as experimental in v1.53.0 and were deliberately left out of the supported platforms table until they had accumulated some real-world exposure. That period has elapsed: they have been in the builder matrix and in build_all_targets since, they pass on this release's commit alongside the seventeen platforms already listed, and no open issue reports a defect in any of them. The table therefore listed seventeen entries while the module shipped, cross-built and tested twenty; it now lists all twenty. Also set the v1.57.0 CHANGELOG date to the release date, and drop a stale claim in lib/hooks_linux_arm64.go that this module is "stuck on libc@v1.55.3" -- go.mod has pinned v1.74.4 since v1.56.0. The comment now says what the run-time patch is actually for.