Documentation
¶
Overview ¶
Package migrate provides internal utilities for database schema migrations.
Index ¶
- func IsBoolColumn(t reflect.Type) bool
- func NormalizeBoolDefault(dialectName, def string) string
- func PKColumnSQL(dialectName string, class PKClass, fallback string) string
- func RegisterTypeMapper(t reflect.Type, m TypeMapper)
- func SQLType(dialectName string, t reflect.Type, isPK bool) string
- func SQLTypeWithOpts(dialectName string, t reflect.Type, opts TypeOptions) string
- type PKClass
- type TypeMapper
- type TypeOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsBoolColumn ¶ added in v1.1.1
IsBoolColumn reports whether t maps to a boolean column. It unwraps a pointer (*bool) and the sql.Null[bool] / quark.Nullable[bool] wrapper the same way SQLTypeWithOpts resolves the column's SQL type, so the default-normalization decision stays consistent with the emitted column type. Callers use it to gate NormalizeBoolDefault.
func NormalizeBoolDefault ¶ added in v1.1.1
NormalizeBoolDefault rewrites a boolean column's `default:"..."` literal to the form the target dialect accepts in a DDL DEFAULT clause.
Quark passes a column default through to DDL verbatim, but a boolean default has NO single literal portable across the six engines: PostgreSQL's BOOLEAN requires TRUE/FALSE and rejects 1/0 (SQLSTATE 42804), while MSSQL's BIT and Oracle's NUMBER(1) require 1/0 and reject TRUE/FALSE. This recognizes the documented bool literals 1/0/true/false (case-insensitive) and emits the dialect-appropriate one (TRUE/FALSE for PostgreSQL, 1/0 for the rest).
Input must be one of 1/0/true/false (case-insensitive); any other string — a function call, a quoted literal, a non-bool value — is returned UNCHANGED, so non-boolean columns and custom expressions are unaffected. Callers gate this on IsBoolColumn; validating the default tag itself is the caller's job.
func PKColumnSQL ¶ added in v1.1.2
PKColumnSQL returns the full column-type fragment for a single-column primary key of the given class. `fallback` is the bare type to use for PKOther; it is ignored for the other classes.
func RegisterTypeMapper ¶ added in v0.3.0
func RegisterTypeMapper(t reflect.Type, m TypeMapper)
RegisterTypeMapper registers a custom Go-type → SQL-type mapping. The public API in package quark forwards to this; the registry lives here because internal/migrate.SQLType is the only consumer and we want the lookup to stay close to the lookup site.
Pointer types are stripped before registration: registering for time.Duration also covers *time.Duration. Re-registering the same type overwrites the previous mapper.
func SQLType ¶
When isPK is true the column DDL includes the PRIMARY KEY constraint. The exact type depends on the Go field kind:
- int / int64 → dialect-native auto-increment (SERIAL, AUTO_INCREMENT, IDENTITY…)
- string → VARCHAR(36) PRIMARY KEY — UUID-friendly; no auto-increment
- anything else → its natural SQL type + PRIMARY KEY (no auto-increment)
func SQLTypeWithOpts ¶ added in v0.3.0
func SQLTypeWithOpts(dialectName string, t reflect.Type, opts TypeOptions) string
SQLTypeWithOpts is the extended form of SQLType that propagates the field's sizing hints to the type mapper. It is the preferred entry point for the migrate / sync layers; SQLType remains as a convenience wrapper for callers that don't (yet) have TypeOptions.
Types ¶
type PKClass ¶ added in v1.1.2
type PKClass int
SQLType maps Go types to SQL types for the given dialect name.
PKClass classifies a single-column primary key for DDL rendering. Two callers funnel into PKColumnSQL so the PRIMARY KEY fragments live in exactly one place: the migrator (which classifies from the model's reflect.Kind inside SQLType) and ApplyPlan's CREATE TABLE executor (which classifies from the neutral type STRING via ClassifyPKType — the Go type is gone by then).
const ( // PKOther appends a plain PRIMARY KEY to the column's own type // (composite-key members never get here — they render as a // table-level constraint). PKOther PKClass = iota // PKInteger renders the dialect's auto-increment integer PK. PKInteger // PKString renders the dialect's fixed-width string PK (UUID/ULID). PKString )
func ClassifyPKType ¶ added in v1.1.2
ClassifyPKType maps a bare column-type string (catalog- or migrator-emitted) to its PKClass. Integer-family types get the auto-increment treatment — mirroring the reflect-side rule "integer PK → auto-increment" so a table created from a Plan matches the one SQLType would emit for the same model. Everything else renders as `<own type> PRIMARY KEY`; notably a string column keeps its declared type (TEXT/VARCHAR(n)) instead of being coerced to the reflect-side VARCHAR(36) — PKString is reachable only from the reflect path.
Bare `NUMBER` (no precision) is classified as integer on purpose: Oracle's catalog reports identity PK columns as precision-less NUMBER (the same asymmetry typesEqual's oracleBareNumberMatch handles on the diff side), so a Plan built from introspection of a Migrate-created table re-renders the identity clause instead of silently dropping it. A hand-made non-identity bare-NUMBER PK would be coerced — accepted trade-off, mirroring the diff layer's "the catalog only emits bare NUMBER for identity columns" assumption.
type TypeMapper ¶ added in v0.3.0
type TypeMapper func(dialect string, opts TypeOptions) string
TypeMapper produces a dialect-specific SQL type for a Go type. The caller supplies the dialect name (lower-case: "postgres", "mysql", ...) and the sizing hints from the field's tag. Implementations should fall back to sensible defaults if Size/Precision/Scale are zero.
func LookupTypeMapper ¶ added in v0.3.0
func LookupTypeMapper(t reflect.Type) TypeMapper
LookupTypeMapper returns the registered mapper for t (pointer stripped). Returns nil if no mapping is registered.