edge badge
Namespace
Methods
A
B
C
D
E
F
I
N
P
Q
R
S
T
U
V
Constants
LOST_CONNECTION_ERROR_MESSAGES = [ "Server shutdown in progress", "Broken pipe", "Lost connection to MySQL server during query", "MySQL server has gone away" ]
 
QUOTED_FALSE = '1', '0'
 
NATIVE_DATABASE_TYPES = { primary_key: "int(11) auto_increment PRIMARY KEY", string: { name: "varchar", limit: 255 }, text: { name: "text" }, integer: { name: "int", limit: 4 }, float: { name: "float" }, decimal: { name: "decimal" }, datetime: { name: "datetime" }, time: { name: "time" }, date: { name: "date" }, binary: { name: "blob" }, boolean: { name: "tinyint", limit: 1 }, bigint: { name: "bigint" }, json: { name: "json" }, }
 
INDEX_TYPES = [:fulltext, :spatial]
 
INDEX_USINGS = [:btree, :hash]
 
MAX_INDEX_LENGTH_FOR_CHARSETS_OF_4BYTES_MAXLEN = 191
 
CHARSETS_OF_4BYTES_MAXLEN = ['utf8mb4', 'utf16', 'utf16le', 'utf32']
 
Class Public methods
emulate_booleans

By default, the MysqlAdapter will consider all columns of type tinyint(1) as boolean. If you wish to disable this emulation (which was the default behavior in versions 0.13.1 and earlier) you can add the following line to your application.rb file:

ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans = false
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 237
class_attribute :emulate_booleans
new(connection, logger, connection_options, config)

FIXME: Make the first parameter more similar for the two adapters

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 268
def initialize(connection, logger, connection_options, config)
  super(connection, logger)
  @connection_options, @config = connection_options, config
  @quoted_column_names, @quoted_table_names = {}, {}

  @visitor = Arel::Visitors::MySQL.new self

  if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
    @prepared_statements = true
  else
    @prepared_statements = false
  end
end
Instance Public methods
begin_db_transaction()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 442
def begin_db_transaction
  execute "BEGIN"
end
begin_isolated_db_transaction(isolation)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 446
def begin_isolated_db_transaction(isolation)
  execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
  begin_db_transaction
end
case_insensitive_comparison(table, attribute, column, value)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 768
def case_insensitive_comparison(table, attribute, column, value)
  if column.case_sensitive?
    super
  else
    table[attribute].eq(value)
  end
end
case_sensitive_comparison(table, attribute, column, value)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 760
def case_sensitive_comparison(table, attribute, column, value)
  if column.case_sensitive?
    table[attribute].eq(value)
  else
    super
  end
end
case_sensitive_modifier(node, table_attribute)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 755
def case_sensitive_modifier(node, table_attribute)
  node = Arel::Nodes.build_quoted node, table_attribute
  Arel::Nodes::Bin.new(node)
end
charset()

Returns the database character set.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 514
def charset
  show_variable 'character_set_database'
end
clear_cache!()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 420
def clear_cache!
  super
  reload_type_map
end
collation()

Returns the database collation strategy.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 519
def collation
  show_variable 'collation_database'
end
column_spec_for_primary_key(column)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 116
def column_spec_for_primary_key(column)
  spec = {}
  if column.auto_increment?
    spec[:id] = ':bigint' if column.bigint?
    return if spec.empty?
  else
    spec[:id] = column.type.inspect
    spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) })
  end
  spec
end
create_database(name, options = {})

Create a new MySQL database with optional :charset and :collation. Charset defaults to utf8.

Example:

create_database 'charset_test', charset: 'latin1', collation: 'latin1_bin'
create_database 'matt_development'
create_database 'matt_development', charset: :big5
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 493
def create_database(name, options = {})
  if options[:collation]
    execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`"
  else
    execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`"
  end
end
current_database()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 509
def current_database
  select_value 'SELECT DATABASE() as db'
end
drop_table(table_name, options = {})

Drops a table from the database.

:force

Set to :cascade to drop dependent objects as well. Defaults to false.

:if_exists

Set to true to only drop the table if it exists. Defaults to false.

:temporary

Set to true to drop temporary table. Defaults to false.

Although this command ignores most options and the block if one is given, it can be helpful to provide these in a migration's change method so it can be reverted. In that case, options and the block will be used by create_table.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 632
def drop_table(table_name, options = {})
  execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
end
empty_insert_statement_value()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 471
def empty_insert_statement_value
  "VALUES ()"
end
execute(sql, name = nil)

Executes the SQL statement in the context of this connection.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 426
def execute(sql, name = nil)
  log(sql, name) { @connection.query(sql) }
