- A
- B
- C
- E
- I
- L
- N
- P
- Q
- R
- S
- T
- V
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) DEFAULT NULL 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" }, :timestamp => { :name => "datetime" }, :time => { :name => "time" }, :date => { :name => "date" }, :binary => { :name => "blob" }, :boolean => { :name => "tinyint", :limit => 1 } } |
INDEX_TYPES | = | [:fulltext, :spatial] |
INDEX_USINGS | = | [:btree, :hash] |
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
FIXME: Make the first parameter more similar for the two adapters
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 162 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
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 315 def begin_isolated_db_transaction(isolation) execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}" begin_db_transaction rescue # Transactions aren't supported end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 498 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 503 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.
Returns the database collation strategy.
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 380 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
Executes the SQL statement in the context of this connection.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 283 def execute(sql, name = nil) if name == :skip_logging @connection.query(sql) else log(sql, name) { @connection.query(sql) } end rescue ActiveRecord::StatementInvalid => exception if exception.message.split(":").first =~ /Packets out of order/ raise ActiveRecord::StatementInvalid.new("'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings.", exception.original_exception) else raise end end
Returns a table's primary key and belonging sequence.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 574 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
QUOTING ==================================================
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 240 def quote(value, column = nil) if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) s = column.class.string_to_binary(value).unpack("H*")[0] "x'#{s}'" elsif value.kind_of?(BigDecimal) value.to_s("F") else super end end
Drops the database specified on the name
attribute and creates
it again using the provided options
.
Renames a table.
Example:
rename_table('octopuses', 'octopi')
SHOW VARIABLES LIKE 'name'
Technically MySQL allows to create indexes with the sort order syntax but at the moment (5.5) it doesn't yet implement them
Returns true, since this connection adapter supports migrations.
Returns true, since this connection adapter supports savepoints.
MySQL 4 technically support transaction isolation, but it is affected by a bug where the transaction level gets persisted for the whole session:
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 420 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
Maps logical Rails types to MySQL-specific data types.
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 528 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 665 def add_column_sql(table_name, column_name, type, options = {}) add_column_sql = "ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" add_column_options!(add_column_sql, options) add_column_position!(add_column_sql, options) add_column_sql end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 629 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 714 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 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 change_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" add_column_options!(change_column_sql, options) add_column_position!(change_column_sql, options) change_column_sql end
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 642 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 689 def rename_column_sql(table_name, column_name, new_column_name) options = {} 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"] rename_column_sql = "CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}" add_column_options!(rename_column_sql, options) rename_column_sql 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 620 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 654 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