class ActiveRecord::ConnectionAdapters::SchemaCreation

:nodoc:

def accept(o)

def accept(o)
  m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
  send m, o
end

def action_sql(action, dependency)

def action_sql(action, dependency)
  case dependency
  when :nullify then "ON #{action} SET NULL"
  when :cascade  then "ON #{action} CASCADE"
  when :restrict then "ON #{action} RESTRICT"
  else
    raise ArgumentError, <<~MSG
      '#{dependency}' is not supported for :on_update or :on_delete.
      Supported values are: :nullify, :cascade, :restrict
    MSG
  end
end

def add_column_options!(sql, options)

def add_column_options!(sql, options)
  sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
  # must explicitly check for :null to allow change_column to work on migrations
  if options[:null] == false
    sql << " NOT NULL"
  end
  if options[:auto_increment] == true
    sql << " AUTO_INCREMENT"
  end
  if options[:primary_key] == true
    sql << " PRIMARY KEY"
  end
  sql
end

def add_table_options!(create_sql, o)

def add_table_options!(create_sql, o)
  create_sql << " #{o.options}" if o.options
  create_sql
end

def column_options(o)

def column_options(o)
  o.options.merge(column: o)
end

def initialize(conn)

:nodoc:
def initialize(conn)
  @conn = conn
  @cache = {}
end

def quoted_columns(o)

def quoted_columns(o)
  String === o.columns ? o.columns : quoted_columns_for_index(o.columns, o.column_options)
end

def supports_index_using?

def supports_index_using?
  true
end

def table_modifier_in_create(o)

Returns any SQL string to go between CREATE and TABLE. May be nil.
def table_modifier_in_create(o)
  " TEMPORARY" if o.temporary
end

def to_sql(sql)

def to_sql(sql)
  sql = sql.to_sql if sql.respond_to?(:to_sql)
  sql
end

def visit_AddCheckConstraint(o)

def visit_AddCheckConstraint(o)
  "ADD #{accept(o)}"
end

def visit_AddColumnDefinition(o)

def visit_AddColumnDefinition(o)
  +"ADD #{accept(o.column)}"
end

def visit_AddForeignKey(o)

def visit_AddForeignKey(o)
  "ADD #{accept(o)}"
end

def visit_AlterTable(o)

def visit_AlterTable(o)
  sql = +"ALTER TABLE #{quote_table_name(o.name)} "
  sql << o.adds.map { |col| accept col }.join(" ")
  sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
  sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
  sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
  sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
end

def visit_CheckConstraintDefinition(o)

def visit_CheckConstraintDefinition(o)
  "CONSTRAINT #{o.name} CHECK (#{o.expression})"
end

def visit_ColumnDefinition(o)

def visit_ColumnDefinition(o)
  o.sql_type = type_to_sql(o.type, **o.options)
  column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
  add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
  column_sql
end

def visit_CreateIndexDefinition(o)

def visit_CreateIndexDefinition(o)
  index = o.index
  sql = ["CREATE"]
  sql << "UNIQUE" if index.unique
  sql << "INDEX"
  sql << o.algorithm if o.algorithm
  sql << "IF NOT EXISTS" if o.if_not_exists
  sql << index.type if index.type
  sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
  sql << "USING #{index.using}" if supports_index_using? && index.using
  sql << "(#{quoted_columns(index)})"
  sql << "WHERE #{index.where}" if supports_partial_index? && index.where
  sql.join(" ")
end

def visit_DropCheckConstraint(name)

def visit_DropCheckConstraint(name)
  "DROP CONSTRAINT #{quote_column_name(name)}"
end

def visit_DropForeignKey(name)

def visit_DropForeignKey(name)
  "DROP CONSTRAINT #{quote_column_name(name)}"
end

def visit_ForeignKeyDefinition(o)

def visit_ForeignKeyDefinition(o)
  sql = +<<~SQL
    CONSTRAINT #{quote_column_name(o.name)}
    FOREIGN KEY (#{quote_column_name(o.column)})
      REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
  SQL
  sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
  sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
  sql
end

def visit_PrimaryKeyDefinition(o)

def visit_PrimaryKeyDefinition(o)
  "PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
end

def visit_TableDefinition(o)

def visit_TableDefinition(o)
  create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
  create_sql << "IF NOT EXISTS " if o.if_not_exists
  create_sql << "#{quote_table_name(o.name)} "
  statements = o.columns.map { |c| accept c }
  statements << accept(o.primary_keys) if o.primary_keys
  if supports_indexes_in_create?
    statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
  end
  if supports_foreign_keys?
    statements.concat(o.foreign_keys.map { |fk| accept fk })
  end
  if supports_check_constraints?
    statements.concat(o.check_constraints.map { |chk| accept chk })
  end
  create_sql << "(#{statements.join(', ')})" if statements.present?
  add_table_options!(create_sql, o)
  create_sql << " AS #{to_sql(o.as)}" if o.as
  create_sql
end