end
foreign_keys(table_name)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 676
      def foreign_keys(table_name)
        fk_info = select_all "          SELECT fk.referenced_table_name as 'to_table'
                ,fk.referenced_column_name as 'primary_key'
                ,fk.column_name as 'column'
                ,fk.constraint_name as 'name'
          FROM information_schema.key_column_usage fk
          WHERE fk.referenced_column_name is not null
            AND fk.table_schema = '#{@config[:database]}'
            AND fk.table_name = '#{table_name}'
".strip_heredoc

        create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]

        fk_info.map do |row|
          options = {
            column: row['column'],
            name: row['name'],
            primary_key: row['primary_key']
          }

          options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE")
          options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE")

          ForeignKeyDefinition.new(table_name, row['to_table'], options)
        end
      end
index_algorithms()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 339
def index_algorithms
  { default: 'ALGORITHM = DEFAULT', copy: 'ALGORITHM = COPY', inplace: 'ALGORITHM = INPLACE' }
end
initialize_schema_migrations_table()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 284
def initialize_schema_migrations_table
  if CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
    ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_CHARSETS_OF_4BYTES_MAXLEN)
  else
    ActiveRecord::SchemaMigration.create_table
  end
end
native_database_types()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 335
def native_database_types
  NATIVE_DATABASE_TYPES
end
pk_and_sequence_for(table)

Returns a table's primary key and belonging sequence.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 737
def pk_and_sequence_for(table)
  execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result|
    create_table = each_hash(result).first[:"Create Table"]
    if create_table.to_s =~ /PRIMARY KEY\s+(?:USING\s+\w+\s+)?\((.+)\)/
      keys = $1.split(",").map { |key| key.delete('`"') }
      keys.length == 1 ? [keys.first, nil] : nil
    else
      nil
    end
  end
end
primary_key(table)

Returns just a table's primary key

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 750
def primary_key(table)
  pk_and_sequence = pk_and_sequence_for(table)
  pk_and_sequence && pk_and_sequence.first
end
quoted_date(value)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 395
def quoted_date(value)
  if supports_datetime_with_precision?
    super
  else
    super.sub(/\.\d{6}\z/, '')
  end
end
quoted_false()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 387
def quoted_false
  QUOTED_FALSE
end
quoted_true()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 379
def quoted_true
  QUOTED_TRUE
end
recreate_database(name, options = {})

Drops the database specified on the name attribute and creates it again using the provided options.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 479
def recreate_database(name, options = {})
  drop_database(name)
  sql = create_database(name, options)
  reconnect!
  sql
end
rename_index(table_name, old_name, new_name)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 636
def rename_index(table_name, old_name, new_name)
  if supports_rename_index?
    validate_index_length!(table_name, new_name)

    execute "ALTER TABLE #{quote_table_name(table_name)} RENAME INDEX #{quote_table_name(old_name)} TO #{quote_table_name(new_name)}"
  else
    super
  end
end
rename_table(table_name, new_name)

Renames a table.

Example:

rename_table('octopuses', 'octopi')
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 612
def rename_table(table_name, new_name)
  execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
  rename_table_indexes(table_name, new_name)
end
schema_creation()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 112
def schema_creation
  SchemaCreation.new self
end
show_variable(name)

SHOW VARIABLES LIKE 'name'

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 729
def show_variable(name)
  variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
  variables.first['Value'] unless variables.empty?
rescue ActiveRecord::StatementInvalid
  nil
end
strict_mode?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 776
def strict_mode?
  self.class.type_cast_config_to_boolean(@config.fetch(:strict, true))
end
supports_datetime_with_precision?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 331
def supports_datetime_with_precision?
  version >= '5.6.4'
end
supports_foreign_keys?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 323
def supports_foreign_keys?
  true
end
supports_index_sort_order?()

Technically MySQL allows to create indexes with the sort order syntax but at the moment (5.5) it doesn't yet implement them

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 307
def supports_index_sort_order?
  true
end
supports_indexes_in_create?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 319
def supports_indexes_in_create?
  true
end
supports_migrations?()

Returns true, since this connection adapter supports migrations.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 293
def supports_migrations?
  true
end
supports_primary_key?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 297
def supports_primary_key?
  true
end
supports_transaction_isolation?()

MySQL 4 technically support transaction isolation, but it is affected by a bug where the transaction level gets persisted for the whole session:

bugs.mysql.com/bug.php?id=39170

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 315
def supports_transaction_isolation?
  version >= '5.0.0'
end
supports_views?()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 327
def supports_views?
  version >= '5.0.0'
end
table_exists?(name)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 537
def table_exists?(name)
  return false unless name.present?
  return true if tables(nil, nil, name).any?

  name          = name.to_s
  schema, table = name.split('.', 2)

  unless table # A table was provided without a schema
    table  = schema
    schema = nil
  end

  tables(nil, schema, table).any?
