Swap deployment_merge_requests columns to bigint

What does this MR do and why?

Final step of the bigint conversion for deployment_merge_requests. Two post-deployment migrations, milestone 19.5.

ValidateDeploymentMergeRequestsBigintFks (20260914090001) synchronously validates three foreign keys on the shadow columns:

Column Constraint
deployment_id_convert_to_bigint fk_rails_dcbce9f4df_tmp
merge_request_id_convert_to_bigint fk_rails_86a6d8bf12_tmp
environment_id_convert_to_bigint fk_a064ff4453_tmp

All three are already validated on GitLab.com, confirmed via pg_constraint.convalidated, so this is a no-op there. It exists so self-managed instances reach the same state before the swap, which assumes validated foreign keys. Guarded by skip_bigint_migration?. down is a no-op, since leaving them validated is safe.

SwapColumnsForDeploymentMergeRequestsBigintConversion (20260914090002) swaps deployment_id, merge_request_id, and environment_id with their _convert_to_bigint counterparts inside with_lock_retries(raise_on_exhaustion: true).

Object type Swapped
Defaults The 0 defaults stay with the retired integer columns
Primary key deployment_merge_requests_pkey, rebuilt from the prepared bigint index
Indexes idx_environment_merge_requests_unique_index, index_deployment_merge_requests_on_merge_request_id
Foreign keys fk_rails_dcbce9f4df, fk_rails_86a6d8bf12, fk_a064ff4453, each with its _tmp counterpart

Three points for the reviewer:

  1. Primary key index name. The prepared bigint index was created under the hash of deployment_merge_requests_on_deployment_id_merge_request_id_pkey, not of the real constraint name deployment_merge_requests_pkey. That came from the async index preparation migration 20251110180845. The swap resolves it from that source name, held in PRIMARY_KEY_SOURCE_NAME.

  2. restore_primary_key_index placement. up does not call it. It relies on the prepared index, which is present and valid on GitLab.com, and fails loudly if missing rather than building a large unique index during the swap. down calls it twice: before the swap to provide the index that becomes the restored integer primary key, and after to leave bigint_idx_dd999be21656bf3d4bcc behind. Replacing the primary key consumes the index, unlike the secondary indexes, which are renamed in pairs.

  3. Wraparound check scope. The check covers only deployment_merge_requests, not deployments, merge_requests, or environments. This migration only renames existing foreign key constraints, which locks just the constrained table. Creating a foreign key locks both sides, and that already happened in !252939 (merged). On detection the migration raises rather than skips, because a skipped swap is still recorded as run.

Both triggers are retained: trigger_b472fca0a1da synchronizes the shadow columns, trigger_cfbec3f07e2b maintains the project_id sharding key. reset_all_trigger_functions runs after the renames.

Each index swap uses swap_index_if_exists. swap_indexes raises when either index is missing, which would abort the whole swap. Earlier conversions hit this in production.

db/structure.sql is unchanged. New installations already start from bigint, so both migrations are no-ops against the canonical schema.

References

How to set up and validate locally

  1. Run ./scripts/regenerate-schema and confirm db/structure.sql is unchanged.
  2. Note that the canonical schema has no shadow columns, so step 1 only proves the no-op path. db:gitlabcom-database-testing is the meaningful verification.
  3. For a real exercise, build a production-shaped copy of the table: integer canonical columns, bigint shadow columns with 0 defaults, the three prepared bigint indexes, all six foreign keys, and both triggers. Run up, down, then up again.

Result of that run: after up, canonical columns are bigint, shadow columns hold the old integer type, the 0 defaults sit on the retired integer columns, canonical index and foreign key names point at the bigint columns, and both triggers are present. After down, the original schema is restored exactly, including bigint_idx_dd999be21656bf3d4bcc. The second up matched the first.

RuboCop, ruby -c, and scripts/validate_migration_checksum all pass. Reek warnings match the baseline of comparable existing swap migrations.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Marius Bobin

Merge request reports

Loading
Loading