module PgPower::CreateIndexConcurrently::Migration

Provides ability to postpone index creation queries in migrations.

Overrides ‘add_index` and `add_foreign_key` methods for migration to be able to prevent indexes creation inside scope of transaction if they have to be created concurrently. Allows to run creation of postponed indexes.

This module included into ActiveRecord::Migration class to extend it with new features.

All postponed index creation queries are stored inside migration instance.

Attributes

postponed_queries[RW]

@attribute postponed_queries

@return [Array] list of arguments to call `add_index` method.

@private

Public Instance Methods

add_foreign_key(from_table, to_table, options = {}, &block) click to toggle source

Add a foreign key.

Options:

  • :column

  • :primary_key

  • :dependent

  • :exclude_index [Boolean]

  • :concurrent_index [Boolean]

@param [String, Symbol] from_table @param [String, Symbol] to_table @param [Hash] options @option options [String, Symbol] :column @option options [String, Symbol] :primary_key @option options [Hash] :dependent @option options [Boolean] :exclude_index @option options [Boolean] :concurrent_index

@raise [ArgumentError] in case of conflicted option were set

@see ::PgPower::ConnectionAdapters::PostgreSQLAdapter::ForeignerMethods.add_foreign_key

# File lib/pg_power/create_index_concurrently.rb, line 110
def add_foreign_key(from_table, to_table, options = {}, &block)
  from_table       = ::ActiveRecord::Migrator.proper_table_name(from_table)
  concurrent_index = options[:concurrent_index]

  if concurrent_index then
    if options[:exclude_index]
      raise ArgumentError, 'Conflicted options(exclude_index, concurrent_index) was found, both are set to true.'
    end

    options[:column] ||= connection.id_column_name_from_table_name(to_table)
    options = options.merge(:concurrently => concurrent_index)

    index_options = { :concurrently => true }
    enque(from_table, options[:column], index_options)
  end

  # GOTCHA:
  #   proceed foreign key creation, but giving :concurrent_index => true
  #   prevent normal index creation in PgPower's `add_foreign_key`.
  #   So, postponed creation could be done after transaction.
  #   -- zekefast 2012-09-12
  connection.add_foreign_key(from_table, to_table, options, &block)
end
add_index(table_name, column_name, options = {}, &block) click to toggle source

Add a new index to the table. column_name can be a single Symbol, or an Array of Symbols.

@param [Symbol, String] table_name @param [Symbol, String, Array<Symbol, String>] column_name @param [optional, Hash] options @option options [Boolean] :unique @option options [Boolean] :concurrently @option options [String] :where

@return [nil]

@see ActiveRecord::ConnectionAdapters::SchemaStatements.add_index in pg_power gem

# File lib/pg_power/create_index_concurrently.rb, line 72
def add_index(table_name, column_name, options = {}, &block)
  table_name = ::ActiveRecord::Migrator.proper_table_name(table_name)
  # GOTCHA:
  #   checks if index should be created concurretnly then put it into
  #   the queue to wait till queue processing will be called (should be
  #   happended after closing transaction).
  #   Otherwise just delegate call to PgPower's `add_index`.
  #   Block is given for future compatibility.
  #   -- zekefast 2012-09-12
  unless options[:concurrently]
    return connection.add_index(table_name, column_name, options, &block)
  end

  enque(table_name, column_name, options, &block)
  nil
end
process_postponed_queries() click to toggle source

Execute all postponed index creation.

@return [::PgPower::CreateIndexConcurrently::Migration]

# File lib/pg_power/create_index_concurrently.rb, line 137
def process_postponed_queries
  Array(@postponed_queries).each do |arguments, block|
    connection.add_index(*arguments, &block)
  end

  clear_queue

  self
end

Private Instance Methods

clear_queue() click to toggle source

Clean postponed queries queue.

@return [::PgPower::CreateIndexConcurrently::Migration] migration

# File lib/pg_power/create_index_concurrently.rb, line 150
def clear_queue
  @postponed_queries = []

  self
end
enque(*arguments, &block) click to toggle source

Add to the queue add_index call parameters to be able execute call later.

@param [Array] arguments @param [Proc] block

@return [::PgPower::CreateIndexConcurrently::Migration]

# File lib/pg_power/create_index_concurrently.rb, line 163
def enque(*arguments, &block)
  @postponed_queries ||= []
  @postponed_queries << [arguments, block]

  self
end