Skip to content

Align SQLite read settings and literal filename handling - #59

Merged
jilio merged 1 commit into
mainfrom
sqlite-read-settings
Sep 12, 2026
Merged

jilio merged 1 commit into
mainfrom
sqlite-read-settings

Conversation

@jilio

@jilio jilio commented Sep 12, 2026 •

Copy link
Copy Markdown
Owner

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.

@claude

claude Bot commented Sep 12, 2026

Copy link
Copy Markdown

Review

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)

  1. 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.
  2. 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).
  3. 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.

@jilio
jilio merged commit 8f8bf8d into main Sep 12, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant