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.

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

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 environment.rb file:

ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false

Constant Summary collapse

LOST_CONNECTION_ERROR_MESSAGES =
[
  "Server shutdown in progress",
  "Broken pipe",
  "Lost connection to MySQL server during query",
  "MySQL server has gone away"
]
@@emulate_booleans =
true

Instance Method Summary collapse

Methods inherited from AbstractAdapter

#clear_query_cache

Constructor Details

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

Returns a new instance of MysqlAdapter.



84
85
86
87
88
89
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 84

def initialize(connection, logger, connection_options, config)
  super(connection, logger)
  @connection_options, @config = connection_options, config
  @null_values_in_each_hash = Mysql.const_defined?(:VERSION)
  connect
end

Instance Method Details

#active?Boolean

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

Returns:

  • (Boolean)


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

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:



91
92
93
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 91

def adapter_name #:nodoc:
  'MySQL'
end

#add_limit_offset!(sql, options) ⇒ Object

:nodoc



226
227
228
229
230
231
232
233
234
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 226

def add_limit_offset!(sql, options) #:nodoc
  if limit = options[:limit]
    unless offset = options[:offset]
      sql << " LIMIT #{limit}"
    else
      sql << " LIMIT #{offset}, #{limit}"
    end
  end
end

#begin_db_transactionObject

:nodoc:



207
208
209
210
211
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 207

def begin_db_transaction #:nodoc:
  execute "BEGIN"
rescue Exception
  # Transactions aren't supported
end

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

:nodoc:



311
312
313
314
315
316
317
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 311

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  options[:default] ||= select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
  
  change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit])}"
  add_column_options!(change_column_sql, options)
  execute(change_column_sql)
end

#change_column_default(table_name, column_name, default) ⇒ Object

:nodoc:



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

def change_column_default(table_name, column_name, default) #:nodoc:
  current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]

  change_column(table_name, column_name, current_type, { :default => default })
end

#columns(table_name, name = nil) ⇒ Object

:nodoc:



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

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

#commit_db_transactionObject

:nodoc:



213
214
215
216
217
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 213

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

#create_database(name) ⇒ Object

:nodoc:



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

def create_database(name) #:nodoc:
  execute "CREATE DATABASE `#{name}`"
end

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

:nodoc:



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

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

#current_databaseObject



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

def current_database
  select_one("SELECT DATABASE() as db")["db"]
end

#disconnect!Object



168
169
170
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 168

def disconnect!
  @connection.close rescue nil
end

#drop_database(name) ⇒ Object

:nodoc:



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

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

#execute(sql, name = nil, retries = 2) ⇒ Object

:nodoc:



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

def execute(sql, name = nil, retries = 2) #:nodoc:
  log(sql, name) { @connection.query(sql) }
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

:nodoc:



275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 275

def indexes(table_name, name = nil)#:nodoc:
  indexes = []
  current_index = nil
  execute("SHOW KEYS FROM #{table_name}", name).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]
  end
  indexes
end

#insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) ⇒ Object

:nodoc:



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

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

#native_database_typesObject

:nodoc



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 99

def native_database_types #:nodoc
  {
    :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
    :string      => { :name => "varchar", :limit => 255 },
    :text        => { :name => "text" },
    :integer     => { :name => "int", :limit => 11 },
    :float       => { :name => "float" },
    :datetime    => { :name => "datetime" },
    :timestamp   => { :name => "datetime" },
    :time        => { :name => "time" },
    :date        => { :name => "date" },
    :binary      => { :name => "blob" },
    :boolean     => { :name => "tinyint", :limit => 1 }
  }
end

#quote(value, column = nil) ⇒ Object

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



118
119
120
121
122
123
124
125
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 118

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:



127
128
129
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 127

def quote_column_name(name) #:nodoc:
  "`#{name}`"
end

#quote_string(string) ⇒ Object

:nodoc:



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

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

#quoted_falseObject



139
140
141
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 139

def quoted_false
  "0"
end

#quoted_trueObject



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

def quoted_true
  "1"
end

#reconnect!Object



163
164
165
166
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 163

def reconnect!
  disconnect!
  connect
end

#recreate_database(name) ⇒ Object

:nodoc:



252
253
254
255
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 252

def recreate_database(name) #:nodoc:
  drop_database(name)
  create_database(name)
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



319
320
321
322
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 319

def rename_column(table_name, column_name, new_column_name) #:nodoc:
  current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]
  execute "ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}"
end

#rename_table(name, new_name) ⇒ Object



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

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

#rollback_db_transactionObject

:nodoc:



219
220
221
222
223
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 219

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

#select_all(sql, name = nil) ⇒ Object

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



175
176
177
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 175

def select_all(sql, name = nil) #:nodoc:
  select(sql, name)
end

#select_one(sql, name = nil) ⇒ Object

:nodoc:



179
180
181
182
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 179

def select_one(sql, name = nil) #:nodoc:
  result = select(sql, name)
  result.nil? ? nil : result.first
end

#structure_dumpObject

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



239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 239

def structure_dump #:nodoc:
  if supports_views?
    sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
  else
    sql = "SHOW TABLES"
  end
  
  select_all(sql).inject("") do |structure, table|
    table.delete('Table_type')
    structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n"
  end
end

#supports_migrations?Boolean

:nodoc:

Returns:

  • (Boolean)


95
96
97
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 95

def supports_migrations? #:nodoc:
  true
end

#tables(name = nil) ⇒ Object

:nodoc:



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

def tables(name = nil) #:nodoc:
  tables = []
  execute("SHOW TABLES", name).each { |field| tables << field[0] }
  tables
end

#update(sql, name = nil) ⇒ Object Also known as: delete

:nodoc:



199
200
201
202
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 199

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