Class: ActiveRecord::ConnectionAdapters::MysqlAdapter

Inherits:
AbstractAdapter show all
Defined in:
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).

  • :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

Classes: BindSubstitution, StatementPool

Constant Summary collapse

ADAPTER_NAME =
'MySQL'
LOST_CONNECTION_ERROR_MESSAGES =
[
"Server shutdown in progress",
"Broken pipe",
"Lost connection to MySQL server during query",
"MySQL server has gone away" ]
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 }
}
ENCODINGS =

Taken from here:

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

Author: TOMITA Masahiro <[email protected]>

Hash.new { |h,k| h[k] = k }

Instance Attribute Summary

Attributes inherited from AbstractAdapter

#logger, #visitor

Attributes included from QueryCache

#query_cache, #query_cache_enabled

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractAdapter

#current_savepoint_name, #decrement_open_transactions, #increment_open_transactions, #open_transactions, #prefetch_primary_key?, #raw_connection, #requires_reloading?, #substitute_at, #supports_count_distinct?, #supports_ddl_transactions?, #transaction_joinable=, #verify!

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

#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

#quoted_date

Methods included from DatabaseStatements

#add_transaction_record, #default_sequence_name, #delete, #empty_insert_statement_value, #exec_insert, #insert, #insert_fixture, #outside_transaction?, #reset_sequence!, #sanitize_limit, #select_all, #select_one, #select_value, #select_values, #to_sql, #transaction, #update

Methods included from SchemaStatements

#add_column_options!, #add_index, #add_timestamps, #assume_migrated_upto_version, #change_table, #column_exists?, #distinct, #dump_schema_information, #index_exists?, #index_name, #index_name_exists?, #initialize_schema_migrations_table, #remove_column, #remove_index, #remove_index!, #remove_timestamps, #rename_index, #table_alias_for

Constructor Details

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

Returns a new instance of MysqlAdapter.



221
222
223
224
225
226
227
228
229
230
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 221

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

Class Method Details

.visitor_for(pool) ⇒ Object

:nodoc:



236
237
238
239
240
241
242
243
244
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 236

def self.visitor_for(pool) # :nodoc:
  config = pool.spec.config

  if config.fetch(:prepared_statements) { true }
    Arel::Visitors::MySQL.new pool
  else
    BindSubstitution.new pool
  end
end

Instance Method Details

#active?Boolean

CONNECTION MANAGEMENT ====================================

Returns:

  • (Boolean)


332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 332

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

#adapter_nameObject

:nodoc:



246
247
248
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 246

def adapter_name #:nodoc:
  ADAPTER_NAME
end

#add_column(table_name, column_name, type, options = {}) ⇒ Object



713
714
715
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 713

def add_column(table_name, column_name, type, options = {})
  execute("ALTER TABLE #{quote_table_name(table_name)} #{add_column_sql(table_name, column_name, type, options)}")
end

#add_column_position!(sql, options) ⇒ Object



765
766
767
768
769
770
771
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 765

def add_column_position!(sql, options)
  if options[:first]
    sql << " FIRST"
  elsif options[:after]
    sql << " AFTER #{quote_column_name(options[:after])}"
  end
end

#add_limit_offset!(sql, options) ⇒ Object

:nodoc:



536
537
538
539
540
541
542
543
544
545
546
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 536

def add_limit_offset!(sql, options) #:nodoc:
  limit, offset = options[:limit], options[:offset]
  if limit && offset
    sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
  elsif limit
    sql << " LIMIT #{sanitize_limit(limit)}"
  elsif offset
    sql << " OFFSET #{offset.to_i}"
  end
  sql
end

#begin_db_transactionObject

:nodoc:



506
507
508
509
510
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 506

def begin_db_transaction #:nodoc:
  exec_without_stmt "BEGIN"
rescue Mysql::Error
  # Transactions aren't supported
end

#bulk_change_table(table_name, operations) ⇒ Object

:nodoc:



698
699
700
701
702
703
704
705
706
707
708
709
710
711
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 698

