๐ค db
amadan.net/rastrillo/rastrillo/db
Opens your SQLite database the way a CARLOS app needs it, as one
*gorm.DB. It is a small package, and almost all its value is in what
Open gets right. Data is the guide.
Open
func Open(path string, log *slog.Logger) (*DB, error)
Opens one file as two pools and returns a handle wrapping both. A nil
logger defaults to slog.Default().
What it sets for you, and why each one is there:
- DSN pragma order.
busy_timeoutbeforejournal_mode=WAL; the other order crashes under concurrent open.foreign_keys(1)is on. - One writer connection. SQLite allows one writer, and queueing
inside the pool beats getting
SQLITE_BUSYat the call site. - Several reader connections โ
runtime.NumCPU(), floor of four. WAL supports many readers, and serialising them behind one connection turns an open*sql.Rowsplus any second query into a silent deadlock. dbresolverrouting, so your code never picks a pool.- An eager ping on both pools, so the file exists on disk from boot. That keeps hibernation replication happy.
TranslateError: true, soerrors.Is(err, gorm.ErrDuplicatedKey)works. Without the flag GORM never calls the dialector'sTranslate.- UTC times.
- A GORM logger writing into your
*slog.Logger, at warn level, with a 200ms slow-query threshold andErrRecordNotFoundignored โ a scoped by-id miss is the ordinary 404 path and happens on every not-yours URL.
DB
type DB struct {
G *gorm.DB
}
G is the handle your models and handlers use. The two *sql.DB pools
behind it are unexported.
DB.Writer
func (d *DB) Writer() *sql.DB
The write pool โ one connection. migrate.Apply takes it directly
rather than through the resolver, because it pins a single connection
for a whole run: PRAGMA foreign_keys is per-connection state, and
SQLite's twelve-step table rebuild has to toggle it outside the
transaction.
d.G.DB() gets you the same pool through GORM, and is what most code
uses when handing a *sql.DB to a database/sql package like
sessions.
DB.Close
func (d *DB) Close() error
Closes both pools. It returns the writer's error in preference to the reader's, so a single returned error names the pool whose failure matters.
Read this page as markdown โ exact, unstyled, and cheap for an agent to fetch.