class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
Constants
- INDEX_TYPES
- INDEX_USINGS
- LOST_CONNECTION_ERROR_MESSAGES
- NATIVE_DATABASE_TYPES
- QUOTED_FALSE
Public Class Methods
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 141 class_attribute :emulate_booleans
FIXME: Make the first parameter more similar for the two adapters
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 175 def initialize(connection, logger, connection_options, config) super(connection, logger) @connection_options, @config = connection_options, config @quoted_column_names, @quoted_table_names = {}, {} if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true }) @prepared_statements = true @visitor = Arel::Visitors::MySQL.new self else @visitor = unprepared_visitor end end
Public Instance Methods
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 560 def add_column_position!(sql, options) if options[:first] sql << " FIRST" elsif options[:after] sql << " AFTER #{quote_column_name(options[:after])}" end end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 318 def begin_db_transaction execute "BEGIN" end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 322 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 597 def case_insensitive_comparison(table, attribute, column, value) if column.case_sensitive? super else table[attribute].eq(value) end end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 593 def case_sensitive_modifier(node) Arel::Nodes::Bin.new(node) end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 499 def change_column_default(table_name, column_name, default) column = column_for(table_name, column_name) change_column table_name, column_name, column.sql_type, :default => default end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 504 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
Returns the database character set.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 390 def charset show_variable 'character_set_database' end
Returns the database collation strategy.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 395 def collation show_variable 'collation_database' end
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 369 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 385 def current_database select_value 'SELECT DATABASE() as db' end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 487 def drop_table(table_name, options = {}) execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE #{quote_table_name(table_name)}" end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 347 def empty_insert_statement_value "VALUES ()" end
Executes the SQL statement in the context of this connection.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 302 def execute(sql, name = nil) log(sql, name) { @connection.query(sql) } end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 234 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 605 def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) where_sql end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 230 def native_database_types NATIVE_DATABASE_TYPES end
Returns a table's primary key and belonging sequence.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 575 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
Returns just a table's primary key
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 588 def primary_key(table) pk_and_sequence = pk_and_sequence_for(table) pk_and_sequence && pk_and_sequence.first end
QUOTING ==================================================
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 259 def quote(value, column = nil) if value.kind_of?(String) && column && column.type == :binary s = value.unpack("H*")[0] "x'#{s}'" elsif value.kind_of?(BigDecimal) value.to_s("F") else super end end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 282 def quoted_false QUOTED_FALSE end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 278 def quoted_true QUOTED_TRUE end
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 355 def recreate_database(name, options = {}) drop_database(name) sql = create_database(name, options) reconnect! sql end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 491 def rename_index(table_name, old_name, new_name) if supports_rename_index? 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
Renames a table.
Example:
rename_table('octopuses', 'octopi')
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 482 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 34 def schema_creation SchemaCreation.new self end
SHOW VARIABLES LIKE 'name'
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 569 def show_variable(name) variables = select_all("SHOW VARIABLES LIKE '#{name}'", 'SCHEMA') variables.first['Value'] unless variables.empty? end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 609 def strict_mode? self.class.type_cast_config_to_boolean(@config.fetch(:strict, true)) end
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 207 def supports_index_sort_order? true end
Returns true, since this connection adapter supports migrations.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 193 def supports_migrations? true end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 197 def supports_primary_key? true end
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 226 def supports_transaction_isolation? version[0] >= 5 end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 409 def table_exists?(name) return false unless name 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 211 def type_cast(value, column) case value when TrueClass 1 when FalseClass 0 else super end end
Maps logical Rails types to MySQL-specific data types.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 529 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 else super end end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 613 def valid_type?(type) !native_database_types[type].nil? end
Protected Instance Methods
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 666 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 630 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 710 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 720 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 672 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 643 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 702 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 706 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 715 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 724 def remove_timestamps_sql(table_name) [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 687 def rename_column_sql(table_name, column_name, new_column_name) options = { name: new_column_name } if column = columns(table_name).find { |c| c.name == column_name.to_s } options[:default] = column.default options[:null] = column.null options[:auto_increment] = (column.extra == "auto_increment") else raise ActiveRecordError, "No such column: #{table_name}.#{column_name}" end 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
MySQL is too stupid to create a temporary table for use subquery, so we have to give it some prompting in the form of a subsubquery. Ugh!
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 621 def subquery_for(key, select) subsubselect = select.clone subsubselect.projections = [key] subselect = Arel::SelectManager.new(select.engine) subselect.project Arel.sql(key.name) subselect.from subsubselect.as('__active_record_temp') end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 655 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
© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.