Skip to content

Add swap_primary_key database helper

Max Orefice requested to merge morefice/add-swap-primary-key-helper into master

Ref: #374743 (closed)

What does this MR do and why?

This MR adds a new migration helper method to swap primary key using a predefined index easily.

Why do we need this?

This is required in order to partition a table, the partition key must be include in the primary key.

It was brought up in !97926 (comment 1107227533) that we need to change the primary key of a table we are currently partitioning ci_builds_metadata.

This MR simplifies the process to swap the primary key.

Fake migration test

class SwapPrimaryKey < Gitlab::Database::Migration[2.0]
  disable_ddl_transaction!

  TABLE_NAME = :ci_builds_metadata
  PRIMARY_KEY = :ci_builds_metadata_pkey
  OLD_INDEX_NAME = :index_ci_builds_metadata_on_id_unique
  NEW_INDEX_NAME = :index_ci_builds_metadata_on_id_partition_id_unique

  def up
    swap_primary_key(TABLE_NAME, PRIMARY_KEY, NEW_INDEX_NAME)
  end

  def down
    add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_INDEX_NAME)
    add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_INDEX_NAME)

    unswap_primary_key(TABLE_NAME, PRIMARY_KEY, OLD_INDEX_NAME)
  end
end
Database changes
ci: == 20220922140645 SwapPrimaryKey: migrating ===================================
ci: -- transaction_open?()
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata)
ci:    -> 0.0000s
ci: -- quote_column_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- execute("ALTER TABLE \"ci_builds_metadata\" DROP CONSTRAINT \"ci_builds_metadata_pkey\" CASCADE\n")
ci:    -> 0.0009s
ci: -- rename_index(:ci_builds_metadata, :index_ci_builds_metadata_on_id_partition_id_unique, :ci_builds_metadata_pkey)
ci:    -> 0.0008s
ci: -- quote_table_name(:ci_builds_metadata)
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- execute("ALTER TABLE \"ci_builds_metadata\" ADD CONSTRAINT \"ci_builds_metadata_pkey\" PRIMARY KEY USING INDEX \"ci_builds_metadata_pkey\"\n")
ci:    -> 0.0011s
ci: == 20220922140645 SwapPrimaryKey: migrated (0.0163s) ==========================

------------------------ROLLBACK------------------------------

ci: == 20220922140645 SwapPrimaryKey: reverting ===================================
ci: -- transaction_open?()
ci:    -> 0.0000s
ci: -- index_exists?(:ci_builds_metadata, :id, {:unique=>true, :name=>:index_ci_builds_metadata_on_id_unique, :algorithm=>:concurrently})
ci:    -> 0.0056s
ci: -- execute("SET statement_timeout TO 0")
ci:    -> 0.0001s
ci: -- add_index(:ci_builds_metadata, :id, {:unique=>true, :name=>:index_ci_builds_metadata_on_id_unique, :algorithm=>:concurrently})
ci:    -> 0.0016s
ci: -- execute("RESET statement_timeout")
ci:    -> 0.0001s
ci: -- transaction_open?()
ci:    -> 0.0000s
ci: -- index_exists?(:ci_builds_metadata, [:id, :partition_id], {:unique=>true, :name=>:index_ci_builds_metadata_on_id_partition_id_unique, :algorithm=>:concurrently})
ci:    -> 0.0020s
ci: -- add_index(:ci_builds_metadata, [:id, :partition_id], {:unique=>true, :name=>:index_ci_builds_metadata_on_id_partition_id_unique, :algorithm=>:concurrently})
ci:    -> 0.0011s
ci: -- transaction_open?()
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata)
ci:    -> 0.0000s
ci: -- quote_column_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- execute("ALTER TABLE \"ci_builds_metadata\" DROP CONSTRAINT \"ci_builds_metadata_pkey\" CASCADE\n")
ci:    -> 0.0008s
ci: -- rename_index(:ci_builds_metadata, :index_ci_builds_metadata_on_id_unique, :ci_builds_metadata_pkey)
ci:    -> 0.0003s
ci: -- quote_table_name(:ci_builds_metadata)
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- quote_table_name(:ci_builds_metadata_pkey)
ci:    -> 0.0000s
ci: -- execute("ALTER TABLE \"ci_builds_metadata\" ADD CONSTRAINT \"ci_builds_metadata_pkey\" PRIMARY KEY USING INDEX \"ci_builds_metadata_pkey\"\n")
ci:    -> 0.0004s
ci: == 20220922140645 SwapPrimaryKey: reverted (0.0241s) ==========================
Indexes:
-     "ci_builds_metadata_pkey" PRIMARY KEY, btree (id)
+     "ci_builds_metadata_pkey" PRIMARY KEY, btree (id, partition_id)

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Max Orefice

Merge request reports