You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Align SQLite read settings and literal filename handling - #59
OpenReadOnly now shares New's per-connection busy timeout, page cache, temporary-storage and mmap settings while retaining mode=ro and query_only, without writer transaction or durability settings. A shared URI builder lets New open literal %, ? and # filenames safely, preserves the special :memory: behavior, and rejects NUL bytes in both constructors instead of opening a truncated filename. This addresses the review on PR #58.
Align nested-module and example dependencies with the unified v0.20.0 release. Add the missing release history, planned 0.20.1 changelog entry, and harness-neutral release rules in AGENTS.md. Included in the unified v0.20.1 release. Published v0.20.0 tags remain unchanged; final nested-module and example dependency alignment is covered by #60 and #61.
Validation:
Regression tests failed on the prior behavior for missing read pragmas, percent-decoded filenames, and NUL filename truncation. New pooled tests cover settings on three distinct connections, rejection of data/schema/temp writes, unchanged database bytes and journal mode, and read transactions while a writer transaction is open.
macOS: standalone formatting, build, vet, normal tests and race tests for all six modules on their declared minimum Go versions: 1.24.2 for core/SQLite, 1.25.1 for Durable Streams, and 1.25.12 for OpenTelemetry and both examples. All aligned dependencies resolve through normal proxy/checksum verification.
Linux arm64, Go 1.24.2: build, vet, normal tests and race tests for core/state and SQLite against the published v0.20.0 dependency graph.
Core/state coverage is 100.0%; SQLite coverage is 97.6% on macOS and 97.9% on Linux.
I read through dsn.go, the updated store.go/readonly.go, and the new test files. Overall this is a well-scoped, carefully-tested fix — the design and reasoning are sound. Note: I wasn't able to execute go build/go test/go vet in this sandboxed review environment, so this is a static read-through rather than a run of the CLAUDE.md-required checks; the PR description already reports those passing on macOS/Linux across all modules, which I have no reason to doubt.
Strengths
Consolidating buildDSN so New and OpenReadOnly share the same read-side pragma construction (busy timeout, cache size, temp store, mmap) is a good fix for the underlying bug (readers previously missing busy_timeout, which could cause spurious SQLITE_BUSY under load). Cleanly separates the writer-only bits (synchronous, _txlock=immediate) from the shared ones.
Using url.URL{Scheme: "file", OmitHost: true, ...} plus url.Values.Encode() to build the DSN, instead of hand-rolled string concatenation, is the right way to guarantee %, ?, and # in a literal filename can't be misparsed as URI syntax or option injection — and rejecting NUL up front avoids SQLite silently truncating the path.
OmitHost is the right call here (avoids emitting // before a Windows drive letter, which could otherwise be misread as an authority component) — nice attention to detail, worth a one-line comment expansion if a future reader doesn't know that history, but the existing comment already gives the "why."
Test coverage is thorough and reads like real regression tests, not just line-coverage padding: pooled-connection pragma checks across 3 separate connections, the write-block-while-read-tx-open test, the literal-filename round trip across a good spread of nasty names (%, ?, #, combined, space+unicode), and the "NUL doesn't open a truncated prefix" test are all exactly the right shape for this kind of bug class.
Removing the old blanket ?/# rejection in New and replacing it with real escaping is a genuine behavior improvement, not just a refactor — and the corresponding store_test.go deletions correctly track that old, now-invalid behavior.
Things worth a second look (none blocking, no confirmed bugs found)
Windows is untested by this PR's own validation (only macOS + Linux arm64 are mentioned). The filepath.Abs + filepath.ToSlash + OmitHost combination should produce SQLite's documented file:C:/path/to/db form for absolute Windows paths, which I believe is correct, but since nobody has actually run it on Windows, it'd be worth a CI leg (even just go vet/go test -run TestNewAndOpenReadOnlyUseLiteralFilePaths on windows-latest) before relying on it in production on that platform.
sqlite: coverage is 97.6%/97.9%, not 100%, per the PR description — presumably the uncovered lines include hard/impossible-to-trigger paths like filepath.Abs failing (which basically requires os.Getwd() to fail). That's a reasonable place to stop, but flagging it since CLAUDE.md calls for 100% coverage of "core functionality" — worth confirming with the maintainer whether the SQLite store is held to that bar or not (this seems to be pre-existing project practice, not something newly introduced here).
Minor: the comment on _txlock=immediate ("Only migrations use them here") is carried over from the old code and is slightly stale — since it's applied at the DSN level, it actually affects any explicit transaction a caller starts via store.db, not just migrations. Not a functional issue, just a comment accuracy nit, and it predates this PR.
Security
No concerns — this actually closes a real gap (the old strings.Contains(path, "?")-style rejection was a weaker, incomplete substitute for proper URI escaping; the new approach is the correct fix). NUL-byte rejection prevents the truncated-path-open issue described in the PR.
Performance
No concerns. Pragma settings are per-connection/in-DSN as before; no additional per-call overhead introduced.
Nice work — the regression tests in particular make this easy to trust.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OpenReadOnlynow sharesNew's per-connection busy timeout, page cache, temporary-storage and mmap settings while retainingmode=roandquery_only, without writer transaction or durability settings. A shared URI builder letsNewopen literal%,?and#filenames safely, preserves the special:memory:behavior, and rejects NUL bytes in both constructors instead of opening a truncated filename. This addresses the review on PR #58.Align nested-module and example dependencies with the unified
v0.20.0release. Add the missing release history, planned0.20.1changelog entry, and harness-neutral release rules inAGENTS.md. Included in the unified v0.20.1 release. Published v0.20.0 tags remain unchanged; final nested-module and example dependency alignment is covered by #60 and #61.Validation:
1.24.2for core/SQLite,1.25.1for Durable Streams, and1.25.12for OpenTelemetry and both examples. All aligned dependencies resolve through normal proxy/checksum verification.1.24.2: build, vet, normal tests and race tests for core/state and SQLite against the publishedv0.20.0dependency graph.100.0%; SQLite coverage is97.6%on macOS and97.9%on Linux.