Documentation
¶
Overview ¶
Package db provides a SQLite database layer with pluggable drivers.
Two SQLite drivers ship with libfossil — modernc (pure Go, default) and ncruces (WASM-capable). Select one at build time by importing its driver package:
import _ "github.com/danmestas/go-libfossil/db/driver/modernc"
Open and OpenWith handle DSN construction, WAL/pragma setup, and WASM-specific workarounds. Use DB.WithTx for transaction scoping with automatic rollback on error.
The Querier interface (Exec, QueryRow, Query) is satisfied by both DB and Tx, allowing callers to write transaction-agnostic code.
Index ¶
- func CreateRepoSchema(d *DB) error
- func DefaultPragmas() map[string]string
- func OpenSQL(path string, cfg OpenConfig, params map[string]string) (*sql.DB, error)
- func Register(cfg DriverConfig)
- func SQLDriverAndDSN(path string, cfg OpenConfig, params map[string]string) (string, string)
- func ScanInt(v any) (int, bool)
- func ScanJulianDay(v any) (float64, bool)
- func ScanTime(v any) (time.Time, bool)
- func SeedConfig(d *DB, rng simio.Rand, projectCode string) error
- func SeedNobody(d *DB, caps string) error
- func SeedUser(d *DB, login string) error
- type CheckpointMode
- type DB
- func (d *DB) ApplicationID() (int32, error)
- func (d *DB) Checkpoint(mode CheckpointMode) error
- func (d *DB) Close() error
- func (d *DB) Driver() string
- func (d *DB) Exec(query string, args ...any) (sql.Result, error)
- func (d *DB) Path() string
- func (d *DB) Query(query string, args ...any) (*sql.Rows, error)
- func (d *DB) QueryRow(query string, args ...any) *sql.Row
- func (d *DB) SetApplicationID(id int32) error
- func (d *DB) SqlDB() *sql.DB
- func (d *DB) WithTx(fn func(tx *Tx) error) error
- type DriverConfig
- type OpenConfig
- type Querier
- type Tx
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateRepoSchema ¶
func DefaultPragmas ¶
DefaultPragmas returns the default pragma settings.
func OpenSQL ¶
OpenSQL opens a raw *sql.DB using the registered driver and the same DSN construction as OpenWith. params are appended as URI query parameters after driver pragmas, so callers can request options such as mode=ro without constructing driver-specific DSNs.
func Register ¶
func Register(cfg DriverConfig)
Register registers a SQLite driver for use by Open/OpenWith. Must be called exactly once (typically from a driver package's init()). Panics if called more than once.
func SQLDriverAndDSN ¶
SQLDriverAndDSN returns the driver name and DSN OpenWith would use, with optional URI query params appended after driver-specific options.
func ScanInt ¶
ScanInt converts a scanned value to int. SQLite drivers differ on BOOLEAN columns: modernc returns int64, ncruces returns bool. Scan the column into an `any` variable, then pass it here.
func ScanJulianDay ¶
ScanJulianDay converts a scanned mtime value to a float64 Julian Day Number. SQLite drivers return mtime differently: modernc returns float64, ncruces returns time.Time for DATETIME/TIMESTAMP/DATE columns. Scan the column into an `any` variable, then pass it here.
The float64 branch returns the scanned value verbatim, and that exactness is load-bearing rather than incidental. A float64 read off the row IS the stored value, so any "canonicalizing" transform can only move it away from what the row holds. Two consumers compare a scanned mtime against other stored mtimes and would silently return a wrong answer (never an error) if the value were perturbed even by one ulp:
- Timeline's pagination cursor, whose predicate `e.mtime < ? OR (e.mtime = ? AND b.rid < ?)` needs the cursor to compare exactly equal to the row it came from. Raise it by an ulp and that row repeats as the next page's first row; lower it and rows are skipped.
- tag propagation's `tagxref.mtime < ?`, where SQLite compares the bound value against raw stored floats.
Neither is hypothetical for values this library did not write: SQLite's own julianday() computes iJD/86400000.0, a different expression from TimeToJulian's julianEpoch + ms/86400000.0, and the two land one ulp apart on a real fraction of instants. Snapping such a value to the millisecond grid changes it.
The time.Time branch is the one case where a transform is required rather than harmful — see timeToJulian.
func ScanTime ¶
ScanTime converts a scanned mtime value to time.Time. Same driver-compatibility rationale as ScanJulianDay.
func SeedConfig ¶
SeedConfig seeds the config table with project-code, server-code, and schema markers. If projectCode is empty, a fresh 40-char lowercase-hex project-code is generated from rng. If non-empty, it must match ^[0-9a-f]{40}$; otherwise an error is returned and no rows are written. Server-code is always generated.
func SeedNobody ¶
SeedNobody inserts a "nobody" user with the given capabilities. This controls anonymous access policy for the repo.
Types ¶
type CheckpointMode ¶
type CheckpointMode int
CheckpointMode mirrors SQLite's PRAGMA wal_checkpoint(<mode>) argument.
const ( // CheckpointPassive checkpoints frames not held by readers; never blocks. // Appropriate for periodic background checkpoints. CheckpointPassive CheckpointMode = iota // CheckpointFull blocks new writers until all frames are checkpointed. CheckpointFull // CheckpointRestart is FULL plus restarts the WAL file. CheckpointRestart // CheckpointTruncate is RESTART plus truncates the WAL file to zero bytes. // Produces the most compact on-disk file and is what Close uses. CheckpointTruncate )
func (CheckpointMode) String ¶
func (m CheckpointMode) String() string
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB wraps a SQLite database connection.
func OpenWith ¶
func OpenWith(path string, cfg OpenConfig) (*DB, error)
OpenWith opens a SQLite database with explicit configuration.
func (*DB) ApplicationID ¶
func (*DB) Checkpoint ¶
func (d *DB) Checkpoint(mode CheckpointMode) error
Checkpoint runs PRAGMA wal_checkpoint(<mode>) against the database. Safe to call on a live database. PASSIVE never blocks; TRUNCATE produces the most compact on-disk layout. On a non-WAL database the underlying PRAGMA is a no-op and returns nil.
func (*DB) Close ¶
Close runs PRAGMA wal_checkpoint(TRUNCATE) before closing the underlying connection so the on-disk file is readable by external SQLite/fossil tooling. The WASM/WASI build path does not use WAL, so the checkpoint is skipped there. Checkpoint errors are joined with the close error so the connection is always closed regardless of checkpoint outcome.
func (*DB) SetApplicationID ¶
type DriverConfig ¶
type DriverConfig struct {
Name string
BuildDSN func(path string, pragmas map[string]string) string
}
DriverConfig defines a SQLite driver's name and DSN builder.
func RegisteredDriver ¶
func RegisteredDriver() *DriverConfig
RegisteredDriver returns a copy of the currently registered driver config, or nil if none.
type OpenConfig ¶
type OpenConfig struct {
Driver string // override driver name (empty = use registered driver)
Pragmas map[string]string // additional/override pragmas (merged with defaults)
}
OpenConfig allows callers to customize driver selection and pragmas.
type Querier ¶
type Querier interface {
Exec(query string, args ...any) (sql.Result, error)
QueryRow(query string, args ...any) *sql.Row
Query(query string, args ...any) (*sql.Rows, error)
}
Querier is the common interface satisfied by both *DB and *Tx. Functions that need to work inside transactions accept Querier instead of *DB.