From 02bcd41de016cf187b9e2aa4ad55943256eac132 Mon Sep 17 00:00:00 2001 From: Francis Rath Date: Tue, 6 Oct 2026 20:47:52 +0200 Subject: [PATCH] test(db): reapply DSN pragmas after OpenMemory deserializes its template synchronous and cache_size are per-schema, so Deserialize reset them to SQLite's defaults (2 and -2000) on every OpenMemory copy, while the DSN asks for 1 and -16000. OpenMemory now runs the DSN's pragmas again after loading the template, and the test checks every DSN pragma on the copy instead of only foreign_keys, so a pragma added to the DSN later is covered too. Refs #2982 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Francis Rath --- internal/db/db.go | 16 ++++++++++++++++ internal/db/openmemory_test.go | 16 +++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/internal/db/db.go b/internal/db/db.go index 157523e1f..e6a6cd1a4 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "log/slog" + "net/url" "os" "path/filepath" "sort" @@ -88,6 +89,14 @@ func OpenMemory() (*sql.DB, error) { db.Close() return nil, fmt.Errorf("load memory template: %w", err) } + // Some DSN pragmas (synchronous, cache_size) belong to the schema, not the + // connection, so Deserialize resets them to SQLite's defaults. Set them again. + for _, p := range connectionPragmas() { + if _, err := db.Exec("PRAGMA " + p); err != nil { + db.Close() + return nil, fmt.Errorf("reapply PRAGMA %s: %w", p, err) + } + } return db, nil } @@ -271,6 +280,13 @@ const connectionPragmaDSN = "?_pragma=foreign_keys(1)" + "&_pragma=temp_store(2)" + "&_pragma=cache_size(-16000)" +// connectionPragmas returns the pragmas connectionPragmaDSN sets, in the +// driver's name(value) form. +func connectionPragmas() []string { + q, _ := url.ParseQuery(strings.TrimPrefix(connectionPragmaDSN, "?")) + return q["_pragma"] +} + func setPragmas(db *sql.DB) error { pragmas := []string{ "PRAGMA journal_mode=WAL", diff --git a/internal/db/openmemory_test.go b/internal/db/openmemory_test.go index 4c3760c27..075105899 100644 --- a/internal/db/openmemory_test.go +++ b/internal/db/openmemory_test.go @@ -9,8 +9,8 @@ import ( ) // OpenMemory hands out copies of one migrated template; a write to one copy -// must not show up in the next, and per-connection pragmas must survive the -// copy. +// must not show up in the next, and every pragma the DSN sets must still hold +// on the copy. func TestOpenMemory_CopiesAreIndependent(t *testing.T) { a, err := OpenMemory() if err != nil { @@ -33,9 +33,15 @@ func TestOpenMemory_CopiesAreIndependent(t *testing.T) { if n != 0 { t.Fatalf("row written to one OpenMemory database leaked into another") } - var fk int - if err := b.QueryRow(`PRAGMA foreign_keys`).Scan(&fk); err != nil || fk != 1 { - t.Fatalf("foreign_keys = %d (err %v), want 1", fk, err) + for _, p := range connectionPragmas() { + name, want, _ := strings.Cut(strings.TrimSuffix(p, ")"), "(") + var got string + if err := b.QueryRow("PRAGMA " + name).Scan(&got); err != nil { + t.Fatal(err) + } + if got != want { + t.Errorf("PRAGMA %s = %s, want %s", name, got, want) + } } if got, want := len(versionSetForTest(t, b)), countMigrationFiles(t); got != want { t.Fatalf("schema_migrations has %d versions, want %d", got, want)