Spec-Zone.ru › Ruby on Rails 4.2

class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter

Parent:
ActiveRecord::ConnectionAdapters::AbstractAdapter

Константы

INDEX_TYPES
INDEX_USINGS
LOST_CONNECTION_ERROR_MESSAGES
NATIVE_DATABASE_TYPES
QUOTED_FALSE

Публичные методы класса

emulate_booleans() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 139
class_attribute :emulate_booleans

По умолчанию, MysqlAdapter будет рассматривать все столбцы типа tinyint(1) как булевы. Если вы хотите отключить эту эмуляцию (что было по умолчанию в версиях 0.13.1 и ранее), вы можете добавить следующую строку в свой файл application.rb:

ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans = false
new(connection, logger, connection_options, config) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 168
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

FIXME: Сделать первый параметр более похожим для двух адаптеров

Вызывает метод суперкласса ActiveRecord::ConnectionAdapters::QueryCache.new

Публичные методы экземпляра

begin_db_transaction() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 332
def begin_db_transaction
  execute "BEGIN"
end
begin_isolated_db_transaction(isolation) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 336
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 659
def case_insensitive_comparison(table, attribute, column, value)
  if column.case_sensitive?
    super
  else
    table[attribute].eq(value)
  end
end
Вызов метода суперкласса ActiveRecord::ConnectionAdapters::AbstractAdapter#case_insensitive_comparison
case_sensitive_comparison(table, attribute, column, value) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 651
def case_sensitive_comparison(table, attribute, column, value)
  if column.case_sensitive?
    table[attribute].eq(value)
  else
    super
  end
end
Вызов метода суперкласса ActiveRecord::ConnectionAdapters::AbstractAdapter#case_sensitive_comparison
case_sensitive_modifier(node, table_attribute) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 646
def case_sensitive_modifier(node, table_attribute)
  node = Arel::Nodes.build_quoted node, table_attribute
  Arel::Nodes::Bin.new(node)
