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
currentbut absent fromprevious(byModel::NAME) has the same NAME as a model present inpreviousbut absent fromcurrent, the table name changed: emitRenameTable { from, to }instead of DropTable + CreateTable. A stdout message names the rename so the developer can auditmakemigrationsoutput. - 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
RenameTableand 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.