Expand description
Schema diff engine: given a target SchemaDescriptor and the live database state (introspected via pg_catalog), produce ordered DDL SQL statements to bring the database in sync with the target.
Used by pylon migration watch (apply directly) and pylon migration create
(render as a migration file body). Pure computation — no I/O.
Structs§
- ColRename
Candidate - A detected potential column rename within an existing table: a dropped column and an added column with the same Postgres type.
- DbCheck
- DbColumn
- DbDomain
- DbEnum
- DbForeign
Key - DbFunction
- DbIndex
- DbSequence
- DbState
- Snapshot of the live PostgreSQL database, built by Python from pg_catalog queries.
- DbTable
- DbView
- DiffOp
- A single DDL operation produced by the diff engine.
- Fill
Required - A column that is being made NOT NULL but currently contains (or could contain) NULL rows, requiring a fill expression to backfill existing rows before the constraint can be added.
- Guidance
- Guidance for re-diffing after a rejected rename candidate — mirrors the two ambiguity detectors below; a plain create/alter/drop has no alternative reading to search for, so rejecting one of those just excludes it (handled by the interactive caller, not here).
- Migration
Step - Required
Input - One
\(placeholder)token embedded in a step’s DDL that the caller must resolve to a PyQL expression (compiled viaquery::compile_fill_expr, evaluated againsttype_name) before executing that statement — mirrors how a fill expression is resolved, just for a type-change’s conversion expression instead of a backfill. - Type
Rename Candidate - A detected potential type (table) rename: a dropped table whose column structure closely matches a newly-created type.
Enums§
- OpKey
- Stable identity an emitted step is grouped by. Every DDL statement that answers the same logical question (e.g. every column/FK/trigger change to one table) shares one key and therefore one step.
- Verb
Functions§
- db_
state_ from_ json - Deserialize a
DbStatefrom the JSON stored in_pylon."Migrations".db_state. - db_
state_ to_ json - Serialize a
DbStateto a JSON string for storage in_pylon."Migrations".db_state. - detect_
col_ renames - Detect potential column renames within tables that exist in both
currentandtarget. A candidate is a (dropped_col, added_col) pair in the same table with the same Postgres type. Candidates already rejected once (guidance.banned_col_renames) are never proposed again. - detect_
fill_ required - Detect all properties that are being made NOT NULL but whose existing rows may contain NULL values and therefore require a fill expression.
- detect_
type_ renames - Detect potential type (table) renames: tables that exist in
currentbut not intarget, paired with types that exist intargetbut not incurrent, where the column-set Jaccard similarity meets a threshold. Candidates already rejected once (guidance.banned_type_renames) are never proposed again — a re-diff after “no” should offer something else. - diff_
schema - Compute ordered DDL SQL strings to bring a database in sync with
target. All statements use plain (non-CONCURRENTLY) index creation — suitable forwatchmode where everything runs inside a single transaction. - diff_
schema_ ops - Compute ordered
DiffOps suitable for a migration file body. Index creation on pre-existing tables usesCONCURRENTLYand is markednon_transactional = truesocreatecan insert step-boundary markers. - diff_
schema_ ops_ with_ renames_ and_ fills - Full diff with confirmed renames and fill expressions applied.
- diff_
schema_ steps - Compute the diff as one
MigrationStepper logical schema-level question — for an interactive caller that confirms/rejects one object at a time instead of a flat DDL dump.fill_indexmarks columns whose NOT NULL constraint is deferred to a caller-supplied backfill (seediff_schema_ops_with_renames_and_fills’s doc comment). - diff_
schema_ steps_ with_ renames_ and_ fills - Like
diff_schema_ops_with_renames_and_fillsbut returnsMigrationSteps grouped by object instead of a flatDiffOplist — for the interactive confirmation loop. Renames themselves aren’t represented as steps here; the caller resolves those first (seedetect_type_renames/detect_col_renames+Guidance) and passes the confirmed set in, same as the flat-DiffOpversion. A fill’sUPDATE+SET NOT NULLfolds into its own table’s step (falling back to a standalone step in the rare case that table has no other change in this diff). - diff_
states - Diff two live-database snapshots (used by squash to capture the net effect of a range of migrations applied to an ephemeral shadow database). “before” = state at the start of the squashed range, “after” = state at the end. Returns DiffOps suitable for a migration file body.
- expected_
triggers - missing_
extension_ ddl CREATE EXTENSION IF NOT EXISTSstatements for every extensiontargetrequires that isn’t already present incurrent— meant to be prepended to an assembled migration/watchsync unconditionally, outside the interactive per-step confirmation flow: enabling a required extension isn’t a design decision to confirm or reject, it’s a hard prerequisite the rest of the DDL can’t succeed without.- required_
extensions - Postgres extensions
targetneeds in order for its own DDL to apply cleanly — currently justvector(pgvector), needed the moment any type declares a vector index. Extending this to a future extension-dependent feature is just adding another check here; the caller-facing surface (missing_extension_ddl) doesn’t change. - schema_
content_ changed - True when
targetdiffers frompreviousin ANY way at all — not just the DDL-visible partsdiff_schema_steps/diff_schema_opscan see. - schema_
to_ db_ state - Convert a compiled
SchemaDescriptorinto the equivalentDbStatesnapshot.