def bulk_change_table(table_name, operations) #:nodoc:
  sqls = operations.map do |command, args|
    table, arguments = args.shift, args
    method = :"#{command}_sql"

    if respond_to?(method, true)
      send(method, table, *arguments)
    else
      raise "Unknown method called : #{method}(#{arguments.inspect})"
    end
  end.flatten.join(", ")

  execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}")
end

#case_sensitive_equality_operatorObject



799
800
801
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 799

def case_sensitive_equality_operator
  "= BINARY"
end

#case_sensitive_modifier(node) ⇒ Object



804
805
806
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 804

def case_sensitive_modifier(node)
  Arel::Nodes::Bin.new(node)
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object

:nodoc:



732
733
734
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 732

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_sql(table_name, column_name, type, options)}")
end

#change_column_default(table_name, column_name, default) ⇒ Object

:nodoc:



717
718
719
720
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 717

def change_column_default(table_name, column_name, default) #:nodoc:
  column = column_for(table_name, column_name)
  change_column table_name, column_name, column.sql_type, :default => default
end

#change_column_null(table_name, column_name, null, default = nil) ⇒ Object



722
723
724
725
726
727
728
729
730
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 722

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

#charsetObject

Returns the database character set.



621
622
623
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 621

def charset
  show_variable 'character_set_database'
end

#clear_cache!Object

Clears the prepared statements cache.



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

def clear_cache!
  @statements.clear
end

#client_encodingObject

Get the client encoding for this database



432
433
434
435
436
437
438
439
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 432

def client_encoding
  return @client_encoding if @client_encoding

  result = exec_query(
    "SHOW VARIABLES WHERE Variable_name = 'character_set_client'",
    'SCHEMA')
  @client_encoding = ENCODINGS[result.rows.last.last]
end

#collationObject

Returns the database collation strategy.



626
627
628
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 626

def collation
  show_variable 'collation_database'
end

#columns(table_name, name = nil) ⇒ Object

Returns an array of MysqlColumn objects for the table specified by table_name.



678
679
680
681
682
683
684
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 678

def columns(table_name, name = nil)#:nodoc:
  sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
  result = execute(sql, 'SCHEMA')
  columns = result.collect { |field| MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") }
  result.free
  columns
end

#commit_db_transactionObject

:nodoc:



512
513
514
515
516
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 512

def commit_db_transaction #:nodoc:
  execute "COMMIT"
rescue Exception
  # Transactions aren't supported
end

#create_database(name, options = {}) ⇒ Object

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


600
601
602
603
604
605
606
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 600

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

#create_savepointObject



524
525
526
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 524

def create_savepoint
  execute("SAVEPOINT #{current_savepoint_name}")
end

#create_table(table_name, options = {}) ⇒ Object

:nodoc:



686
687
688
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 686

def create_table(table_name, options = {}) #:nodoc:
  super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB"))
end

#current_databaseObject



616
617
618
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 616

def current_database
  select_value 'SELECT DATABASE() as db'
end

#disable_referential_integrityObject

REFERENTIAL INTEGRITY ====================================



319
320
321
322
323
324
325
326
327
328
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 319

def disable_referential_integrity #:nodoc:
  old = select_value("SELECT @@FOREIGN_KEY_CHECKS")

  begin
    update("SET FOREIGN_KEY_CHECKS = 0")
    yield
  ensure
    update("SET FOREIGN_KEY_CHECKS = #{old}")
  end
end

#disconnect!Object

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



357
358
359
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 357

def disconnect!
  @connection.close rescue nil
end

#drop_database(name) ⇒ Object

Drops a MySQL database.

Example:

drop_database 'sebastian_development'


612
613
614
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 612

def drop_database(name) #:nodoc:
  execute "DROP DATABASE IF EXISTS `#{name}`"
end

#drop_table(table_name, options = {}) ⇒ Object



654
655
656
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 654

def drop_table(table_name, options = {})
  super(table_name, options)
end

#emulate_booleansObject

:singleton-method: 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::MysqlAdapter.emulate_booleans = false


161
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 161

cattr_accessor :emulate_booleans

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



497
498
499
500
501
502
503
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 497

def exec_delete(sql, name, binds)
  log(sql, name, binds) do
    exec_stmt(sql, name, binds) do |cols, stmt|
      stmt.affected_rows
    end
  end
end

#exec_query(sql, name = 'SQL', binds = []) ⇒ Object



441
442
443
444
445
446
447
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 441

def exec_query(sql, name = 'SQL', binds = [])
  log(sql, name, binds) do
    exec_stmt(sql, name, binds) do |cols, stmt|
      ActiveRecord::Result.new(cols, stmt.to_a) if cols
    end
  end
end

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

:nodoc:



453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 453

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)
    cols = []
    rows = []

    if result
      cols = result.fetch_fields.map { |field| field.name }
      rows = result.to_a
      result.free
    end
    ActiveRecord::Result.new(cols, rows)
  end
