2021-11-11 11:23:49 +05:30
# frozen_string_literal: true
class FinalizeCiBuildsMetadataBigintConversion < Gitlab :: Database :: Migration [ 1 . 0 ]
disable_ddl_transaction!
TABLE_NAME = 'ci_builds_metadata'
def up
ensure_batched_background_migration_is_finished (
job_class_name : 'CopyColumnUsingBackgroundMigrationJob' ,
table_name : TABLE_NAME ,
column_name : 'id' ,
job_arguments : [ [ " id " ] , [ " id_convert_to_bigint " ] ]
)
ensure_batched_background_migration_is_finished (
job_class_name : 'CopyColumnUsingBackgroundMigrationJob' ,
table_name : TABLE_NAME ,
column_name : 'id' ,
job_arguments : [ [ " build_id " ] , [ " build_id_convert_to_bigint " ] ]
)
swap
end
def down
swap
end
private
def swap
# Indexes were pre-created on gitlab.com to avoid slowing down deployments
#
# rubocop:disable Migration/PreventIndexCreation
add_concurrent_index TABLE_NAME , :id_convert_to_bigint , unique : true , name : 'index_ci_builds_metadata_on_id_convert_to_bigint'
add_concurrent_index TABLE_NAME , :build_id_convert_to_bigint , where : 'has_exposed_artifacts IS TRUE' , name : 'index_ci_builds_metadata_on_build_id_int8_and_exposed_artifacts'
create_covering_index TABLE_NAME , 'index_ci_builds_metadata_on_build_id_int8_where_interruptible'
add_concurrent_index TABLE_NAME , :build_id_convert_to_bigint , unique : true , name : 'index_ci_builds_metadata_on_build_id_convert_to_bigint'
# rubocop:enable Migration/PreventIndexCreation
add_concurrent_foreign_key TABLE_NAME , :ci_builds , column : :build_id_convert_to_bigint , on_delete : :cascade ,
reverse_lock_order : true
with_lock_retries ( raise_on_exhaustion : true ) do
execute " LOCK TABLE ci_builds, #{ TABLE_NAME } IN ACCESS EXCLUSIVE MODE "
# rubocop:disable Migration/WithLockRetriesDisallowedMethod
swap_column :id
swap_column :build_id
# rubocop:enable Migration/WithLockRetriesDisallowedMethod
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
2021-12-11 22:18:48 +05:30
execute " ALTER FUNCTION #{ quote_table_name ( Gitlab :: Database :: UnidirectionalCopyTrigger . on_table ( TABLE_NAME , connection : connection ) . name ( :id , :id_convert_to_bigint ) ) } RESET ALL "
execute " ALTER FUNCTION #{ quote_table_name ( Gitlab :: Database :: UnidirectionalCopyTrigger . on_table ( TABLE_NAME , connection : connection ) . name ( :build_id , :build_id_convert_to_bigint ) ) } RESET ALL "
2021-11-11 11:23:49 +05:30
# Swap defaults for PK
execute " ALTER SEQUENCE ci_builds_metadata_id_seq OWNED BY #{ TABLE_NAME } .id "
change_column_default TABLE_NAME , :id , - > { " nextval('ci_builds_metadata_id_seq'::regclass) " }
change_column_default TABLE_NAME , :id_convert_to_bigint , 0
# Swap defaults for FK
change_column_default TABLE_NAME , :build_id , nil
change_column_default TABLE_NAME , :build_id_convert_to_bigint , 0
# Swap PK constraint
execute " ALTER TABLE #{ TABLE_NAME } DROP CONSTRAINT ci_builds_metadata_pkey CASCADE "
rename_index TABLE_NAME , 'index_ci_builds_metadata_on_id_convert_to_bigint' , 'ci_builds_metadata_pkey'
execute " ALTER TABLE #{ TABLE_NAME } ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY USING INDEX ci_builds_metadata_pkey "
# Rename the rest of the indexes (we already hold an exclusive lock, so no need to use DROP INDEX CONCURRENTLY here)
# rubocop:disable Migration/WithLockRetriesDisallowedMethod
swap_index 'index_ci_builds_metadata_on_build_id' , 'index_ci_builds_metadata_on_build_id_convert_to_bigint'
swap_index 'index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts' , 'index_ci_builds_metadata_on_build_id_int8_and_exposed_artifacts'
swap_index 'index_ci_builds_metadata_on_build_id_and_id_and_interruptible' , 'index_ci_builds_metadata_on_build_id_int8_where_interruptible'
# rubocop:enable Migration/WithLockRetriesDisallowedMethod
# Swap FK constraint
remove_foreign_key TABLE_NAME , name : concurrent_foreign_key_name ( TABLE_NAME , :build_id )
rename_constraint (
TABLE_NAME ,
concurrent_foreign_key_name ( TABLE_NAME , :build_id_convert_to_bigint ) ,
concurrent_foreign_key_name ( TABLE_NAME , :build_id )
)
end
end
def swap_index ( old , new )
execute " DROP INDEX #{ old } "
rename_index TABLE_NAME , new , old
end
def swap_column ( name )
temp_name = " #{ name } _tmp "
execute " ALTER TABLE #{ quote_table_name ( TABLE_NAME ) } RENAME COLUMN #{ quote_column_name ( name ) } TO #{ quote_column_name ( temp_name ) } "
execute " ALTER TABLE #{ quote_table_name ( TABLE_NAME ) } RENAME COLUMN #{ quote_column_name ( :" #{ name } _convert_to_bigint " ) } TO #{ quote_column_name ( name ) } "
execute " ALTER TABLE #{ quote_table_name ( TABLE_NAME ) } RENAME COLUMN #{ quote_column_name ( temp_name ) } TO #{ quote_column_name ( :" #{ name } _convert_to_bigint " ) } "
end
def create_covering_index ( table , name )
return if index_exists_by_name? ( table , name )
disable_statement_timeout do
execute << ~ SQL
CREATE INDEX CONCURRENTLY #{name}
ON #{table} (build_id_convert_to_bigint) INCLUDE (id_convert_to_bigint)
WHERE interruptible = true
SQL
end
end
end