mysql2 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ require 'rake/clean'
2
+ require 'rake/extensioncompiler'
3
+
4
+ # download mysql library and headers
5
+ directory "vendor"
6
+
7
+ file "vendor/mysql-noinstall-#{MYSQL_VERSION}-win32.zip" => ['vendor'] do |t|
8
+ base_version = MYSQL_VERSION.gsub(/\.[0-9]+$/, '')
9
+ url = "http://dev.mysql.com/get/Downloads/MySQL-#{base_version}/#{File.basename(t.name)}/from/#{MYSQL_MIRROR}/"
10
+ when_writing "downloading #{t.name}" do
11
+ cd File.dirname(t.name) do
12
+ sh "wget -c #{url} || curl -C - -O #{url}"
13
+ end
14
+ end
15
+ end
16
+
17
+ file "vendor/mysql-#{MYSQL_VERSION}-win32/include/mysql.h" => ["vendor/mysql-noinstall-#{MYSQL_VERSION}-win32.zip"] do |t|
18
+ full_file = File.expand_path(t.prerequisites.last)
19
+ when_writing "creating #{t.name}" do
20
+ cd "vendor" do
21
+ sh "unzip #{full_file} mysql-#{MYSQL_VERSION}-win32/bin/** mysql-#{MYSQL_VERSION}-win32/include/** mysql-#{MYSQL_VERSION}-win32/lib/**"
22
+ end
23
+ # update file timestamp to avoid Rake perform this extraction again.
24
+ touch t.name
25
+ end
26
+ end
27
+
28
+ # clobber expanded packages
29
+ CLOBBER.include("vendor/mysql-#{MYSQL_VERSION}-win32")
30
+
31
+ # vendor:mysql
32
+ task 'vendor:mysql' => ["vendor/mysql-#{MYSQL_VERSION}-win32/include/mysql.h"]
33
+
34
+ # hook into cross compilation vendored mysql dependency
35
+ if RUBY_PLATFORM =~ /mingw|mswin/ then
36
+ Rake::Task['compile'].prerequisites.unshift 'vendor:mysql'
37
+ else
38
+ if Rake::Task.tasks.map {|t| t.name }.include? 'cross'
39
+ Rake::Task['cross'].prerequisites.unshift 'vendor:mysql'
40
+ end
41
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 9
10
- version: 0.1.9
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Lopez
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-17 00:00:00 -07:00
18
+ date: 2010-08-16 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -35,19 +35,23 @@ files:
35
35
  - Rakefile
36
36
  - VERSION
37
37
  - benchmark/active_record.rb
38
+ - benchmark/allocations.rb
38
39
  - benchmark/escape.rb
39
40
  - benchmark/query_with_mysql_casting.rb
40
41
  - benchmark/query_without_mysql_casting.rb
41
42
  - benchmark/sequel.rb
42
43
  - benchmark/setup_db.rb
44
+ - benchmark/thread_alone.rb
43
45
  - examples/eventmachine.rb
46
+ - examples/threaded.rb
47
+ - ext/mysql2/client.c
48
+ - ext/mysql2/client.h
44
49
  - ext/mysql2/extconf.rb
45
50
  - ext/mysql2/mysql2_ext.c
46
51
  - ext/mysql2/mysql2_ext.h
47
52
  - ext/mysql2/result.c
48
53
  - ext/mysql2/result.h
49
54
  - lib/active_record/connection_adapters/em_mysql2_adapter.rb
50
- - lib/active_record/connection_adapters/mysql2_adapter.rb
51
55
  - lib/active_record/fiber_patches.rb
52
56
  - lib/arel/engines/sql/compilers/mysql2_compiler.rb
53
57
  - lib/mysql2.rb
@@ -55,9 +59,7 @@ files:
55
59
  - lib/mysql2/em.rb
56
60
  - lib/mysql2/error.rb
57
61
  - lib/mysql2/result.rb
58
- - lib/sequel/adapters/mysql2.rb
59
62
  - mysql2.gemspec
60
- - spec/active_record/active_record_spec.rb
61
63
  - spec/em/em_spec.rb
62
64
  - spec/mysql2/client_spec.rb
63
65
  - spec/mysql2/error_spec.rb
@@ -65,6 +67,9 @@ files:
65
67
  - spec/rcov.opts
66
68
  - spec/spec.opts
67
69
  - spec/spec_helper.rb
70
+ - tasks/benchmarks.rake
71
+ - tasks/compile.rake
72
+ - tasks/vendor_mysql.rake
68
73
  has_rdoc: true
69
74
  homepage: http://github.com/brianmario/mysql2
70
75
  licenses: []
