класс ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
Константы
- CHARSETS_OF_4BYTES_MAXLEN
- ТИПЫ_ИНДЕКСОВ
- ИСПОЛЬЗОВАНИЯ_ИНДЕКСОВ
- ТИПЫ_ДАННЫХ_БД
Публичные методы класса
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 38 class_attribute :emulate_booleans
По умолчанию, Mysql2Adapter будет рассматривать все столбцы типа tinyint(1) как булевы. Если вы хотите отключить эту эмуляцию, добавьте следующую строку в файл application.rb:
ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 65
def initialize(connection, logger, connection_options, config)
super(connection, logger, config)
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
if version < '5.0.0'
raise "Your version of MySQL (#{version_string}) is too old. Active Record supports MySQL >= 5.0."
end
end Публичные методы экземпляров
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 228 def begin_db_transaction execute "BEGIN" end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 232
def begin_isolated_db_transaction(isolation)
execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
begin_db_transaction
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 616
def case_sensitive_comparison(table, attribute, column, value)
if !value.nil? && column.collation && !column.case_sensitive?
table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
else
super
end
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 300 def charset show_variable 'character_set_database' end
Возвращает наборы символов базы данных.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 198 def clear_cache! reload_type_map @statements.clear end
Очищает кэш подготовленных инструкций.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 305 def collation show_variable 'collation_database' end
Возвращает стратегию сортировки базы данных.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 279
def create_database(name, options = {})
if options[:collation]
execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')} COLLATE #{quote_table_name(options[:collation])}"
else
execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 295 def current_database select_value 'SELECT DATABASE() as db' end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 347
def data_source_exists?(table_name)
return false unless table_name.present?
schema, name = extract_schema_qualified_name(table_name)
sql = "SELECT table_name FROM information_schema.tables "
sql << "WHERE table_schema = #{schema} AND table_name = #{name}"
select_values(sql, 'SCHEMA').any?
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 325 def data_sources sql = "SELECT table_name FROM information_schema.tables " sql << "WHERE table_schema = DATABASE()" select_values(sql, 'SCHEMA') end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 465
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 Удаляет таблицу из базы данных.
-
:force -
Установить в
:cascadeдля удаления зависимых объектов. По умолчанию false. -
:if_exists -
Установить в
trueдля удаления таблицы только в случае её существования. По умолчанию false. -
:temporary -
Установить в
trueдля удаления временной таблицы. По умолчанию false.
Хотя эта команда игнорирует большинство options и блок, если он задан, это может быть полезно для предоставления этих данных в методе миграции change для отката. В этом случае options и блок будут использоваться методом create_table.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 257 def empty_insert_statement_value "VALUES ()" end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 217
def execute(sql, name = nil)
log(sql, name) { @connection.query(sql) }
end Выполняет SQL инструкцию в контексте этого соединения.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 207
def explain(arel, binds = [])
sql = "EXPLAIN #{to_sql(arel, binds)}"
start = Time.now
result = exec_query(sql, 'EXPLAIN', binds)
elapsed = Time.now - start
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 515
def foreign_keys(table_name)
raise ArgumentError unless table_name.present?
schema, name = extract_schema_qualified_name(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',
rc.update_rule AS 'on_update',
rc.delete_rule AS 'on_delete'
FROM information_schema.key_column_usage fk
JOIN information_schema.referential_constraints rc
USING (constraint_schema, constraint_name)
WHERE fk.referenced_column_name IS NOT NULL
AND fk.table_schema = #{schema}
AND fk.table_name = #{name}
AND rc.table_name = #{name}
".strip_heredoc, 'SCHEMA')
fk_info.map do |row|
options = {
column: row['column'],
name: row['name'],
primary_key: row['primary_key']
}
options[:on_update] = extract_foreign_key_action(row['on_update'])
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
ForeignKeyDefinition.new(table_name, row['to_table'], options)
end
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 160
def index_algorithms
{ default: 'ALGORITHM = DEFAULT', copy: 'ALGORITHM = COPY', inplace: 'ALGORITHM = INPLACE' }
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 156 def native_database_types NATIVE_DATABASE_TYPES end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 265
def recreate_database(name, options = {})
drop_database(name)
sql = create_database(name, options)
reconnect!
sql
end Удаляет базу данных, указанную в атрибуте name, и создаёт её заново, используя предоставленные options.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 469
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 445
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')
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 595
def show_variable(name)
select_value("SELECT @@#{name}", 'SCHEMA')
rescue ActiveRecord::StatementInvalid
nil
end SHOW VARIABLES LIKE 'name'
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 644 def strict_mode? self.class.type_cast_config_to_boolean(@config.fetch(:strict, true)) end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 144 def supports_advisory_locks? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 136
def supports_datetime_with_precision?
if mariadb?
version >= '5.3.0'
else
version >= '5.6.4'
end
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 120 def supports_explain? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 128 def supports_foreign_keys? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 112 def supports_index_sort_order? true end
Технически MySQL позволяет создавать индексы с синтаксисом порядка сортировки, но в настоящее время (версия 5.5) они ещё не реализованы.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 124 def supports_indexes_in_create? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 92 def supports_migrations? true end
Возвращает true, так как этот адаптер подключения поддерживает миграции.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 96 def supports_primary_key? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 106 def supports_statement_cache? true end
Возвращает true, так как этот адаптер подключения поддерживает кэширование подготовленных операторов.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 116 def supports_transaction_isolation? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 132 def supports_views? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 336
def table_exists?(table_name)
# Update lib/active_record/internal_metadata.rb when this gets removed
ActiveSupport::Deprecation.warn(" #table_exists? currently checks both tables and views.
This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
Use #data_source_exists? instead.
".squish)
data_source_exists?(table_name)
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 332
def truncate(table_name, name = nil)
execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 572
def type_to_sql(type, limit = nil, precision = nil, scale = nil, unsigned = nil)
sql = case type.to_s
when 'integer'
integer_to_sql(limit)
when 'text'
text_to_sql(limit)
when 'blob'
binary_to_sql(limit)
when 'binary'
if (0..0xfff) === limit
"varbinary(#{limit})"
else
binary_to_sql(limit)
end
else
super(type, limit, precision, scale)
end
sql << ' unsigned' if unsigned && type != :primary_key
sql
end Сопоставляет логические типы Rails с конкретными типами данных MySQL.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 648 def valid_type?(type) !native_database_types[type].nil? end
Защищённые методы экземпляра
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 748
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 716
def add_index_length(quoted_columns, **options)
if length = options[:length]
case length
when Hash
length = length.symbolize_keys
quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
when Integer
quoted_columns.each { |name, column| column << "(#{length})" }
end
end
quoted_columns
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 792
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 730 def add_options_for_index_columns(quoted_columns, **options) quoted_columns = add_index_length(quoted_columns, options) super end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 803
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 754
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 704
def extract_precision(sql_type)
if /time/ === sql_type
super || 0
else
super
end
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 712 def fetch_type_metadata(sql_type, extra = "") MySQL::TypeMetadata.new(super(sql_type), extra: extra, strict: strict_mode?) end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 784
def remove_column_sql(table_name, column_name, type = nil, options = {})
"DROP #{quote_column_name(column_name)}"
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 788
def remove_columns_sql(table_name, *column_names)
column_names.map {|column_name| remove_column_sql(table_name, column_name) }
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 798
def remove_index_sql(table_name, options = {})
index_name = index_name_for_remove(table_name, options)
"DROP INDEX #{index_name}"
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 807
def remove_timestamps_sql(table_name, options = {})
[remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)]
end # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 770
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 # File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 735
def translate_exception(exception, message)
case error_number(exception)
when 1062
RecordNotUnique.new(message)
when 1452
InvalidForeignKey.new(message)
when 1406
ValueTooLong.new(message)
else
super
end
end
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.