end

#execute(sql, name = nil) ⇒ Object

Executes an SQL query and returns a MySQL::Result object. Note that you have to free the Result object after you’re done using it.



472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 472

def execute(sql, name = nil) #:nodoc:
  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, "'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."
  else
    raise
  end
end

#indexes(table_name, name = nil) ⇒ Object

Returns an array of indexes for the given table.



659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 659

def indexes(table_name, name = nil)#:nodoc:
  indexes = []
  current_index = nil
  result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name)
  result.each do |row|
    if current_index != row[2]
      next if row[2] == "PRIMARY" # skip the primary key
      current_index = row[2]
      indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [], [])
    end

    indexes.last.columns << row[4]
    indexes.last.lengths << row[7]
  end
  result.free
  indexes
end

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

:nodoc:



486
487
488
489
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 486

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

#join_to_update(update, select) ⇒ Object

In the simple case, MySQL allows us to place JOINs directly into the UPDATE query. However, this does not allow for LIMIT, OFFSET and ORDER. To support these, we must use a subquery. However, MySQL is too stupid to create a temporary table for this automatically, so we have to give it some prompting in the form of a subsubquery. Ugh!



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 554

def join_to_update(update, select) #:nodoc:
  if select.limit || select.offset || select.orders.any?
    subsubselect = select.clone
    subsubselect.projections = [update.key]

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

    update.where update.key.in(subselect)
  else
    update.table select.source
    update.wheres = select.constraints
  end
end

#last_inserted_id(result) ⇒ Object



449
450
451
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 449

def last_inserted_id(result)
  @connection.insert_id
end

#limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) ⇒ Object



808
809
810
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 808

def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
  where_sql
end

#native_database_typesObject

:nodoc:



275
276
277
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 275

def native_database_types #:nodoc:
  NATIVE_DATABASE_TYPES
end

#pk_and_sequence_for(table) ⇒ Object

Returns a table’s primary key and belonging sequence.



780
781
782
783
784
785
786
787
788
789
790
791
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 780

def pk_and_sequence_for(table) #:nodoc:
  result = execute("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA')
  create_table = result.fetch_hash["Create Table"]
  result.free

  if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
    keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
    keys.length == 1 ? [keys.first, nil] : nil
  else
    nil
  end
end

#primary_key(table) ⇒ Object

Returns just a table’s primary key



794
795
796
797
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 794

def primary_key(table)
  pk_and_sequence = pk_and_sequence_for(table)
  pk_and_sequence && pk_and_sequence.first
end

#quote(value, column = nil) ⇒ Object

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



282
283
284
285
286
287
288
289
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 282

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}'"
  else
    super
  end
end

#quote_column_name(name) ⇒ Object

:nodoc:



297
298
299
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 297

def quote_column_name(name) #:nodoc:
  @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`"
end

#quote_string(string) ⇒ Object

:nodoc:



305
306
307
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 305

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

#quote_table_name(name) ⇒ Object

:nodoc:



301
302
303
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 301

def quote_table_name(name) #:nodoc:
  @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`')
end

#quoted_falseObject



313
314
315
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 313

def quoted_false
  QUOTED_FALSE
end

#quoted_trueObject



309
310
311
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 309

def quoted_true
  QUOTED_TRUE
