Diff a model's declared columns against the reflected ones from a live table:
declared-only columns are Added, reflected-only are Removed, and a name in
both with a different col_type is TypeChanged. An empty result means the table
matches the model. This is the write half of autogenerate — feed the diff to DDL
to synthesise the migration.
Scope: reflection recovers only a column's storage type, so declare a model at the
same granularity to avoid spurious diffs — a Bool stored as INTEGER reflects as
Int, Uuid/Json stored as TEXT reflect as Text. And the diff reports
add/remove/type only, not nullable / default / unique / PK / FK changes.
With dialect the types compare as that engine writes them, so a BigIntType
declared against SQLite, where every integer is INTEGER, is no change; without
it they compare as declared.