You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix: seed() crash in Django mode and silent seeder failures
- seed() used self._runner.engine which is None in Django mode;
switch to self._seeder.engine which is always set
- replace bare except/pass in SmartSeeder.seed_table() with
warnings.warn so failures are visible instead of swallowed silently
Closes#83, #84
* fix: seed() ignored rows param, UNIQUE collisions in check_all, silent custom-seed failures
Three root causes fixed:
1. seed() was calling seed_table() (auto-generates rows) instead of
inserting the caller-supplied rows. Add SmartSeeder.seed_custom()
and wire seed() through it so the rows parameter is actually used.
2. SmartSeeder.seed_table() used a deterministic hash for generated
values, causing UNIQUE constraint violations when check_all() seeded
the same table across consecutive revision checks (prior rows survive
downgrade and remain in the DB). Add a per-instance random offset so
each SmartSeeder produces distinct values.
3. Custom-seed insertion in verifier._build_seeder() silently swallowed
all exceptions. Replace bare except/pass with warnings.warn so
failures are visible.
* fix: seeder value generation — prevent UNIQUE collisions for any column type
String columns used a fixed-width row_index format that truncates to the
same prefix when the instance offset is large (e.g. offset=500000 →
"mrt_title_500000"[:10] == "mrt_title_" for all rows). Switch to
uuid4().hex[:limit] which is unique regardless of column length.
Datetime/date/time types had a narrow modulo range (28 days, 24 hours)
causing cross-instance collisions. Spread values over a 10-year window
using the full hash seed instead.
* feat: add PostgreSQL concurrency safety patterns MRT211-MRT213
Three new static analysis checks for lock-heavy PostgreSQL operations:
MRT211 — create_foreign_key() without postgresql_not_valid=True
Acquires ShareRowExclusiveLock and scans the referencing table.
Safe path: add with NOT VALID, then VALIDATE CONSTRAINT separately.
MRT212 — create_check_constraint() without postgresql_not_valid=True
Full table scan under AccessShareLock. Same two-step approach applies.
MRT213 — alter_column(nullable=False) on an existing column
SET NOT NULL triggers a full table scan under AccessExclusiveLock.
Safe path on PG 12+: validated CHECK constraint first, then SET NOT NULL.
Closes#85
* revert: remove MRT211/MRT212 (lock warnings outside core scope)
MRT211 (FK without NOT VALID) and MRT212 (CHECK without NOT VALID) warn
about PostgreSQL lock duration — a performance/availability concern, not
a data survival or rollback safety concern. That's django-migration-linter
territory.
MRT213 (SET NOT NULL on existing column) stays: it's about existing NULL
data causing migration failure, consistent with MRT401/MRT403.
* test: fill coverage gaps — seed() E2E, seed_custom(), Django mode seed(), cli drift
* fix: don't track custom seed rows whose INSERT failed (false positive)
A failed custom-seed INSERT was caught and warned, but the row had
already been appended to the seeder's tracked rows. verify() then
reported it as 'lost after rollback', blaming the migration for data
the seed never inserted. Track rows only after a successful insert.
Also applies ruff format to verifier.py (fixes CI lint failure).
0 commit comments