-- Per-instance match-contract counter on an owned instance. -- -- NULLABLE ON PURPOSE. NULL means "Core tracks no contract for this instance", -- which is NOT the same as zero: a game whose contracts start at a pack-fresh -- default (FIFA 17 hands out 7) must supply that default itself, so the number -- stays in the game adapter and never becomes a Core constant. Every row that -- pre-dates this migration therefore reads back NULL and keeps its exact prior -- meaning — the migration is a pure widening, not a backfill. -- -- `>= 0` only: the cap is a per-application input (the caller's game rule), not -- a schema invariant, so the CHECK refuses the one value that is nonsense in -- every game rather than pinning someone else's ceiling. -- -- ALTER TABLE ADD COLUMN, NEVER a table rebuild: `owned_cards` carries the -- `clear_club_active_item_before_transfer` trigger installed by 0026, and a -- DROP/recreate would silently take it with it — exactly the failure 0026:44-46 -- documents for 0024's trigger. ALTER TABLE owned_cards ADD COLUMN contract_matches INTEGER CHECK (contract_matches IS NULL OR contract_matches >= 0);