@@ -101,10 +106,10 @@ signing_key:
101
106
  specification_version: 3
102
107
  summary: A simple, fast Mysql library for Ruby, binding to libmysql
103
108
  test_files:
104
- - spec/active_record/active_record_spec.rb
105
109
  - spec/em/em_spec.rb
106
110
  - spec/mysql2/client_spec.rb
107
111
  - spec/mysql2/error_spec.rb
108
112
  - spec/mysql2/result_spec.rb
109
113
  - spec/spec_helper.rb
110
114
  - examples/eventmachine.rb
115
+ - examples/threaded.rb
@@ -1,598 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'mysql2' unless defined? Mysql2
4
-
5
- module ActiveRecord
6
- class Base
7
- def self.mysql2_connection(config)
8
- config[:username] = 'root' if config[:username].nil?
9
- client = Mysql2::Client.new(config.symbolize_keys)
10
- options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
11
- ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
12
- end
13
- end
14
-
15
- module ConnectionAdapters
16
- class Mysql2Column < Column
17
- BOOL = "tinyint(1)".freeze
18
- def extract_default(default)
19
- if sql_type =~ /blob/i || type == :text
20
- if default.blank?
21
- return null ? nil : ''
22
- else
23
- raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
24
- end
25
- elsif missing_default_forged_as_empty_string?(default)
26
- nil
27
- else
28
- super
29
- end
30
- end
31
-
32
- def has_default?
33
- return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns
34
- super
35
- end
36
-
37
- # Returns the Ruby class that corresponds to the abstract data type.
38
- def klass
39
- case type
40
- when :integer then Fixnum
41
- when :float then Float
42
- when :decimal then BigDecimal
43
- when :datetime then Time
44
- when :date then Date
45
- when :timestamp then Time
46
- when :time then Time
47
- when :text, :string then String
48
- when :binary then String
49
- when :boolean then Object
50
- end
51
- end
52
-
53
- def type_cast(value)
54
- return nil if value.nil?
55
- case type
56
- when :string then value
57
- when :text then value
58
- when :integer then value.to_i rescue value ? 1 : 0
59
- when :float then value.to_f # returns self if it's already a Float
60
- when :decimal then self.class.value_to_decimal(value)
61
- when :datetime, :timestamp then value.class == Time ? value : self.class.string_to_time(value)
62
- when :time then value.class == Time ? value : self.class.string_to_dummy_time(value)
63
- when :date then value.class == Date ? value : self.class.string_to_date(value)
64
- when :binary then value
65
- when :boolean then self.class.value_to_boolean(value)
66
- else value
67
- end
68
- end
69
-
70
- def type_cast_code(var_name)
71
- case type
72
- when :string then nil
73
- when :text then nil
74
- when :integer then "#{var_name}.to_i rescue #{var_name} ? 1 : 0"
75
- when :float then "#{var_name}.to_f"
76
- when :decimal then "#{self.class.name}.value_to_decimal(#{var_name})"
77
- when :datetime, :timestamp then "#{var_name}.class == Time ? #{var_name} : #{self.class.name}.string_to_time(#{var_name})"
78
- when :time then "#{var_name}.class == Time ? #{var_name} : #{self.class.name}.string_to_dummy_time(#{var_name})"
79
- when :date then "#{var_name}.class == Date ? #{var_name} : #{self.class.name}.string_to_date(#{var_name})"
80
- when :binary then nil
81
- when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
82
- else nil
83
- end
84
- end
85
-
86
- private
87
- def simplified_type(field_type)
88
- return :boolean if Mysql2Adapter.emulate_booleans && field_type.downcase.index(BOOL)
89
- return :string if field_type =~ /enum/i
90
- return :integer if field_type =~ /year/i
91
- super
92
- end
93
-
94
- def extract_limit(sql_type)
95
- case sql_type
96
- when /blob|text/i
97
- case sql_type
98
- when /tiny/i
99
- 255
100
- when /medium/i
101
- 16777215
102
- when /long/i
103
- 2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases
104
- else
105
- super # we could return 65535 here, but we leave it undecorated by default
106
- end
107
- when /^bigint/i; 8
108
- when /^int/i; 4
109
- when /^mediumint/i; 3
110
- when /^smallint/i; 2
111
- when /^tinyint/i; 1
112
- else
113
- super
114
- end
115
- end
116
-
117
- # MySQL misreports NOT NULL column default when none is given.
118
- # We can't detect this for columns which may have a legitimate ''
119
- # default (string) but we can for others (integer, datetime, boolean,
120
- # and the rest).
121
- #
122
- # Test whether the column has default '', is not null, and is not
123
- # a type allowing default ''.
124
- def missing_default_forged_as_empty_string?(default)
125
- type != :string && !null && default == ''
126
- end
127
- end
128
-
129
- class Mysql2Adapter < AbstractAdapter
130
- cattr_accessor :emulate_booleans
131
- self.emulate_booleans = true
132
-
133
- ADAPTER_NAME = 'MySQL'.freeze
134
- PRIMARY = "PRIMARY".freeze
135
-
136
- LOST_CONNECTION_ERROR_MESSAGES = [
137
- "Server shutdown in progress",
138
- "Broken pipe",
139
- "Lost connection to MySQL server during query",
140
- "MySQL server has gone away" ]
141
-
142
- QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
143
-
144
- NATIVE_DATABASE_TYPES = {
145
- :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY".freeze,
146
- :string => { :name => "varchar", :limit => 255 },
147
- :text => { :name => "text" },
148
- :integer => { :name => "int", :limit => 4 },
149
- :float => { :name => "float" },
150
- :decimal => { :name => "decimal" },
151
- :datetime => { :name => "datetime" },
152
- :timestamp => { :name => "datetime" },
153
- :time => { :name => "time" },
154
- :date => { :name => "date" },
155
- :binary => { :name => "blob" },
156
- :boolean => { :name => "tinyint", :limit => 1 }
157
- }
158
-
159
- def initialize(connection, logger, connection_options, config)
160
- super(connection, logger)
161
- @connection_options, @config = connection_options, config
162
- @quoted_column_names, @quoted_table_names = {}, {}
163
- end
164
-
165
- def adapter_name
166
- ADAPTER_NAME
167
- end
168
-
169
- def supports_migrations?
170
- true
171
- end
172
-
173
- def supports_primary_key?
174
- true
175
- end
176
-
177
- def supports_savepoints?
178
- true
179
- end
180
-
181
- def native_database_types
182
- NATIVE_DATABASE_TYPES
183
- end
184
-
185
- # QUOTING ==================================================
186
-
187
- def quote(value, column = nil)
188
- if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
189
- s = column.class.string_to_binary(value).unpack("H*")[0]
190
- "x'#{s}'"
191
- elsif value.kind_of?(BigDecimal)
192
- value.to_s("F")
193
- else
194
- super
195
- end
196
- end
197
-
198
- def quote_column_name(name) #:nodoc:
199
- @quoted_column_names[name] ||= "`#{name}`"
200
- end
201
-
202
- def quote_table_name(name) #:nodoc:
203
- @quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`')
204
- end
205
-
206
- def quote_string(string)
207
- @connection.escape(string)
208
- end
209
-
210
- def quoted_true
211
- QUOTED_TRUE
212
- end
213
-
214
- def quoted_false
215
- QUOTED_FALSE
216
- end
217
-
218
- # REFERENTIAL INTEGRITY ====================================
219
-
220
- def disable_referential_integrity(&block) #:nodoc:
221
- old = select_value("SELECT @@FOREIGN_KEY_CHECKS")
222
-
223
- begin
224
- update("SET FOREIGN_KEY_CHECKS = 0")
225
- yield
226
- ensure
227
- update("SET FOREIGN_KEY_CHECKS = #{old}")
228
- end
229
- end
230
-
231
- # CONNECTION MANAGEMENT ====================================
232
-
233
- def active?
234
- @connection.query 'select 1'
235
- true
236
- rescue Mysql2::Error
237
- false
238
- end
239
-
240
- def reconnect!
241
- reset!
242
- end
243
-
244
- def disconnect!
245
- unless @connection.nil?
246
- @connection.close
247
- @connection = nil
248
- end
249
- end
250
-
251
- def reset!
252
- disconnect!
253
- @connection = Mysql2::Client.new(@config)
254
- end
255
-
256
- # DATABASE STATEMENTS ======================================
257
-
258
- def select_values(sql, name = nil)
259
- select(sql, name).map { |row| row.values.first }
260
- end
261
-
262
- def select_rows(sql, name = nil)
263
- select(sql, name).map { |row| row.values }
264
- end
265
-
266
- # Executes a SQL query and returns a MySQL::Result object. Note that you have to free the Result object after you're done using it.
267
- def execute(sql, name = nil)
268
- if name == :skip_logging
269
- @connection.query(sql)
270
- else
271
- log(sql, name) { @connection.query(sql) }
272
- end
273
- rescue ActiveRecord::StatementInvalid => exception
274
- if exception.message.split(":").first =~ /Packets out of order/
275
- 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."
276
- else
277
- raise
278
- end
279
- end
280
-
281
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
282
- super sql, name
283
- id_value || @connection.last_id
284
- end
285
- alias :create :insert_sql
286
-
287
- def update_sql(sql, name = nil)
288
- super
289
- @connection.affected_rows
290
- end
291
-
292
- def begin_db_transaction
293
- execute "BEGIN"
294
- rescue Exception
295
- # Transactions aren't supported
296
- end
297
-
298
- def commit_db_transaction
299
- execute "COMMIT"
300
- rescue Exception
301
- # Transactions aren't supported
302
- end
303
-
304
- def rollback_db_transaction
305
- execute "ROLLBACK"
306
- rescue Exception
307
- # Transactions aren't supported
308
- end
309
-
310
- def create_savepoint
311
- execute("SAVEPOINT #{current_savepoint_name}")
312
- end
313
-
314
- def rollback_to_savepoint
315
- execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
316
- end
317
-
318
- def release_savepoint
319
- execute("RELEASE SAVEPOINT #{current_savepoint_name}")
320
- end
321
-
322
- def add_limit_offset!(sql, options)
323
- limit, offset = options[:limit], options[:offset]
324
- if limit && offset
325
- sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
326
- elsif limit
327
- sql << " LIMIT #{sanitize_limit(limit)}"
328
- elsif offset
329
- sql << " OFFSET #{offset.to_i}"
330
- end
331
- sql
332
- end
333
-
334
- # SCHEMA STATEMENTS ========================================
335
-
336
- def structure_dump
337
- if supports_views?
338
- sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
339
- else
340
- sql = "SHOW TABLES"
341
- end
342
-
343
- select_all(sql).inject("") do |structure, table|
344
- table.delete('Table_type')
345
- structure += select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n"
346
- end
347
- end
348
-
349
- def recreate_database(name, options = {})
350
- drop_database(name)
351
- create_database(name, options)
352
- end
353
-
354
- # Create a new MySQL database with optional <tt>:charset</tt> and <tt>:collation</tt>.
355
- # Charset defaults to utf8.
356
- #
357
- # Example:
358
- # create_database 'charset_test', :charset => 'latin1', :collation => 'latin1_bin'
359
- # create_database 'matt_development'
360
- # create_database 'matt_development', :charset => :big5
361
- def create_database(name, options = {})
362
- if options[:collation]
363
- execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`"
364
- else
365
- execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`"
366
- end
367
- end
368
-
369
- def drop_database(name) #:nodoc:
370
- execute "DROP DATABASE IF EXISTS `#{name}`"
371
- end
372
-
373
- def current_database
374
- select_value 'SELECT DATABASE() as db'
375
- end
376
-
377
- # Returns the database character set.
378
- def charset
379
- show_variable 'character_set_database'
380
- end
381
-
382
- # Returns the database collation strategy.
383
- def collation
384
- show_variable 'collation_database'
385
- end
386
-
387
- def tables(name = nil)
388
- tables = []
389
- execute("SHOW TABLES", name).each(:symbolize_keys => true) do |field|
390
- tables << field.values.first
391
- end
392
- tables
393
- end
394
-
395
- def drop_table(table_name, options = {})
396
- super(table_name, options)
397
- end
398
-
399
- def indexes(table_name, name = nil)
400
- indexes = []
401
- current_index = nil
402
- result = execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name)
403
- result.each(:symbolize_keys => true) do |row|
404
- if current_index != row[:Key_name]
405
- next if row[:Key_name] == PRIMARY # skip the primary key
406
- current_index = row[:Key_name]
407
- indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique] == 0, [])
408
- end
409
-
410
- indexes.last.columns << row[:Column_name]
411
- end
412
- indexes
413
- end
414
-
415
- def columns(table_name, name = nil)
416
- sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
417
- columns = []
418
- result = execute(sql, :skip_logging)
419
- result.each(:symbolize_keys => true) { |field|
420
- columns << Mysql2Column.new(field[:Field], field[:Default], field[:Type], field[:Null] == "YES")
421
- }
422
- columns
423
- end
424
-
425
- def create_table(table_name, options = {})
426
- super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB"))
427
- end
428
-
429
- def rename_table(table_name, new_name)
430
- execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
431
- end
432
-
433
- def add_column(table_name, column_name, type, options = {})
434
- add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
435
- add_column_options!(add_column_sql, options)
436
- add_column_position!(add_column_sql, options)
437
- execute(add_column_sql)
438
- end
439
-
440
- def change_column_default(table_name, column_name, default)
441
- column = column_for(table_name, column_name)
442
- change_column table_name, column_name, column.sql_type, :default => default
443
- end
444
-
445
- def change_column_null(table_name, column_name, null, default = nil)
446
- column = column_for(table_name, column_name)
447
-
448
- unless null || default.nil?
449
- execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
450
- end
451
-
452
- change_column table_name, column_name, column.sql_type, :null => null
453
- end
454
-
455
- def change_column(table_name, column_name, type, options = {})
456
- column = column_for(table_name, column_name)
457
-
458
- unless options_include_default?(options)
459
- options[:default] = column.default
460
- end
461
-
462
- unless options.has_key?(:null)
463
- options[:null] = column.null
464
- end
465
-
466
- change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
467
- add_column_options!(change_column_sql, options)
468
- add_column_position!(change_column_sql, options)
469
- execute(change_column_sql)
470
- end
471
-
472
- def rename_column(table_name, column_name, new_column_name)
473
- options = {}
474
- if column = columns(table_name).find { |c| c.name == column_name.to_s }
475
- options[:default] = column.default
476
- options[:null] = column.null
477
- else
478
- raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
479
- end
480
- current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
481
- rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
482
- add_column_options!(rename_column_sql, options)
483
- execute(rename_column_sql)
484
- end
485
-
486
- # Maps logical Rails types to MySQL-specific data types.
487
- def type_to_sql(type, limit = nil, precision = nil, scale = nil)
488
- return super unless type.to_s == 'integer'
489
-
490
- case limit
491
- when 1; 'tinyint'
492
- when 2; 'smallint'
493
- when 3; 'mediumint'
494
- when nil, 4, 11; 'int(11)' # compatibility with MySQL default
495
- when 5..8; 'bigint'
496
- else raise(ActiveRecordError, "No integer type has byte size #{limit}")
497
- end
498
- end
499
-
500
- def add_column_position!(sql, options)
501
- if options[:first]
502
- sql << " FIRST"
503
- elsif options[:after]
504
- sql << " AFTER #{quote_column_name(options[:after])}"
505
- end
506
- end
507
-
508
- def show_variable(name)
509
- variables = select_all("SHOW VARIABLES LIKE '#{name}'")
510
- variables.first['Value'] unless variables.empty?
511
- end
512
-
513
- def pk_and_sequence_for(table)
514
- keys = []
515
- result = execute("describe #{quote_table_name(table)}")
516
- result.each(:symbolize_keys => true) do |row|
517
- keys << row[:Field] if row[:Key] == "PRI"
518
- end
519
- keys.length == 1 ? [keys.first, nil] : nil
520
- end
521
-
522
- # Returns just a table's primary key
523
- def primary_key(table)
524
- pk_and_sequence = pk_and_sequence_for(table)
525
- pk_and_sequence && pk_and_sequence.first
526
- end
527
-
528
- def case_sensitive_equality_operator
529
- "= BINARY"
530
- end
531
-
532
- def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
533
- where_sql
534
- end
535
-
536
- protected
537
- def quoted_columns_for_index(column_names, options = {})
538
- length = options[:length] if options.is_a?(Hash)
539
-
540
- quoted_column_names = case length
541
- when Hash
542
- column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
543
- when Fixnum
544
- column_names.map {|name| "#{quote_column_name(name)}(#{length})"}
545
- else
546
- column_names.map {|name| quote_column_name(name) }
547
- end
548
- end
549
-
550
- # TODO: implement error_number method on Mysql2::Exception
551
- def translate_exception(exception, message)
552
- return super unless exception.respond_to?(:error_number)
553
-
554
- case exception.error_number
555
- when 1062
556
- RecordNotUnique.new(message, exception)
557
- when 1452
558
- InvalidForeignKey.new(message, exception)
559
- else
560
- super
561
- end
562
- end
563
-
564
- private
565
- def connect
566
- # no-op
567
- end
568
-
569
- def configure_connection
570
- encoding = @config[:encoding]
571
- execute("SET NAMES '#{encoding}'", :skip_logging) if encoding
572
-
573
- # By default, MySQL 'where id is null' selects the last inserted id.
574
- # Turn this off. http://dev.rubyonrails.org/ticket/6778
575
- execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
576
- end
577
-
578
- def select(sql, name = nil)
579
- execute(sql, name).to_a
580
- end
581
-
582
- def supports_views?
583
- version[0] >= 5
584
- end
585
-
586
- def version
587
- @version ||= @connection.info[:version].scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
588
- end
589
-
590
- def column_for(table_name, column_name)
591
- unless column = columns(table_name).find { |c| c.name == column_name.to_s }
592
- raise "No such column: #{table_name}.#{column_name}"
593
- end
594
- column
595
- end
596
- end
597
- end
598
- end