Help us shape the future of Go! Take the 2026 Go Developer Survey

db

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package db opens the GoRun SQLite database and provides migration, transaction, ID and time helpers shared by every module.

Index

Constants

View Source
const (
	RuleDropTable  = "DROP TABLE"
	RuleDropColumn = "DROP COLUMN"
	RuleDropIndex  = "DROP INDEX"
	RuleRename     = "RENAME"
)

Destructive statement rules reported by DestructiveStatements.

Variables

View Source
var ErrDecrypt = errors.New("db: decrypt failed")

ErrDecrypt is returned when a ciphertext cannot be opened: wrong key, wrong AAD, tampering or truncation. Callers cannot tell these apart, by design.

Functions

func Checksum

func Checksum(body string) string

Checksum is the hex sha256 recorded for a migration file's content.

func Decrypt

func Decrypt(key []byte, ciphertext string, aad string) ([]byte, error)

Decrypt opens a value produced by Encrypt with the same key and aad. Any mismatch or corruption yields ErrDecrypt (wrapped); a bad key length yields a key error.

func DestructiveStatements

func DestructiveStatements(body string) []string

DestructiveStatements returns the destructive rules (DROP TABLE, DROP COLUMN, DROP INDEX, RENAME) the migration body matches, ignoring comments and string literals. Nil means the migration is additive. Matching is case-insensitive and whitespace-tolerant.

func Encrypt

func Encrypt(key, plaintext []byte, aad string) (string, error)

Encrypt seals plaintext with AES-256-GCM under a 32-byte key and a fresh random 12-byte nonce. aad binds the ciphertext to its context (e.g. "settings:mail.password") so it cannot be replayed into another field. The result is standard base64 (with padding) of nonce || ciphertext || tag.

func FileURI

func FileURI(path string) (string, error)

FileURI returns path as an SQLite "file:" URI with the path percent-encoded, so characters such as '?', '#', '%' and spaces are part of the file name instead of starting the query (which carries the pragmas) or a fragment. The path is made absolute first (file:///abs).

func FormatTime

func FormatTime(t time.Time) string

FormatTime formats t like Now.

func InTx

func InTx(ctx context.Context, d *sql.DB, fn func(tx *sql.Tx) error) (err error)

InTx runs fn inside a transaction (BEGIN IMMEDIATE, see Open). It commits when fn returns nil and rolls back on error or panic (re-panicking).

The transaction holds SQLite's write lock, so any write made through the pool (*sql.DB) from inside fn waits busy_timeout (5s) and fails. Inside fn write only through tx: use audit RecordTx, jobs EnqueueTx and settings SetTx; call Record, Enqueue, hooks Emit and Set only after InTx returns.

func Migrate

func Migrate(ctx context.Context, d *sql.DB, module string, files fs.FS) error

Migrate applies the module's pending migrations from files. Files must live at "migrations/NNNN_name.sql" inside files; they are applied in lexical order, each in its own transaction, and recorded in schema_migrations(module, name, applied_at, checksum). A nil FS or one without migrations is a no-op.

func NewID

func NewID() string

NewID returns a new ULID string (26 chars, lexically sortable by time). ulid.Make uses a process-wide, mutex-guarded monotonic entropy source, so IDs generated within the same millisecond still sort in creation order.

func Now

func Now() string

Now returns the current time as an RFC3339 UTC string at second precision. Every stored timestamp uses this format so lexical comparison in SQL (e.g. run_at <= ?) matches chronological order.

func Open

func Open(path string) (*sql.DB, error)

Open opens (creating if needed) the SQLite database at path with WAL, busy_timeout=5000, foreign_keys=ON, synchronous=NORMAL and immediate transactions. The parent directory is created when missing.

func ParseTime

func ParseTime(s string) (time.Time, error)

ParseTime parses a timestamp produced by Now or FormatTime.

func StripSQL

func StripSQL(s string) string

StripSQL removes "--" line comments and "/* */" block comments (each becomes a space, newlines kept) and empties single-quoted string literals (doubled-quote escapes included), in one pass so an apostrophe inside a comment or "--" inside a string cannot confuse the other. Double-quoted identifiers are kept.

Types

type MigrateReport

type MigrateReport struct {
	Module     string
	Applied    []string // applied by this run
	Backfilled []string // applied earlier without a checksum; checksum recorded now
	Mismatched []string // applied earlier, but the file in this binary has different content
}

MigrateReport is what one module's migrate run did. Names are file names ("0001_x.sql").

func MigrateWithReport

func MigrateWithReport(ctx context.Context, d *sql.DB, module string, files fs.FS) (MigrateReport, error)

MigrateWithReport is Migrate, also reporting what it applied and which already-applied files no longer match their recorded sha256 checksum. A mismatch is not an error: the caller decides how loudly to warn.

type SchemaInspection

type SchemaInspection struct {
	// Unknown are applied migrations this binary has no file for: a newer
	// binary migrated the database (the schema is ahead), or a module was
	// removed.
	Unknown []string `json:"unknown"`
	// Mismatched are applied migrations whose file in this binary differs
	// from the content recorded when they ran.
	Mismatched []string `json:"mismatched"`
}

SchemaInspection compares schema_migrations with the migration files a binary ships. Entries are "module/name", sorted.

func InspectMigrations

func InspectMigrations(ctx context.Context, d *sql.DB, known map[string]fs.FS) (SchemaInspection, error)

InspectMigrations reads schema_migrations and compares it with known, the migration files of every module this binary ships (module name → FS as given to Migrate; a nil FS means the module has no migrations). Rows of a module missing from known are all unknown. Rows without a checksum (applied before checksums, or by an older binary) are never mismatched.

func (SchemaInspection) Ahead

func (s SchemaInspection) Ahead() bool

Ahead reports whether the database holds migrations this binary does not know.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL