Class: ActiveRecord::ConnectionAdapters::MysqlAdapter

Inherits:
AbstractMysqlAdapter show all
Defined in:
activerecord/lib/active_record/connection_adapters/mysql_adapter.rb

Overview

The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with the faster C-based MySQL/Ruby adapter (available both as a gem and from www.tmtm.org/en/mysql/ruby/).

Options:

  • :host - Defaults to “localhost”.

  • :port - Defaults to 3306.

  • :socket - Defaults to “/tmp/mysql.sock”.

  • :username - Defaults to “root”

  • :password - Defaults to nothing.

  • :database - The name of the database. No default, must be provided.

  • :encoding - (Optional) Sets the client encoding by executing “SET NAMES <encoding>” after connection.

  • :reconnect - Defaults to false (See MySQL documentation: dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html).

  • :strict - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: dev.mysql.com/doc/refman/5.0/en/sql-mode.html)

  • :variables - (Optional) A hash session variables to send as SET @@SESSION.key = value on each database connection. Use the value :default to set a variable to its DEFAULT value. (See MySQL documentation: dev.mysql.com/doc/refman/5.0/en/set-statement.html).

  • :sslca - Necessary to use MySQL with an SSL connection.

  • :sslkey - Necessary to use MySQL with an SSL connection.

  • :sslcert - Necessary to use MySQL with an SSL connection.

  • :sslcapath - Necessary to use MySQL with an SSL connection.

  • :sslcipher - Necessary to use MySQL with an SSL connection.

Defined Under Namespace

Modules: Fields Classes: StatementPool

Constant Summary collapse

ADAPTER_NAME =
'MySQL'.freeze
ENCODINGS =

Taken from here:

https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb

Author: TOMITA Masahiro <[email protected]>

{
  "armscii8" => nil,
  "ascii"    => Encoding::US_ASCII,
  "big5"     => Encoding::Big5,
  "binary"   => Encoding::ASCII_8BIT,
  "cp1250"   => Encoding::Windows_1250,
  "cp1251"   => Encoding::Windows_1251,
  "cp1256"   => Encoding::Windows_1256,
  "cp1257"   => Encoding::Windows_1257,
  "cp850"    => Encoding::CP850,
  "cp852"    => Encoding::CP852,
  "cp866"    => Encoding::IBM866,
  "cp932"    => Encoding::Windows_31J,
  "dec8"     => nil,
  "eucjpms"  => Encoding::EucJP_ms,
  "euckr"    => Encoding::EUC_KR,
  "gb2312"   => Encoding::EUC_CN,
  "gbk"      => Encoding::GBK,
  "geostd8"  => nil,
  "greek"    => Encoding::ISO_8859_7,
  "hebrew"   => Encoding::ISO_8859_8,
  "hp8"      => nil,
  "keybcs2"  => nil,
  "koi8r"    => Encoding::KOI8_R,
  "koi8u"    => Encoding::KOI8_U,
  "latin1"   => Encoding::ISO_8859_1,
  "latin2"   => Encoding::ISO_8859_2,
  "latin5"   => Encoding::ISO_8859_9,
  "latin7"   => Encoding::ISO_8859_13,
  "macce"    => Encoding::MacCentEuro,
  "macroman" => Encoding::MacRoman,
  "sjis"     => Encoding::SHIFT_JIS,
  "swe7"     => nil,
  "tis620"   => Encoding::TIS_620,
  "ucs2"     => Encoding::UTF_16BE,
  "ujis"     => Encoding::EucJP_ms,
  "utf8"     => Encoding::UTF_8,
  "utf8mb4"  => Encoding::UTF_8,
}

Constants inherited from AbstractMysqlAdapter

AbstractMysqlAdapter::INDEX_TYPES, AbstractMysqlAdapter::INDEX_USINGS, AbstractMysqlAdapter::LOST_CONNECTION_ERROR_MESSAGES, AbstractMysqlAdapter::NATIVE_DATABASE_TYPES

Constants inherited from AbstractAdapter

AbstractAdapter::SIMPLE_INT

Constants included from ActiveSupport::Callbacks

ActiveSupport::Callbacks::CALLBACK_FILTER_TYPES

Instance Attribute Summary

Attributes inherited from AbstractAdapter

#logger, #owner, #pool, #prepared_statements, #schema_cache, #visitor

Attributes included from QueryCache

#query_cache, #query_cache_enabled

Attributes included from DatabaseStatements

#transaction_manager

Instance Method Summary collapse

Methods inherited from AbstractMysqlAdapter

#_quote, #add_index, #begin_isolated_db_transaction, #bulk_change_table, #case_insensitive_comparison, #case_sensitive_comparison, #case_sensitive_modifier, #change_column, #change_column_default, #change_column_null, #charset, #collation, #columns, #columns_for_distinct, #commit_db_transaction, #create_database, #create_table, #current_database, #disable_referential_integrity, #drop_database, #drop_table, #empty_insert_statement_value, #emulate_booleans, #exec_rollback_db_transaction, #execute, #foreign_keys, #index_algorithms, #indexes, #join_to_update, #native_database_types, #new_column, #pk_and_sequence_for, #prepare_column_options, #primary_key, #quote_column_name, #quote_table_name, #quoted_date, #quoted_false, #quoted_true, #recreate_database, #rename_column, #rename_index, #rename_table, #schema_creation, #show_variable, #strict_mode?, #supports_bulk_alter?, #supports_datetime_with_precision?, #supports_foreign_keys?, #supports_index_sort_order?, #supports_indexes_in_create?, #supports_migrations?, #supports_primary_key?, #supports_transaction_isolation?, #supports_views?, #table_exists?, #tables, #truncate, #type_to_sql, #unquoted_false, #unquoted_true, #update_sql, #valid_type?

Methods included from Savepoints

#create_savepoint, #exec_rollback_to_savepoint, #release_savepoint, #supports_savepoints?

Methods inherited from AbstractAdapter

#adapter_name, #case_insensitive_comparison, #case_sensitive_comparison, #case_sensitive_modifier, #close, #collector, #column_name_for_operation, #create_savepoint, #current_savepoint_name, #disable_extension, #disable_referential_integrity, #enable_extension, #expire, #extensions, #index_algorithms, #lease, #lookup_cast_type, #new_column, #prefetch_primary_key?, #raw_connection, #release_savepoint, #requires_reloading?, #schema_creation, #substitute_at, #supports_bulk_alter?, #supports_ddl_transactions?, #supports_explain?, #supports_extensions?, #supports_foreign_keys?, #supports_index_sort_order?, #supports_indexes_in_create?, #supports_migrations?, #supports_partial_index?, #supports_primary_key?, #supports_savepoints?, #supports_transaction_isolation?, #supports_views?, type_cast_config_to_boolean, type_cast_config_to_integer, #type_map, #unprepared_statement, #valid_type?, #verify!

Methods included from ColumnDumper

#column_spec, #migration_keys, #prepare_column_options

Methods included from ActiveSupport::Callbacks

#run_callbacks

Methods included from ActiveSupport::Concern

#append_features, #class_methods, extended, #included

Methods included from QueryCache

#cache, #clear_query_cache, dirties_query_cache, #disable_query_cache!, #enable_query_cache!, included, #select_all, #uncached

Methods included from DatabaseLimits

#allowed_index_name_length, #column_name_length, #columns_per_multicolumn_index, #columns_per_table, #in_clause_length, #index_name_length, #indexes_per_table, #joins_per_query, #sql_query_length, #table_alias_length, #table_name_length

Methods included from Quoting

#quote, #quote_column_name, #quote_table_name, #quote_table_name_for_assignment, #quoted_date, #quoted_false, #quoted_true, #type_cast, #unquoted_false, #unquoted_true

Methods included from DatabaseStatements

#add_transaction_record, #begin_isolated_db_transaction, #cacheable_query, #commit_db_transaction, #default_sequence_name, #delete, #empty_insert_statement_value, #exec_insert, #exec_rollback_db_transaction, #exec_rollback_to_savepoint, #execute, #insert, #insert_fixture, #join_to_delete, #join_to_update, #reset_sequence!, #reset_transaction, #rollback_db_transaction, #rollback_to_savepoint, #sanitize_limit, #select_all, #select_one, #select_value, #select_values, #to_sql, #transaction, #transaction_isolation_levels, #transaction_open?, #transaction_state, #truncate, #update

Methods included from SchemaStatements

#add_column, #add_foreign_key, #add_index, #add_index_options, #add_reference, #add_timestamps, #assume_migrated_upto_version, #change_column, #change_column_default, #change_column_null, #change_table, #column_exists?, #columns, #columns_for_distinct, #create_join_table, #create_table, #data_source_exists?, #data_sources, #drop_join_table, #drop_table, #dump_schema_information, #foreign_key_column_for, #foreign_keys, #index_exists?, #index_name, #index_name_exists?, #initialize_schema_migrations_table, #native_database_types, #remove_column, #remove_columns, #remove_foreign_key, #remove_index, #remove_index!, #remove_reference, #remove_timestamps, #rename_column, #rename_index, #rename_table, #table_alias_for, #table_exists?, #type_to_sql, #update_table_definition

Methods included from TimestampDefaultDeprecation

#emit_warning_if_null_unspecified

Constructor Details

#initialize(connection, logger, connection_options, config) ⇒ MysqlAdapter


103
104
105
106
107
108
109
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 103

