module OnlineMigrations::Utils

@private

Constants

FUNCTION_CALL_RE

Public Class Methods

ar_partial_writes?() click to toggle source
# File lib/online_migrations/utils.rb, line 79
def ar_partial_writes?
  ActiveRecord::Base.public_send(ar_partial_writes_setting)
end
ar_partial_writes_setting() click to toggle source
# File lib/online_migrations/utils.rb, line 83
def ar_partial_writes_setting
  if Utils.ar_version >= 7.0
    "partial_inserts"
  else
    "partial_writes"
  end
end
ar_version() click to toggle source
# File lib/online_migrations/utils.rb, line 7
def ar_version
  ActiveRecord.version.to_s.to_f
end
ar_where_not_multiple_conditions(relation, conditions) click to toggle source
# File lib/online_migrations/utils.rb, line 114
def ar_where_not_multiple_conditions(relation, conditions)
  if Utils.ar_version >= 6.1
    relation.where.not(conditions)
  else
    # In Active Record < 6.1, NOT with multiple conditions behaves as NOR,
    # which should really behave as NAND.
    # https://www.bigbinary.com/blog/rails-6-deprecates-where-not-working-as-nor-and-will-change-to-nand-in-rails-6-1
    arel_table = relation.arel_table
    conditions = conditions.map { |column, value| arel_table[column].not_eq(value) }
    conditions = conditions.inject(:or)
    relation.where(conditions)
  end
end
connection() click to toggle source
# File lib/online_migrations/utils.rb, line 63
def self.connection
  @online_migrations_connection
end
define_model(table_name, connection = ActiveRecord::Base.connection) click to toggle source
# File lib/online_migrations/utils.rb, line 56
def define_model(table_name, connection = ActiveRecord::Base.connection)
  Class.new(ActiveRecord::Base) do
    self.table_name = table_name
    self.inheritance_column = :_type_disabled

    @online_migrations_connection = connection

    def self.connection
      @online_migrations_connection
    end
  end
end
developer_env?() click to toggle source
# File lib/online_migrations/utils.rb, line 11
def developer_env?
  defined?(Rails) && (Rails.env.development? || Rails.env.test?)
end
estimated_count(connection, table_name) click to toggle source

Returns estimated rows count for a table. www.citusdata.com/blog/2016/10/12/count-performance/

# File lib/online_migrations/utils.rb, line 93
      def estimated_count(connection, table_name)
        quoted_table = connection.quote(table_name)

        count = connection.select_value(<<-SQL.strip_heredoc)
          SELECT
            (reltuples / COALESCE(NULLIF(relpages, 0), 1)) *
            (pg_relation_size(#{quoted_table}) / (current_setting('block_size')::integer))
          FROM pg_catalog.pg_class
          WHERE relname = #{quoted_table}
            AND relnamespace = current_schema()::regnamespace
        SQL

        if count
          count = count.to_i
          # If the table has never yet been vacuumed or analyzed, reltuples contains -1
          # indicating that the row count is unknown.
          count = 0 if count == -1
          count
        end
      end
foreign_table_name(ref_name, options) click to toggle source
# File lib/online_migrations/utils.rb, line 73
def foreign_table_name(ref_name, options)
  options.fetch(:to_table) do
    ActiveRecord::Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
  end
end
migration_parent() click to toggle source
# File lib/online_migrations/utils.rb, line 32
def migration_parent
  if ar_version <= 4.2
    ActiveRecord::Migration
  else
    ActiveRecord::Migration[ar_version]
  end
end
migration_parent_string() click to toggle source
# File lib/online_migrations/utils.rb, line 40
def migration_parent_string
  if ar_version <= 4.2
    "ActiveRecord::Migration"
  else
    "ActiveRecord::Migration[#{ar_version}]"
  end
end
model_parent_string() click to toggle source
# File lib/online_migrations/utils.rb, line 48
def model_parent_string
  if ar_version >= 5.0
    "ApplicationRecord"
  else
    "ActiveRecord::Base"
  end
end
say(message) click to toggle source
# File lib/online_migrations/utils.rb, line 15
def say(message)
  message = "[online_migrations] #{message}"
  if (migration = OnlineMigrations.current_migration)
    migration.say(message)
  elsif (logger = ActiveRecord::Base.logger)
    logger.info(message)
  end
end
supports_multiple_dbs?() click to toggle source
# File lib/online_migrations/utils.rb, line 28
def supports_multiple_dbs?
  ar_version >= 6.0
end
to_bool(value) click to toggle source
# File lib/online_migrations/utils.rb, line 69
def to_bool(value)
  !value.to_s.match(/^(true|t|yes|y|1|on)$/i).nil?
end
volatile_default?(connection, type, value) click to toggle source
# File lib/online_migrations/utils.rb, line 131
def volatile_default?(connection, type, value)
  return false unless value.is_a?(Proc) || (type.to_s == "uuid" && value.is_a?(String))

  value = value.call if value.is_a?(Proc)
  return false if !value.is_a?(String)

  value.scan(FUNCTION_CALL_RE).any? { |(function_name)| volatile_function?(connection, function_name.downcase) }
end
volatile_function?(connection, function_name) click to toggle source
# File lib/online_migrations/utils.rb, line 140
      def volatile_function?(connection, function_name)
        query = <<-SQL.strip_heredoc
          SELECT provolatile
          FROM pg_catalog.pg_proc
          WHERE proname = #{connection.quote(function_name)}
        SQL

        connection.select_value(query) == "v"
      end
warn(message) click to toggle source
# File lib/online_migrations/utils.rb, line 24
def warn(message)
  Kernel.warn("[online_migrations] #{message}")
end