Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions internal/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"log/slog"
"net/url"
"os"
"path/filepath"
"sort"
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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",
Expand Down
16 changes: 11 additions & 5 deletions internal/db/openmemory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
Expand Down
Loading