Skip to content
Snippets Groups Projects

Swap primary key with bigint column for ci_pipeline_variables

Merged Tianwen Chen requested to merge 408936-swap-pk into master
Files
3
# frozen_string_literal: true
class SwapCiPipelineVariablesPkWithBigint < Gitlab::Database::Migration[2.1]
include Gitlab::Database::MigrationHelpers::ConvertToBigint
disable_ddl_transaction!
TABLE_NAME = 'ci_pipeline_variables'
def up
swap
end
def down
+6
swap
end
private
def swap
# Prepare the names we need below
primary_key_constraint_name = "#{TABLE_NAME}_pkey"
sequence_name = "#{TABLE_NAME}_id_seq"
bigint_primary_key_index_name = "index_#{TABLE_NAME}_on_id_convert_to_bigint"
temp_name = quote_column_name(:id_tmp)
id_name = quote_column_name(:id)
id_convert_to_bigint_name = quote_column_name(:id_convert_to_bigint)
function_name = quote_table_name(
Gitlab::Database::UnidirectionalCopyTrigger.on_table(
TABLE_NAME, connection: Ci::ApplicationRecord.connection
).name(:id, :id_convert_to_bigint)
)
# 2. Create indexes using the bigint columns that match the existing indexes using the integer column
# NOTE: this index is already created in:
# - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120946
# - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120950
# Therefore, this won't have any effect for `up` step, but will be used for `down` step.
add_concurrent_index TABLE_NAME, :id_convert_to_bigint, unique: true, name: bigint_primary_key_index_name
# 4. Inside a transaction, swap the columns
with_lock_retries(raise_on_exhaustion: true) do
# a. Lock the tables involved.
execute "LOCK TABLE #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
# b. Rename the columns to swap names
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{id_name} TO #{temp_name}"
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{id_convert_to_bigint_name} TO #{id_name}"
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{temp_name} TO #{id_convert_to_bigint_name}"
# c. Reset the trigger function
execute "ALTER FUNCTION #{function_name} RESET ALL"
# d. Swap the defaults
execute "ALTER SEQUENCE #{sequence_name} OWNED BY #{TABLE_NAME}.id"
change_column_default TABLE_NAME, :id, -> { "nextval('#{sequence_name}'::regclass)" }
change_column_default TABLE_NAME, :id_convert_to_bigint, 0
# e. Swap the PK constraint
execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT #{primary_key_constraint_name} CASCADE"
rename_index TABLE_NAME, bigint_primary_key_index_name, primary_key_constraint_name
execute <<~SQL
ALTER TABLE #{TABLE_NAME}
ADD CONSTRAINT #{primary_key_constraint_name} PRIMARY KEY
USING INDEX #{primary_key_constraint_name}
SQL
end
end
end
Loading