Documentation
¶
Index ¶
- Variables
- func CountTables(ctx context.Context, db orm.DB, kind config.DBKind, tables []string) (int, error)
- func IsBusyContention(err error) bool
- func LoadScript(scripts fs.FS, kind config.DBKind) (string, error)
- func LoadTableColumns(ctx context.Context, db orm.DB, kind config.DBKind, table string) (map[string]Column, error)
- func Run(ctx context.Context, db orm.DB, plan Plan) error
- func TableExists(ctx context.Context, db orm.DB, kind config.DBKind, table string) (bool, error)
- func WithLock(ctx context.Context, db orm.DB, kind config.DBKind, name string, ...) error
- type Column
- type ColumnKind
- type Index
- type Plan
Constants ¶
This section is empty.
Variables ¶
var ErrUnsupportedDBKind = errors.New("sqlmigration: unsupported database kind")
ErrUnsupportedDBKind indicates the configured database dialect has no migration script or schema lookup query for the supplied Plan.
Functions ¶
func CountTables ¶ added in v0.40.0
CountTables counts how many of the named tables exist in the connection's active schema — current_schema() on Postgres, the connected database on MySQL, the main database on SQLite. Every migration probe shares this one dialect vocabulary so presence semantics cannot drift between modules.
func IsBusyContention ¶ added in v0.40.0
IsBusyContention reports whether err is SQLite write-lock contention: another connection held the database's single writer, so the statement was refused rather than failing on its own merits. Callers treat it as a benign "try again" — the migration lock retries acquisition, the cron store retries a claim on the next tick and re-attempts an outcome write.
The driver's own result code is authoritative and is trusted alone whenever it is available: an unrelated failure must never reclassify as contention because a statement argument echoed into its message happened to read "is locked". Only a driver that surfaces no result code (the cgo github.com/mattn/go-sqlite3 build) falls back to matching the message.
func LoadScript ¶
LoadScript returns the DDL script for the given dialect from the supplied script bundle. Exported so callers that need the SQL text (e.g. integration tests) can re-use the lookup convention.
func LoadTableColumns ¶ added in v0.40.0
func LoadTableColumns( ctx context.Context, db orm.DB, kind config.DBKind, table string, ) (map[string]Column, error)
LoadTableColumns returns the table's columns keyed by name, with types normalized into the ColumnKind vocabulary. The probe follows the connection's active schema, like every sqlmigration metadata query.
func Run ¶
Run executes the supplied Plan under the module's migration lock, so concurrently booting nodes provision a schema exactly once instead of racing the probe. It is a no-op when every expected table is already present and Pre hooks have completed without error.
func TableExists ¶ added in v0.40.0
TableExists reports whether the named table exists in the connection's active schema.
func WithLock ¶ added in v0.40.0
func WithLock( ctx context.Context, db orm.DB, kind config.DBKind, name string, fn func(context.Context, orm.DB) error, ) error
WithLock runs fn while holding the named migration lock, serializing concurrently booting nodes through the database's own locking primitive: a transaction-scoped advisory lock on Postgres, GET_LOCK on a dedicated MySQL connection, and BEGIN IMMEDIATE on SQLite (whose single writer makes the database file itself the lock scope). fn receives the handle the DDL must execute on — a transaction on Postgres and SQLite, a dedicated connection on MySQL.
Types ¶
type Column ¶ added in v0.40.0
type Column struct {
// Kind is the dialect-neutral type classification.
Kind ColumnKind
// Nullable reports whether the column accepts NULL.
Nullable bool
// MaxLength is the declared character bound of a varchar column; zero
// when unbounded or not exposed by the dialect (SQLite reports it only
// through the declared type text).
MaxLength int
}
Column is the observed metadata of one table column, normalized across dialects. LoadTableColumns keys it by column name.
type ColumnKind ¶ added in v0.40.0
type ColumnKind string
ColumnKind is the dialect-neutral classification of a column's declared type: schema verifiers compare requirements against it instead of against raw dialect type names.
const ( // ColumnVarchar is a length-bounded character column; Column.MaxLength // carries the bound where the dialect exposes one. ColumnVarchar ColumnKind = "varchar" // ColumnTimestamp is a wall-clock timestamp without timezone. ColumnTimestamp ColumnKind = "timestamp" // ColumnInt64 is a signed 64-bit integer; unsigned MySQL declarations // deliberately do not normalize to it. ColumnInt64 ColumnKind = "int64" // ColumnInt32 is a signed 32-bit integer; unsigned MySQL declarations // deliberately do not normalize to it. ColumnInt32 ColumnKind = "int32" // ColumnBool is a boolean (tinyint(1) on MySQL). ColumnBool ColumnKind = "bool" // ColumnJSON is a JSON document column (jsonb on Postgres). ColumnJSON ColumnKind = "json" // ColumnText is an unbounded character column. ColumnText ColumnKind = "text" )
Dialect-neutral column kinds. A declaration outside this vocabulary surfaces verbatim (lowercased) so capability mismatches name what the schema actually contains.
type Index ¶ added in v0.40.0
type Index struct {
// Name is the index's schema name.
Name string
// Columns is the exact key column sequence.
Columns []string
// Unique reports whether the index enforces uniqueness.
Unique bool
}
Index is the observed metadata of one table index. Capability checks match on Columns and Unique; Name exists for diagnostics only.
func LoadTableIndexes ¶ added in v0.40.0
func LoadTableIndexes( ctx context.Context, db orm.DB, kind config.DBKind, table string, ) ([]Index, error)
LoadTableIndexes returns the table's complete, non-partial indexes with their exact key column sequences. Partial and expression indexes are excluded — they cannot back a capability requirement — and MySQL prefix index parts surface as an empty column name so they never match one.
type Plan ¶
type Plan struct {
// Label is a short, human-readable identifier ("storage",
// "event inbox", ...). Used as the error prefix and as the
// migration lock name.
Label string
// Kind is the database dialect.
Kind config.DBKind
// Scripts is the SQL bundle — typically a //go:embed FS. Run looks up
// "scripts/<kind>.sql" within it.
Scripts fs.FS
// ExpectedTables names every table the migration must end up with.
// The migration is skipped when all of them already exist.
ExpectedTables []string
// Pre is an optional list of steps that run before the
// needs-migration probe (e.g. dropping obsolete tables left over
// from earlier schema revisions). Each hook should be idempotent.
Pre []func(ctx context.Context, db orm.DB) error
}
Plan describes one module's migration. Label appears in error messages so logs identify which module is being migrated.