Files
job-search/internal/store/common.go
T
bwilliams 465358609a Naming, layout and comments: descriptive full-word names, one item per line in wrapped calls and literals, and doc comments on exported names
Short and single-letter names in application code become full words (tests
keep theirs). Wrapped calls, signatures and composite literals put one item
per line, and one-line function bodies are expanded. Exported names and
groups of constants get doc comments, and comments refer to the renamed
identifiers.
2026-10-15 16:12:56 +01:00

46 lines
1.4 KiB
Go

package store
import (
"database/sql"
"fmt"
)
// Option configures Open.
type Option func(*options)
type options struct {
autoMigrate bool
}
// OpenDB opens the SQLite database at path with the store's connection
// settings (foreign keys, WAL, busy timeout, immediate transactions). The
// file is created on first use. Use it for anything that works on the store's
// database directly, such as running migrations.
func OpenDB(path string) (*sql.DB, error) {
return sql.Open("sqlite3", dsn(path))
}
// WithAutoMigrate makes Open apply pending migrations instead of returning
// ErrNeedsMigration. Intended for tests and throwaway databases; applications
// should migrate explicitly with the migrate command.
func WithAutoMigrate() Option {
return func(opts *options) {
opts.autoMigrate = true
}
}
// dsn builds the mattn/go-sqlite3 connection string.
//
// - _foreign_keys: SQLite ignores REFERENCES clauses unless this is on.
// - _journal_mode=WAL: readers don't block the writer or each other.
// - _busy_timeout: wait for a lock rather than failing immediately.
// - _txlock=immediate: transactions take the write lock at BEGIN, so a
// read-then-write transaction (as in SaveOpportunity) can't fail with
// SQLITE_BUSY halfway through.
func dsn(path string) string {
return fmt.Sprintf(
"file:%s?_foreign_keys=on&_journal_mode=WAL&_busy_timeout=5000&_txlock=immediate",
path,
)
}