On this page
Package diff compares two resolved schemas or a schema against a live database, producing a structured diff with risk annotations and partition changes.
#internal/diff
#internal/diff
Package diff compares two resolved schemas or a schema against a live database and produces a structured diff with risk annotations on each change.
#SchemaDiff
type SchemaDiff structSchemaDiff describes the differences between a desired and actual schema.
#RenamePair
type RenamePair structRenamePair is a resolved from->to rename (table or column).
#RenameSpec
type RenameSpec structRenameSpec is the set of declared renames consumed at diff time (parsed from the project config [renames] section). It is a pure, committed, CI-safe migration directive — never part of the schema's canonical identity.
#ColumnRenameSpec
type ColumnRenameSpec structColumnRenameSpec declares a single column rename within a table.
#SMTransitionDiff
type SMTransitionDiff structSMTransitionDiff describes changes to a state machine type's transitions. Enum value changes (states added/removed) are tracked separately in EnumsChanged.
#SMTransitionRef
type SMTransitionRef structSMTransitionRef identifies a single directed transition edge (from -> to).
#TableDiff
type TableDiff structTableDiff describes the differences within a single table.
#ColumnChange
type ColumnChange structColumnChange describes a change to a single column, with risk classification.
#EnumDiff
type EnumDiff structEnumDiff describes changes to an enum type.
#EnumValueInsert
type EnumValueInsert structEnumValueInsert describes an enum value inserted in the middle of an existing enum, requiring BEFORE/AFTER syntax in ALTER TYPE.
#ViewDiff
type ViewDiff structViewDiff describes changes to a view.
#MaterializedViewDiff
type MaterializedViewDiff structMaterializedViewDiff describes changes to a materialized view.
#SequenceDiff
type SequenceDiff structSequenceDiff describes changes to a sequence.
#CompositeTypeDiff
type CompositeTypeDiff structCompositeTypeDiff describes changes to a composite type. Composite type changes are destructive (DROP + CREATE CASCADE).
#CompositeFieldChange
type CompositeFieldChange structCompositeFieldChange describes a change to a composite type field.
#FunctionDiff
type FunctionDiff structFunctionDiff describes changes to a function/procedure.
#DomainDiff
type DomainDiff structDomainDiff describes changes to a domain type.
#FKChange
type FKChange structFKChange describes a changed foreign key constraint.
#IndexChange
type IndexChange structIndexChange describes a changed index.
#TriggerChange
type TriggerChange structTriggerChange describes a changed trigger.
#PolicyDiff
type PolicyDiff structPolicyDiff describes changes to a single RLS policy.
#PartitionDiff
type PartitionDiff structPartitionDiff describes changes to a table's partitioning configuration.
#MaintenanceDiff
type MaintenanceDiff structMaintenanceDiff describes changes to a table's partman maintenance configuration.
#LiveNormalizer
type LiveNormalizer interfaceLiveNormalizer resolves the ≈_pg RESIDUE that pure N cannot reach: catalog-dependent cast materialization (e.g. status = 'active' vs the PG-stored status = 'active'::text). It round-trips a desired-side expression through the target database — PG computes its own canonical form — so the desired side matches the introspected (already PG-canonical) side.
It is used ONLY on the live diff path (diff --live). Identity NEVER consumes its output: the pure/encoding path has no database. Implementations are best-effort total — an expression a round-trip cannot reach (referencing an absent table/column) falls to the minimal forward-simulation rule set, which is N itself.
#Diff
func Diff(desired, actual *model.Schema) *SchemaDiffDiff compares two registry-present models (desired vs actual) and returns a structured diff. Items in desired but not in actual are "added"; items in actual but not in desired are "removed". Both sides are the SAME model class (L7): semantic type names are compared. Use DiffLive when actual is an introspected (registry-absent) schema.
#DiffLive
func DiffLive(desired, actual *model.Schema, ln LiveNormalizer) *SchemaDiffDiffLive compares a registry-present desired model against an INTROSPECTED (registry-absent) actual schema, with an optional LiveNormalizer. Because the introspected side carries no semantic type information (L7 — a different model class), class-aware fields such as Column.SemanticTypeName are NOT compared, so they never false-drift. When ln is non-nil (the diff --live path), the DESIRED side's table-scoped expressions are round-tripped through the target DB before comparison, resolving the catalog-dependent cast residue. The caller's desired schema is never mutated — a normalized copy is built.
#IsWidening
func IsWidening(oldType, newType string) boolIsWidening returns true if oldType -> newType is a safe widening conversion. Arguments are SQL type strings (e.g., from typeinfo.Reconstruct output).
#ChangedObjectKeys
func ChangedObjectKeys(desired, actual *model.Schema) ([]enc.Key, error)ChangedObjectKeys is the per-object-id DIFF FAST PATH (roadmap kernel 1.4, Part I). It builds both models' revision manifests (kind-qualified key -> object-id) and returns the keys whose canonical bytes differ: objects present on one side only, or present on both with a different content id. A caller can then DEEP-diff only these objects and skip every object whose id is unchanged, turning a whole-schema comparison into O(changed objects).
When the result is empty the two models are byte-identical object-for-object, hence ≈_syn-equal, hence diff-empty (the forward conformance direction).
WIRING CHOICE (reported): this is the "kernel utility diff CONSUMES" option, not a short-circuit injected into Diff. Diff remains the AUTHORITATIVE full comparison for two reasons: (1) building two manifests on every Diff call would add an encode pass to the common (unequal) path; (2) more importantly, a manifest-equality short-circuit inside Diff would MASK Diff's own object-by-object logic from the forward-conformance test (which compares a model against its round-trip) — the test would then exercise the short-circuit rather than Diff. Keeping the fast path as a consumed utility preserves both Diff's semantics and the test's teeth. The on-disk chain (roadmap 5.2), where both manifests are already materialized, is the natural caller that prunes its O(objects) work through this function.
#FormatTerminal
func FormatTerminal(d *SchemaDiff) stringFormatTerminal renders the diff as human-readable colored terminal output.
#FormatJSON
func FormatJSON(d *SchemaDiff) stringFormatJSON renders the diff as a JSON string.
#CheckTruncationCollisions
func CheckTruncationCollisions(s *model.Schema) errorCheckTruncationCollisions is the NAMEDATALEN collision guard for the diff path. Content-derived constraint/index names can exceed 63 bytes; when two DISTINCT such names in one table collection truncate to the same 63 bytes, PostgreSQL stores them identically and matchObjectsTrunc's truncation-aware fallback can no longer tell them apart — it would silently pair both desired names against the one truncated actual. This guard runs on the DESIRED schema before any diff and returns a HARD ERROR naming the truncation and every colliding name, per-collection and per-table, so the ambiguity is surfaced loudly instead of producing a wrong migration. It is a pure function of the desired schema (the collision is a property of desired names alone).
#ResolveRenames
func ResolveRenames(d *SchemaDiff, desired, actual *model.Schema, spec RenameSpec, actualIntrospected bool) errorResolveRenames applies the rename gate to a computed diff. actual is the base model (the reconstructed head, or the introspected live schema); it may be nil at genesis, where no removals and therefore no renames are possible. actualIntrospected suppresses class-aware column comparison against an introspected base (matching diffColumn's own contract).
#SchemaDiff.IsEmpty
func (d *SchemaDiff) IsEmpty() boolIsEmpty returns true if the diff contains no changes.
#SchemaDiff.Summary
func (d *SchemaDiff) Summary() stringSummary returns a human-readable summary of the diff.