end

#reconnect!Object



349
350
351
352
353
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 349

def reconnect!
  disconnect!
  clear_cache!
  connect
end

#recreate_database(name, options = {}) ⇒ Object

Drops the database specified on the name attribute and creates it again using the provided options.



588
589
590
591
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 588

def recreate_database(name, options = {}) #:nodoc:
  drop_database(name)
  create_database(name, options)
end

#release_savepointObject



532
533
534
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 532

def release_savepoint
  execute("RELEASE SAVEPOINT #{current_savepoint_name}")
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



736
737
738
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 736

def rename_column(table_name, column_name, new_column_name) #:nodoc:
  execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}")
end

#rename_table(table_name, new_name) ⇒ Object

Renames a table.

Example:

rename_table('octopuses', 'octopi')


694
695
696
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 694

def rename_table(table_name, new_name)
  execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
end

#reset!Object



361
362
363
364
365
366
367
368
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 361

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

#rollback_db_transactionObject

:nodoc:



518
519
520
521
522
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 518

def rollback_db_transaction #:nodoc:
  execute "ROLLBACK"
rescue Exception
  # Transactions aren't supported
end

#rollback_to_savepointObject



528
529
530
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 528

def rollback_to_savepoint
  execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
end

#select_rows(sql, name = nil) ⇒ Object

DATABASE STATEMENTS ======================================



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

def select_rows(sql, name = nil)
  @connection.query_with_result = true
  rows = exec_without_stmt(sql, name).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

#show_variable(name) ⇒ Object

SHOW VARIABLES LIKE ‘name’



774
775
776
777
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 774

def show_variable(name)
  variables = select_all("SHOW VARIABLES LIKE '#{name}'")
  variables.first['Value'] unless variables.empty?
end

#structure_dumpObject

SCHEMA STATEMENTS ========================================



572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 572

def structure_dump #:nodoc:
  if supports_views?
    sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
  else
    sql = "SHOW TABLES"
  end

  select_all(sql).map do |table|
    table.delete('Table_type')
    sql = "SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}"
    exec_without_stmt(sql).first['Create Table'] + ";\n\n"
  end.join("")
end

#supports_bulk_alter?Boolean

:nodoc:

Returns:

  • (Boolean)


250
251
252
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 250

def supports_bulk_alter? #:nodoc:
  true
end

#supports_migrations?Boolean

Returns true, since this connection adapter supports migrations.

Returns:

  • (Boolean)


261
262
263
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 261

def supports_migrations? #:nodoc:
  true
end

#supports_primary_key?Boolean

Returns true.

Returns:

  • (Boolean)


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

def supports_primary_key? #:nodoc:
  true
end

#supports_savepoints?Boolean

Returns true, since this connection adapter supports savepoints.

Returns:

  • (Boolean)


271
272
273
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 271

def supports_savepoints? #:nodoc:
  true
end

#supports_statement_cache?Boolean

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

Returns:

  • (Boolean)


256
257
258
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 256

def supports_statement_cache?
  true
end

#table_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


640
641
642
643
644
645
646
647
648
649
650
651
652
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 640

def table_exists?(name)
  return true if super

  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).include? table
end

#tables(name = nil, database = nil) ⇒ Object

:nodoc:



630
631
632
633
634
635
636
637
638
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 630

def tables(name = nil, database = nil) #:nodoc:
  sql = "SHOW TABLES "
  sql << "IN #{quote_table_name(database)} " if database

  result = execute(sql, 'SCHEMA')
  tables = result.collect { |field| field[0] }
  result.free
  tables
end

#type_cast(value, column) ⇒ Object



291
292
293
294
295
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 291

def type_cast(value, column)
  return super unless value == true || value == false

  value ? 1 : 0
end

#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object

Maps logical Rails types to MySQL-specific data types.



741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 741

def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  case type.to_s
  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

#update_sql(sql, name = nil) ⇒ Object

:nodoc:



492
493
494
495
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 492

def update_sql(sql, name = nil) #:nodoc:
  super
  @connection.affected_rows
end