Skip to main content

diff

Function diff 

Source
pub fn diff(
    previous: &Snapshot,
    current: &Snapshot,
) -> Result<Vec<Operation>, MigrateError>
Expand description

Diff the previous snapshot against the current one and produce the ordered operation list.

Emits CreateTable / DropTable for whole-model changes (M5 v1), and AddColumn / DropColumn for column-level changes on a model that appears in both snapshots (M8 v1). A column whose name stays the same but whose type or nullable flag changed surfaces as MigrateError::UnsafeAlter: SQLite can’t ALTER COLUMN TYPE in place, and a nullable flip on a populated table is destructive.

Gap 30 adds two-pass rename detection. Model::NAME (the Rust struct name) is the stable identity key across snapshots; the SQL table name in Model::TABLE may change (e.g. via the #[umbral(plugin = "...")] opt-in). The two passes are:

  • First pass — struct-name match. If a model present in current but absent from previous (by Model::NAME) has the same NAME as a model present in previous but absent from current, the table name changed: emit RenameTable { from, to } instead of DropTable + CreateTable. A stdout message names the rename so the developer can audit makemigrations output.
  • Second pass — column-shape match. Among unpaired drops and creates, if a drop candidate and a create candidate have bit-identical column shapes (same column names, types, nullable, fk_target), emit RenameTable and log a warning so the developer can verify the intent. Struct names differ; the shape heuristic fills in for cases like a wholesale model rename (Foo → Bar, identical fields).
  • No-match. Drop and create as today.

pub (not pub(crate)) so integration tests can drive the diff directly with hand-built snapshots. Spec 06 calls the diff the engine’s contract; exposing it lets the tests pin every scenario without laundering snapshots through the process-wide registry.