def initialize(connection, logger, connection_options, config)
  super
  @statements = StatementPool.new(@connection,
                                  self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
  @client_encoding = nil
  connect
end

Instance Method Details

#active?Boolean

– CONNECTION MANAGEMENT ==================================== ++


144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 144

def active?
  if @connection.respond_to?(:stat)
    @connection.stat
  else
    @connection.query 'select 1'
  end

  # mysql-ruby doesn't raise an exception when stat fails.
  if @connection.respond_to?(:errno)
    @connection.errno.zero?
  else
    true
  end
rescue Mysql::Error
  false
end

#begin_db_transactionObject

:nodoc:


397
398
399
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 397

def begin_db_transaction #:nodoc:
  exec_query "BEGIN"
end

#clear_cache!Object

Clears the prepared statements cache.


195
196
197
198
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 195

def clear_cache!
  super
  @statements.clear
end

#client_encodingObject

Get the client encoding for this database


244
245
246
247
248
249
250
251
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 244

def client_encoding
  return @client_encoding if @client_encoding

  result = exec_query(
    "select @@character_set_client",
    'SCHEMA')
  @client_encoding = ENCODINGS[result.rows.last.last]
end

#disconnect!Object

Disconnects from the database if already connected. Otherwise, this method does nothing.


169
170
171
172
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 169

def disconnect!
  super
  @connection.close rescue nil
end

#each_hash(result) ⇒ Object

HELPER METHODS ===========================================


119
120
121
122
123
124
125
126
127
128
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 119

def each_hash(result) # :nodoc:
  if block_given?
    result.each_hash do |row|
      row.symbolize_keys!
      yield row
    end
  else
    to_enum(:each_hash, result)
  end
end

#error_number(exception) ⇒ Object

:nodoc:


130
131
132
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 130

def error_number(exception) # :nodoc:
  exception.errno if exception.respond_to?(:errno)
end

#exec_delete(sql, name, binds) ⇒ Object Also known as: exec_update

:nodoc:


386
387
388
389
390
391
392
393
394
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 386

def exec_delete(sql, name, binds) # :nodoc:
  affected_rows = 0

  exec_query(sql, name, binds) do |n|
    affected_rows = n
  end

  affected_rows
end

#exec_query(sql, name = 'SQL', binds = []) {|affected_rows| ... } ⇒ Object

Yields:

  • (affected_rows)

253
254
255
256
257
258
259
260
261
262
263
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 253

def exec_query(sql, name = 'SQL', binds = [])
  if without_prepared_statement?(binds)
    result_set, affected_rows = exec_without_stmt(sql, name)
  else
    result_set, affected_rows = exec_stmt(sql, name, binds)
  end

  yield affected_rows if block_given?

  result_set
end

#exec_without_stmt(sql, name = 'SQL') ⇒ Object

:nodoc:


342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 342

def exec_without_stmt(sql, name = 'SQL') # :nodoc:
  # Some queries, like SHOW CREATE TABLE don't work through the prepared
  # statement API. For those queries, we need to use this method. :'(
  log(sql, name) do
    result = @connection.query(sql)
    affected_rows = @connection.affected_rows

    if result
      types = {}
      fields = []
      result.fetch_fields.each { |field|
        field_name = field.name
        fields << field_name

        if field.decimals > 0
          types[field_name] = Type::Decimal.new
        else
          types[field_name] = Fields.find_type field
        end
      }

      result_set = ActiveRecord::Result.new(fields, result.to_a, types)
      result.free
    else
      result_set = ActiveRecord::Result.new([], [])
    end

    [result_set, affected_rows]
  end
end

#execute_and_free(sql, name = nil) ⇒ Object

:nodoc:


373
374
375
376
377
378
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 373

def execute_and_free(sql, name = nil) # :nodoc:
  result = execute(sql, name)
  ret = yield result
  result.free
  ret
end

#initialize_type_map(m) ⇒ Object

:nodoc:


333
334
335
336
337
338
339
340
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 333

def initialize_type_map(m) # :nodoc:
  super
  m.register_type %r(time)i,     Fields::Time.new
  m.register_type(%r(datetime)i) do |sql_type|
    precision = extract_precision(sql_type)
    Fields::DateTime.new(precision: precision)
  end
end

#insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) ⇒ Object Also known as: create

:nodoc:


380
381
382
383
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 380

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
  super sql, name
  id_value || @connection.insert_id
end

#last_inserted_id(result) ⇒ Object


265
266
267
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 265

def last_inserted_id(result)
  @connection.insert_id
end

#quote_string(string) ⇒ Object

QUOTING ==================================================


136
137
138
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 136

def quote_string(string) #:nodoc:
  @connection.quote(string)
end

#reconnect!Object


161
162
163
164
165
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 161

def reconnect!
  super
  disconnect!
  connect
end

#reset!Object


174
175
176
177
178
179
180
181
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 174

def reset!
  if @connection.respond_to?(:change_user)    # See http://bugs.mysql.com/bug.php?id=33540 -- the workaround way to
    # reset the connection is to change the user to the same user.

    @connection.change_user(@config[:username], @config[:password], @config[:database])
    configure_connection
  end
end

#select_rows(sql, name = nil, binds = []) ⇒ Object

– DATABASE STATEMENTS ====================================== ++


187
188
189
190
191
192
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 187

def select_rows(sql, name = nil, binds = [])
  @connection.query_with_result = true
  rows = exec_query(sql, name, binds).rows
  @connection.more_results && @connection.next_result    # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
  rows
end

#supports_statement_cache?Boolean

Returns true, since this connection adapter supports prepared statement caching.


113
114
115
# File 'activerecord/lib/active_record/connection_adapters/mysql_adapter.rb', line 113

def supports_statement_cache?
  true
end