end
change_column_null(table_name, column_name, null, default = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 528
def change_column_null(table_name, column_name, null, default = nil)
  column = column_for(table_name, column_name)

  unless null || default.nil?
    execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
  end

  change_column table_name, column_name, column.sql_type, :null => null
end
charset() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 404
def charset
  show_variable 'character_set_database'
end

Возвращает кодировку символов базы данных.

clear_cache!() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 310
def clear_cache!
  super
  reload_type_map
end
Вызов метода суперкласса ActiveRecord::ConnectionAdapters::AbstractAdapter#clear_cache!
collation() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 409
def collation
  show_variable 'collation_database'
end

Возвращает стратегию сортировки базы данных.

create_database(name, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 383
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

Создаёт новую базу данных MySQL с опциональными :charset и :collation. Кодировка по умолчанию utf8.

Пример:

create_database 'charset_test', charset: 'latin1', collation: 'latin1_bin'
create_database 'matt_development'
create_database 'matt_development', charset: :big5
current_database() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 399
def current_database
  select_value 'SELECT DATABASE() as db'
end
data_source_exists?(name)
Псевдоним для: table_exists?
drop_table(table_name, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 509
def drop_table(table_name, options = {})
  execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE #{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 361
def empty_insert_statement_value
  "VALUES ()"
end
execute(sql, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 316
def execute(sql, name = nil)
  log(sql, name) { @connection.query(sql) }
end

Выполняет SQL-запрос в контексте этого соединения.

foreign_keys(table_name) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 552
      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 229
def index_algorithms
  { default: 'ALGORITHM = DEFAULT', copy: 'ALGORITHM = COPY', inplace: 'ALGORITHM = INPLACE' }
end
native_database_types() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 225
def native_database_types
  NATIVE_DATABASE_TYPES
end
pk_and_sequence_for(table) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 628
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) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 641
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 285
def quoted_date(value)
  if supports_datetime_with_precision? && value.acts_like?(:time) && value.respond_to?(:usec)
    "#{super}.#{sprintf("%06d", value.usec)}"
  else
    super
  end
end
Вызов метода суперкласса ActiveRecord::ConnectionAdapters::Quoting#quoted_date
quoted_false() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 277
def quoted_false
  QUOTED_FALSE
end
quoted_true() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 269
def quoted_true
  QUOTED_TRUE
end
recreate_database(name, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 369
def recreate_database(name, options = {})
  drop_database(name)
  sql = create_database(name, options)
  reconnect!
  sql
end

Удаляет базу данных, указанную в атрибуте name, и создаёт её заново, используя предоставленные options.

rename_index(table_name, old_name, new_name) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 513
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
Вызов метода суперкласса ActiveRecord::ConnectionAdapters::SchemaStatements#rename_index
rename_table(table_name, new_name) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 504
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

Переименовывает таблицу.

Пример:

rename_table('octopuses', 'octopi')
END_OF_DOCUMENT_MARKER
schema_creation() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 57
def schema_creation
  SchemaCreation.new self
end
show_variable(name) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 620
def show_variable(name)
  variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
  variables.first['Value'] unless variables.empty?
rescue ActiveRecord::StatementInvalid
  nil
end

ПОКАЗАТЬ ПЕРЕМЕННЫЕ, ТАКИЕ КАК 'name'

strict_mode?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 682
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 221
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 213
def supports_foreign_keys?
  true
end
supports_index_sort_order?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 197
def supports_index_sort_order?
  true
end

Технически MySQL позволяет создавать индексы с синтаксисом порядка сортировки, но в настоящее время (5.5) они ещё не реализованы

supports_indexes_in_create?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 209
def supports_indexes_in_create?
  true
end
supports_migrations?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 183
def supports_migrations?
  true
end

Возвращает true, так как этот адаптер соединения поддерживает миграции.

supports_primary_key?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 187
def supports_primary_key?
  true
end
supports_transaction_isolation?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 205
def supports_transaction_isolation?
  version >= '5.0.0'
end

MySQL 4 технически поддерживает изоляцию транзакций, но она подвержена ошибке, где уровень транзакции сохраняется для всей сессии:

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

supports_views?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 217
def supports_views?
  version >= '5.0.0'
end
table_exists?(name) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 428
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
Также переименовано как: data_source_exists?
truncate(table_name, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 424
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) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 581
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  case type.to_s
  when 'binary'
    case limit
    when 0..0xfff;           "varbinary(#{limit})"
    when nil;                "blob"
    when 0x1000..0xffffffff; "blob(#{limit})"
    else raise(ActiveRecordError, "No binary type has character length #{limit}")
    end
  when 'integer'
    case limit
    when 1; 'tinyint'
    when 2; 'smallint'
    when 3; 'mediumint'
    when nil, 4, 11; 'int(11)'  # compatibility with MySQL default
    when 5..8; 'bigint'
    else raise(ActiveRecordError, "No integer type has byte size #{limit}")
    end
  when 'text'
    case limit
    when 0..0xff;               'tinytext'
    when nil, 0x100..0xffff;    'text'
    when 0x10000..0xffffff;     'mediumtext'
    when 0x1000000..0xffffffff; 'longtext'
    else raise(ActiveRecordError, "No text type has character length #{limit}")
    end
  when 'datetime'
    return super unless precision

    case precision
      when 0..6; "datetime(#{precision})"
      else raise(ActiveRecordError, "No datetime type has precision of #{precision}. The allowed range of precision is from 0 to 6.")
    end
  else
    super
  end
end

Преобразует логические типы Rails в специфичные для MySQL типы данных.

Вызывает метод родительского класса
unquoted_false() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 281
def unquoted_false
  0
end
unquoted_true() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 273
def unquoted_true
  1
end
valid_type?(type) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 686
def valid_type?(type)
  !native_database_types[type].nil?
end
END_OF_DOCUMENT_MARKER

Защищенные методы экземпляра

add_column_sql(table_name, column_name, type, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 792
def add_column_sql(table_name, column_name, type, options = {})
  td = create_table_definition table_name, options[:temporary], options[:options]
  cd = td.new_column_definition(column_name, type, options)
  schema_creation.visit_AddColumn cd
end
add_index_length(option_strings, column_names, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 756
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 Integer
      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 834
def add_index_sql(table_name, column_name, options = {})
  index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
  "ADD #{index_type} INDEX #{index_name} (#{index_columns})"
end
add_timestamps_sql(table_name, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 844
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 798
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

  options[:name] = column.name
  schema_creation.accept ChangeColumnDefinition.new column, type, options
end
quoted_columns_for_index(column_names, options = {}) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 769
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 826
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 830
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 839
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 848
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 813
def rename_column_sql(table_name, column_name, new_column_name)
  column  = column_for(table_name, column_name)
  options = {
    name: new_column_name,
    default: column.default,
    null: column.null,
    auto_increment: column.extra == "auto_increment"
  }

  current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'", 'SCHEMA')["Type"]
  schema_creation.accept ChangeColumnDefinition.new column, current_type, options
end
subquery_for(key, select) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 743
def subquery_for(key, select)
  subsubselect = select.clone
  subsubselect.projections = [key]

  # Materialize subquery by adding distinct
  # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
  subsubselect.distinct unless select.limit || select.offset || select.orders.any?

  subselect = Arel::SelectManager.new(select.engine)
  subselect.project Arel.sql(key.name)
  subselect.from subsubselect.as('__active_record_temp')
end

MySQL слишком глуп, чтобы создавать временную таблицу для использования подзапроса, поэтому мы должны подсказать ему в виде подподзапроса. Фу!

translate_exception(exception, message) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 781
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
Вызывает метод суперкласса ActiveRecord::ConnectionAdapters::AbstractAdapter#translate_exception

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API