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)


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

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



715
716
717
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 715

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



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

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:



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

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:



508
509
510
511
512
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 508

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:



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

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



801
802
803
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 801

def case_sensitive_equality_operator
  "= BINARY"
end

#case_sensitive_modifier(node) ⇒ Object



806
807
808
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 806

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

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

:nodoc:



734
735
736
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 734

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:



719
720
721
722
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 719

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



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

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.



623
624
625
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 623

def charset
  show_variable 'character_set_database'
end

#clear_cache!Object

Clears the prepared statements cache.



382
383
384
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 382

def clear_cache!
  @statements.clear
end

#client_encodingObject

Get the client encoding for this database



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

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.



628
629
630
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 628

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.



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

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:



514
515
516
517
518
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 514

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


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

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



526
527
528
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 526

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

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

:nodoc:



688
689
690
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 688

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

#current_databaseObject



618
619
620
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 618

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

#disable_referential_integrityObject

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



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

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.



359
360
361
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 359

def disconnect!
  @connection.close rescue nil
end

#drop_database(name) ⇒ Object

Drops a MySQL database.

Example:

drop_database 'sebastian_development'


614
615
616
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 614

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

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



656
657
658
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 656

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



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

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



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

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:



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

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.



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

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.



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

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:



488
489
490
491
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 488

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!



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

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



451
452
453
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 451

def last_inserted_id(result)
  @connection.insert_id
end

#limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) ⇒ Object



810
811
812
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 810

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.



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

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



796
797
798
799
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 796

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
290
291
# 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}'"
  elsif value.kind_of?(BigDecimal)
    value.to_s("F")
  else
    super
  end
end

#quote_column_name(name) ⇒ Object

:nodoc:



299
300
301
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 299

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

#quote_string(string) ⇒ Object

:nodoc:



307
308
309
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 307

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

#quote_table_name(name) ⇒ Object

:nodoc:



303
304
305
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 303

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

#quoted_falseObject



315
316
317
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 315

def quoted_false
  QUOTED_FALSE
end

#quoted_trueObject



311
312
313
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 311

def quoted_true
  QUOTED_TRUE
end

#reconnect!Object



351
352
353
354
355
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 351

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.



590
591
592
593
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 590

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

#release_savepointObject



534
535
536
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 534

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

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



738
739
740
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 738

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')


696
697
698
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 696

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

#reset!Object



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

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:



520
521
522
523
524
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 520

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

#rollback_to_savepointObject



530
531
532
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 530

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

#select_rows(sql, name = nil) ⇒ Object

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



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

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’



776
777
778
779
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 776

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

#structure_dumpObject

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



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

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)


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

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:



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

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



293
294
295
296
297
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 293

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.



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

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:



494
495
496
497
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 494

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