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
@@null_values_in_each_hash =
false

Instance Method Summary collapse

Methods inherited from AbstractAdapter

#clear_query_cache

Constructor Details

#initialize(connection, logger, connection_options = nil) ⇒ MysqlAdapter

Returns a new instance of MysqlAdapter.



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

def initialize(connection, logger, connection_options=nil)
  super(connection, logger)
  @connection_options = connection_options
end

Instance Method Details

#adapter_nameObject

:nodoc:



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

def adapter_name #:nodoc:
  'MySQL'
end

#add_limit_offset!(sql, options) ⇒ Object

:nodoc



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

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:



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

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

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

:nodoc:



280
281
282
283
284
285
286
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 280

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:



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

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:



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

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:



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

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

#create_database(name) ⇒ Object

:nodoc:



229
230
231
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 229

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

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

:nodoc:



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

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

#drop_database(name) ⇒ Object

:nodoc:



233
234
235
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 233

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

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

:nodoc:



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 151

def execute(sql, name = nil, retries = 2) #:nodoc:
  unless @logger
    @connection.query(sql)
  else
    log(sql, name) { @connection.query(sql) }
  end
rescue ActiveRecord::StatementInvalid => exception
  if LOST_CONNECTION_ERROR_MESSAGES.any? { |msg| exception.message.split(":").first =~ /^#{msg}/ }
    @connection.real_connect(*@connection_options)
    unless @logger
      @connection.query(sql)
    else
      @logger.info "Retrying invalid statement with reopened connection"
      log(sql, name) { @connection.query(sql) }
    end
  elsif 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 update mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information."
  else
    raise
  end
end

#indexes(table_name, name = nil) ⇒ Object

:nodoc:



244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 244

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:



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

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



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 104

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_column_name(name) ⇒ Object

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



123
124
125
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 123

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

#quote_string(string) ⇒ Object

:nodoc:



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

def quote_string(string) #:nodoc:
  Mysql::quote(string)
end

#quoted_falseObject



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

def quoted_false
  "0"
end

#quoted_trueObject



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

def quoted_true
  "1"
end

#recreate_database(name) ⇒ Object

:nodoc:



224
225
226
227
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 224

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

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



288
289
290
291
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 288

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



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

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

#rollback_db_transactionObject

:nodoc:



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

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

#select_all(sql, name = nil) ⇒ Object

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



142
143
144
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 142

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

#select_one(sql, name = nil) ⇒ Object

:nodoc:



146
147
148
149
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 146

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

#structure_dumpObject

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



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

def structure_dump #:nodoc:
  select_all("SHOW TABLES").inject("") do |structure, table|
    structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n"
  end
end

#supports_migrations?Boolean

:nodoc:

Returns:

  • (Boolean)


100
101
102
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 100

def supports_migrations? #:nodoc:
  true
end

#tables(name = nil) ⇒ Object

:nodoc:



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

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:



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

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