end
table_options(table_name)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 704
def table_options(table_name)
  create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]

  # strip create_definitions and partition_options
  raw_table_options = create_table_info.sub(/\A.*\n\) /m, '').sub(/\n\/\*!.*\*\/\n\z/m, '').strip

  # strip AUTO_INCREMENT
  raw_table_options.sub(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
end
truncate(table_name, name = nil)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 533
def truncate(table_name, name = nil)
  execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
end
type_to_sql(type, limit = nil, precision = nil, scale = nil)

Maps logical Rails types to MySQL-specific data types.

# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 715
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  case type.to_s
  when 'binary'
    binary_to_sql(limit)
  when 'integer'
    integer_to_sql(limit)
  when 'text'
    text_to_sql(limit)
  else
    super
  end
end
unquoted_false()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 391
def unquoted_false
  0
end
unquoted_true()
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 383
def unquoted_true
  1
end
valid_type?(type)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 780
def valid_type?(type)
  !native_database_types[type].nil?
end
Instance Protected methods
add_column_sql(table_name, column_name, type, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 879
def add_column_sql(table_name, column_name, type, options = {})
  td = create_table_definition(table_name)
  cd = td.new_column_definition(column_name, type, options)
  schema_creation.accept(AddColumnDefinition.new(cd))
end
add_index_length(option_strings, column_names, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 843
def add_index_length(option_strings, column_names, options = {})
  if options.is_a?(Hash) && length = options[:length]
    case length
    when Hash
      column_names.each {|name| option_strings[name] += "(#{length[name]})" if length.has_key?(name) && length[name].present?}
    when Fixnum
      column_names.each {|name| option_strings[name] += "(#{length})"}
    end
  end

  return option_strings
end
add_index_sql(table_name, column_name, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 923
def add_index_sql(table_name, column_name, options = {})
  index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, options)
  index_algorithm[0, 0] = ", " if index_algorithm.present?
  "ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
end
add_timestamps_sql(table_name, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 934
def add_timestamps_sql(table_name, options = {})
  [add_column_sql(table_name, :created_at, :datetime, options), add_column_sql(table_name, :updated_at, :datetime, options)]
end
change_column_sql(table_name, column_name, type, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 885
def change_column_sql(table_name, column_name, type, options = {})
  column = column_for(table_name, column_name)

  unless options_include_default?(options)
    options[:default] = column.default
  end

  unless options.has_key?(:null)
    options[:null] = column.null
  end

  td = create_table_definition(table_name)
  cd = td.new_column_definition(column.name, type, options)
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
end
extract_precision(sql_type)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 831
def extract_precision(sql_type)
  if /time/ === sql_type
    super || 0
  else
    super
  end
end
fetch_type_metadata(sql_type, extra = "")
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 839
def fetch_type_metadata(sql_type, extra = "")
  MysqlTypeMetadata.new(super(sql_type), extra: extra, strict: strict_mode?)
end
quoted_columns_for_index(column_names, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 856
def quoted_columns_for_index(column_names, options = {})
  option_strings = Hash[column_names.map {|name| [name, '']}]

  # add index length
  option_strings = add_index_length(option_strings, column_names, options)

  # add index sort order
  option_strings = add_index_sort_order(option_strings, column_names, options)

  column_names.map {|name| quote_column_name(name) + option_strings[name]}
end
remove_column_sql(table_name, column_name, type = nil, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 915
def remove_column_sql(table_name, column_name, type = nil, options = {})
  "DROP #{quote_column_name(column_name)}"
end
remove_columns_sql(table_name, *column_names)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 919
def remove_columns_sql(table_name, *column_names)
  column_names.map {|column_name| remove_column_sql(table_name, column_name) }
end
remove_index_sql(table_name, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 929
def remove_index_sql(table_name, options = {})
  index_name = index_name_for_remove(table_name, options)
  "DROP INDEX #{index_name}"
end
remove_timestamps_sql(table_name, options = {})
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 938
def remove_timestamps_sql(table_name, options = {})
  [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)]
end
rename_column_sql(table_name, column_name, new_column_name)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 901
def rename_column_sql(table_name, column_name, new_column_name)
  column  = column_for(table_name, column_name)
  options = {
    default: column.default,
    null: column.null,
    auto_increment: column.auto_increment?
  }

  current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'", 'SCHEMA')["Type"]
  td = create_table_definition(table_name)
  cd = td.new_column_definition(new_column_name, current_type, options)
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
end
translate_exception(exception, message)
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 868
def translate_exception(exception, message)
  case error_number(exception)
  when 1062
    RecordNotUnique.new(message, exception)
  when 1452
    InvalidForeignKey.new(message, exception)
  else
    super
  end
end