activerecord-mysql-adapter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in activerecord-mysql-adapter.gemspec
4
+ gemspec
5
+ gem 'mysql', '>= 2.9.0'
6
+ gem 'activerecord', '>= 3.2.9'
7
+ gem 'activesupport', '>= 3.2.9'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Andrey Deryabin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ # Activerecord::Mysql::Adapter
2
+
3
+ An ActiveRecord adapter for MySQL, based on mysql gem. This is extract from Rails core source code.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'activerecord-mysql-adapter'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install activerecord-mysql-adapter
18
+
19
+ ## Contributing
20
+
21
+ 1. Fork it
22
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
23
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
24
+ 4. Push to the branch (`git push origin my-new-feature`)
25
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'activerecord-mysql-adapter/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "activerecord-mysql-adapter"
8
+ gem.version = ActiverecordMysqlAdapter::VERSION
9
+ gem.authors = ["Andrey Deryabin"]
10
+ gem.email = ["deriabin@gmail.com"]
11
+ gem.description = 'An ActiveRecord adapter for MySQL, based on mysql gem.'
12
+ gem.summary = 'An ActiveRecord adapter for MySQL, based on mysql gem.'
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_dependency('mysql', '>= 2.9.0')
20
+ gem.add_dependency('activerecord', '>= 3.2.9')
21
+ gem.add_dependency('activesupport', '>= 3.2.9')
22
+ end
@@ -0,0 +1,565 @@
1
+ require 'active_record/connection_adapters/abstract_mysql_adapter'
2
+ require 'active_record/connection_adapters/statement_pool'
3
+ require 'active_support/core_ext/hash/keys'
4
+
5
+ gem 'mysql', '~> 2.9'
6
+ require 'mysql'
7
+
8
+ class Mysql
9
+ class Time
10
+ def to_date
11
+ Date.new(year, month, day)
12
+ end
13
+ end
14
+ class Stmt; include Enumerable end
15
+ class Result; include Enumerable end
16
+ end
17
+
18
+ module ActiveRecord
19
+ module ConnectionHandling
20
+ # Establishes a connection to the database that's used by all Active Record objects.
21
+ def mysql_connection(config) # :nodoc:
22
+ config = config.symbolize_keys
23
+ host = config[:host]
24
+ port = config[:port]
25
+ socket = config[:socket]
26
+ username = config[:username] ? config[:username].to_s : 'root'
27
+ password = config[:password].to_s
28
+ database = config[:database]
29
+
30
+ mysql = Mysql.init
31
+ mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey]
32
+
33
+ default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0
34
+ default_flags |= Mysql::CLIENT_FOUND_ROWS if Mysql.const_defined?(:CLIENT_FOUND_ROWS)
35
+ options = [host, username, password, database, port, socket, default_flags]
36
+ ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config)
37
+ end
38
+ end
39
+
40
+ module ConnectionAdapters
41
+ # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with
42
+ # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/).
43
+ #
44
+ # Options:
45
+ #
46
+ # * <tt>:host</tt> - Defaults to "localhost".
47
+ # * <tt>:port</tt> - Defaults to 3306.
48
+ # * <tt>:socket</tt> - Defaults to "/tmp/mysql.sock".
49
+ # * <tt>:username</tt> - Defaults to "root"
50
+ # * <tt>:password</tt> - Defaults to nothing.
51
+ # * <tt>:database</tt> - The name of the database. No default, must be provided.
52
+ # * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
53
+ # * <tt>:reconnect</tt> - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html).
54
+ # * <tt>:strict</tt> - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.5/en/server-sql-mode.html)
55
+ # * <tt>:sslca</tt> - Necessary to use MySQL with an SSL connection.
56
+ # * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
57
+ # * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
58
+ # * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
59
+ # * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
60
+ #
61
+ class MysqlAdapter < AbstractMysqlAdapter
62
+
63
+ class Column < AbstractMysqlAdapter::Column #:nodoc:
64
+ def self.string_to_time(value)
65
+ return super unless Mysql::Time === value
66
+ new_time(
67
+ value.year,
68
+ value.month,
69
+ value.day,
70
+ value.hour,
71
+ value.minute,
72
+ value.second,
73
+ value.second_part)
74
+ end
75
+
76
+ def self.string_to_dummy_time(v)
77
+ return super unless Mysql::Time === v
78
+ new_time(2000, 01, 01, v.hour, v.minute, v.second, v.second_part)
79
+ end
80
+
81
+ def self.string_to_date(v)
82
+ return super unless Mysql::Time === v
83
+ new_date(v.year, v.month, v.day)
84
+ end
85
+
86
+ def adapter
87
+ MysqlAdapter
88
+ end
89
+ end
90
+
91
+ ADAPTER_NAME = 'MySQL'
92
+
93
+ class StatementPool < ConnectionAdapters::StatementPool
94
+ def initialize(connection, max = 1000)
95
+ super
96
+ @cache = Hash.new { |h,pid| h[pid] = {} }
97
+ end
98
+
99
+ def each(&block); cache.each(&block); end
100
+ def key?(key); cache.key?(key); end
101
+ def [](key); cache[key]; end
102
+ def length; cache.length; end
103
+ def delete(key); cache.delete(key); end
104
+
105
+ def []=(sql, key)
106
+ while @max <= cache.size
107
+ cache.shift.last[:stmt].close
108
+ end
109
+ cache[sql] = key
110
+ end
111
+
112
+ def clear
113
+ cache.values.each do |hash|
114
+ hash[:stmt].close
115
+ end
116
+ cache.clear
117
+ end
118
+
119
+ private
120
+ def cache
121
+ @cache[Process.pid]
122
+ end
123
+ end
124
+
125
+ def initialize(connection, logger, connection_options, config)
126
+ super
127
+ @statements = StatementPool.new(@connection,
128
+ config.fetch(:statement_limit) { 1000 })
129
+ @client_encoding = nil
130
+ connect
131
+ end
132
+
133
+ # Returns true, since this connection adapter supports prepared statement
134
+ # caching.
135
+ def supports_statement_cache?
136
+ true
137
+ end
138
+
139
+ # HELPER METHODS ===========================================
140
+
141
+ def each_hash(result) # :nodoc:
142
+ if block_given?
143
+ result.each_hash do |row|
144
+ row.symbolize_keys!
145
+ yield row
146
+ end
147
+ else
148
+ to_enum(:each_hash, result)
149
+ end
150
+ end
151
+
152
+ def new_column(field, default, type, null, collation) # :nodoc:
153
+ Column.new(field, default, type, null, collation, strict_mode?)
154
+ end
155
+
156
+ def error_number(exception) # :nodoc:
157
+ exception.errno if exception.respond_to?(:errno)
158
+ end
159
+
160
+ # QUOTING ==================================================
161
+
162
+ def type_cast(value, column)
163
+ return super unless value == true || value == false
164
+
165
+ value ? 1 : 0
166
+ end
167
+
168
+ def quote_string(string) #:nodoc:
169
+ @connection.quote(string)
170
+ end
171
+
172
+ # CONNECTION MANAGEMENT ====================================
173
+
174
+ def active?
175
+ if @connection.respond_to?(:stat)
176
+ @connection.stat
177
+ else
178
+ @connection.query 'select 1'
179
+ end
180
+
181
+ # mysql-ruby doesn't raise an exception when stat fails.
182
+ if @connection.respond_to?(:errno)
183
+ @connection.errno.zero?
184
+ else
185
+ true
186
+ end
187
+ rescue Mysql::Error
188
+ false
189
+ end
190
+
191
+ def reconnect!
192
+ super
193
+ disconnect!
194
+ connect
195
+ end
196
+
197
+ # Disconnects from the database if already connected. Otherwise, this
198
+ # method does nothing.
199
+ def disconnect!
200
+ super
201
+ @connection.close rescue nil
202
+ end
203
+
204
+ def reset!
205
+ if @connection.respond_to?(:change_user)
206
+ # See http://bugs.mysql.com/bug.php?id=33540 -- the workaround way to
207
+ # reset the connection is to change the user to the same user.
208
+ @connection.change_user(@config[:username], @config[:password], @config[:database])
209
+ configure_connection
210
+ end
211
+ end
212
+
213
+ # DATABASE STATEMENTS ======================================
214
+
215
+ def select_rows(sql, name = nil)
216
+ @connection.query_with_result = true
217
+ rows = exec_query(sql, name).rows
218
+ @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
219
+ rows
220
+ end
221
+
222
+ # Clears the prepared statements cache.
223
+ def clear_cache!
224
+ @statements.clear
225
+ end
226
+
227
+ # Taken from here:
228
+ # https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
229
+ # Author: TOMITA Masahiro <tommy@tmtm.org>
230
+ ENCODINGS = {
231
+ "armscii8" => nil,
232
+ "ascii" => Encoding::US_ASCII,
233
+ "big5" => Encoding::Big5,
234
+ "binary" => Encoding::ASCII_8BIT,
235
+ "cp1250" => Encoding::Windows_1250,
236
+ "cp1251" => Encoding::Windows_1251,
237
+ "cp1256" => Encoding::Windows_1256,
238
+ "cp1257" => Encoding::Windows_1257,
239
+ "cp850" => Encoding::CP850,
240
+ "cp852" => Encoding::CP852,
241
+ "cp866" => Encoding::IBM866,
242
+ "cp932" => Encoding::Windows_31J,
243
+ "dec8" => nil,
244
+ "eucjpms" => Encoding::EucJP_ms,
245
+ "euckr" => Encoding::EUC_KR,
246
+ "gb2312" => Encoding::EUC_CN,
247
+ "gbk" => Encoding::GBK,
248
+ "geostd8" => nil,
249
+ "greek" => Encoding::ISO_8859_7,
250
+ "hebrew" => Encoding::ISO_8859_8,
251
+ "hp8" => nil,
252
+ "keybcs2" => nil,
253
+ "koi8r" => Encoding::KOI8_R,
254
+ "koi8u" => Encoding::KOI8_U,
255
+ "latin1" => Encoding::ISO_8859_1,
256
+ "latin2" => Encoding::ISO_8859_2,
257
+ "latin5" => Encoding::ISO_8859_9,
258
+ "latin7" => Encoding::ISO_8859_13,
259
+ "macce" => Encoding::MacCentEuro,
260
+ "macroman" => Encoding::MacRoman,
261
+ "sjis" => Encoding::SHIFT_JIS,
262
+ "swe7" => nil,
263
+ "tis620" => Encoding::TIS_620,
264
+ "ucs2" => Encoding::UTF_16BE,
265
+ "ujis" => Encoding::EucJP_ms,
266
+ "utf8" => Encoding::UTF_8,
267
+ "utf8mb4" => Encoding::UTF_8,
268
+ }
269
+
270
+ # Get the client encoding for this database
271
+ def client_encoding
272
+ return @client_encoding if @client_encoding
273
+
274
+ result = exec_query(
275
+ "SHOW VARIABLES WHERE Variable_name = 'character_set_client'",
276
+ 'SCHEMA')
277
+ @client_encoding = ENCODINGS[result.rows.last.last]
278
+ end
279
+
280
+ def exec_query(sql, name = 'SQL', binds = [])
281
+ # If the configuration sets prepared_statements:false, binds will
282
+ # always be empty, since the bind variables will have been already
283
+ # substituted and removed from binds by BindVisitor, so this will
284
+ # effectively disable prepared statement usage completely.
285
+ if binds.empty?
286
+ result_set, affected_rows = exec_without_stmt(sql, name)
287
+ else
288
+ result_set, affected_rows = exec_stmt(sql, name, binds)
289
+ end
290
+
291
+ yield affected_rows if block_given?
292
+
293
+ result_set
294
+ end
295
+
296
+ def last_inserted_id(result)
297
+ @connection.insert_id
298
+ end
299
+
300
+ module Fields
301
+ class Type
302
+ def type; end
303
+
304
+ def type_cast_for_write(value)
305
+ value
306
+ end
307
+ end
308
+
309
+ class Identity < Type
310
+ def type_cast(value); value; end
311
+ end
312
+
313
+ class Integer < Type
314
+ def type_cast(value)
315
+ return if value.nil?
316
+
317
+ value.to_i rescue value ? 1 : 0
318
+ end
319
+ end
320
+
321
+ class Date < Type
322
+ def type; :date; end
323
+
324
+ def type_cast(value)
325
+ return if value.nil?
326
+
327
+ # FIXME: probably we can improve this since we know it is mysql
328
+ # specific
329
+ ConnectionAdapters::Column.value_to_date value
330
+ end
331
+ end
332
+
333
+ class DateTime < Type
334
+ def type; :datetime; end
335
+
336
+ def type_cast(value)
337
+ return if value.nil?
338
+
339
+ # FIXME: probably we can improve this since we know it is mysql
340
+ # specific
341
+ ConnectionAdapters::Column.string_to_time value
342
+ end
343
+ end
344
+
345
+ class Time < Type
346
+ def type; :time; end
347
+
348
+ def type_cast(value)
349
+ return if value.nil?
350
+
351
+ # FIXME: probably we can improve this since we know it is mysql
352
+ # specific
353
+ ConnectionAdapters::Column.string_to_dummy_time value
354
+ end
355
+ end
356
+
357
+ class Float < Type
358
+ def type; :float; end
359
+
360
+ def type_cast(value)
361
+ return if value.nil?
362
+
363
+ value.to_f
364
+ end
365
+ end
366
+
367
+ class Decimal < Type
368
+ def type_cast(value)
369
+ return if value.nil?
370
+
371
+ ConnectionAdapters::Column.value_to_decimal value
372
+ end
373
+ end
374
+
375
+ class Boolean < Type
376
+ def type_cast(value)
377
+ return if value.nil?
378
+
379
+ ConnectionAdapters::Column.value_to_boolean value
380
+ end
381
+ end
382
+
383
+ TYPES = {}
384
+
385
+ # Register an MySQL +type_id+ with a typcasting object in
386
+ # +type+.
387
+ def self.register_type(type_id, type)
388
+ TYPES[type_id] = type
389
+ end
390
+
391
+ def self.alias_type(new, old)
392
+ TYPES[new] = TYPES[old]
393
+ end
394
+
395
+ register_type Mysql::Field::TYPE_TINY, Fields::Boolean.new
396
+ register_type Mysql::Field::TYPE_LONG, Fields::Integer.new
397
+ alias_type Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_LONG
398
+ alias_type Mysql::Field::TYPE_NEWDECIMAL, Mysql::Field::TYPE_LONG
399
+
400
+ register_type Mysql::Field::TYPE_VAR_STRING, Fields::Identity.new
401
+ register_type Mysql::Field::TYPE_BLOB, Fields::Identity.new
402
+ register_type Mysql::Field::TYPE_DATE, Fields::Date.new
403
+ register_type Mysql::Field::TYPE_DATETIME, Fields::DateTime.new
404
+ register_type Mysql::Field::TYPE_TIME, Fields::Time.new
405
+ register_type Mysql::Field::TYPE_FLOAT, Fields::Float.new
406
+
407
+ Mysql::Field.constants.grep(/TYPE/).map { |class_name|
408
+ Mysql::Field.const_get class_name
409
+ }.reject { |const| TYPES.key? const }.each do |const|
410
+ register_type const, Fields::Identity.new
411
+ end
412
+ end
413
+
414
+ def exec_without_stmt(sql, name = 'SQL') # :nodoc:
415
+ # Some queries, like SHOW CREATE TABLE don't work through the prepared
416
+ # statement API. For those queries, we need to use this method. :'(
417
+ log(sql, name) do
418
+ result = @connection.query(sql)
419
+ affected_rows = @connection.affected_rows
420
+
421
+ if result
422
+ types = {}
423
+ result.fetch_fields.each { |field|
424
+ if field.decimals > 0
425
+ types[field.name] = Fields::Decimal.new
426
+ else
427
+ types[field.name] = Fields::TYPES.fetch(field.type) {
428
+ Fields::Identity.new
429
+ }
430
+ end
431
+ }
432
+ result_set = ActiveRecord::Result.new(types.keys, result.to_a, types)
433
+ result.free
434
+ else
435
+ result_set = ActiveRecord::Result.new([], [])
436
+ end
437
+
438
+ [result_set, affected_rows]
439
+ end
440
+ end
441
+
442
+ def execute_and_free(sql, name = nil)
443
+ result = execute(sql, name)
444
+ ret = yield result
445
+ result.free
446
+ ret
447
+ end
448
+
449
+ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
450
+ super sql, name
451
+ id_value || @connection.insert_id
452
+ end
453
+ alias :create :insert_sql
454
+
455
+ def exec_delete(sql, name, binds)
456
+ affected_rows = 0
457
+
458
+ exec_query(sql, name, binds) do |n|
459
+ affected_rows = n
460
+ end
461
+
462
+ affected_rows
463
+ end
464
+ alias :exec_update :exec_delete
465
+
466
+ def begin_db_transaction #:nodoc:
467
+ exec_query "BEGIN"
468
+ rescue Mysql::Error
469
+ # Transactions aren't supported
470
+ end
471
+
472
+ private
473
+
474
+ def exec_stmt(sql, name, binds)
475
+ cache = {}
476
+ log(sql, name, binds) do
477
+ if binds.empty?
478
+ stmt = @connection.prepare(sql)
479
+ else
480
+ cache = @statements[sql] ||= {
481
+ :stmt => @connection.prepare(sql)
482
+ }
483
+ stmt = cache[:stmt]
484
+ end
485
+
486
+ begin
487
+ stmt.execute(*binds.map { |col, val| type_cast(val, col) })
488
+ rescue Mysql::Error => e
489
+ # Older versions of MySQL leave the prepared statement in a bad
490
+ # place when an error occurs. To support older mysql versions, we
491
+ # need to close the statement and delete the statement from the
492
+ # cache.
493
+ stmt.close
494
+ @statements.delete sql
495
+ raise e
496
+ end
497
+
498
+ cols = nil
499
+ if metadata = stmt.result_metadata
500
+ cols = cache[:cols] ||= metadata.fetch_fields.map { |field|
501
+ field.name
502
+ }
503
+ end
504
+
505
+ result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
506
+ affected_rows = stmt.affected_rows
507
+
508
+ stmt.result_metadata.free if cols
509
+ stmt.free_result
510
+ stmt.close if binds.empty?
511
+
512
+ [result_set, affected_rows]
513
+ end
514
+ end
515
+
516
+ def connect
517
+ encoding = @config[:encoding]
518
+ if encoding
519
+ @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
520
+ end
521
+
522
+ if @config[:sslca] || @config[:sslkey]
523
+ @connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
524
+ end
525
+
526
+ @connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
527
+ @connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
528
+ @connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
529
+
530
+ @connection.real_connect(*@connection_options)
531
+
532
+ # reconnect must be set after real_connect is called, because real_connect sets it to false internally
533
+ @connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=)
534
+
535
+ configure_connection
536
+ end
537
+
538
+ def configure_connection
539
+ encoding = @config[:encoding]
540
+ execute("SET NAMES '#{encoding}'", :skip_logging) if encoding
541
+
542
+ # By default, MySQL 'where id is null' selects the last inserted id.
543
+ # Turn this off. http://dev.rubyonrails.org/ticket/6778
544
+ execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
545
+
546
+ # Make MySQL reject illegal values rather than truncating or
547
+ # blanking them. See
548
+ # http://dev.mysql.com/doc/refman/5.5/en/server-sql-mode.html#sqlmode_strict_all_tables
549
+ execute("SET SQL_MODE='STRICT_ALL_TABLES'", :skip_logging) if strict_mode?
550
+ end
551
+
552
+ def select(sql, name = nil, binds = [])
553
+ @connection.query_with_result = true
554
+ rows = exec_query(sql, name, binds)
555
+ @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
556
+ rows
557
+ end
558
+
559
+ # Returns the version of the connected MySQL server.
560
+ def version
561
+ @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
562
+ end
563
+ end
564
+ end
565
+ end
@@ -0,0 +1 @@
1
+ require "activerecord-mysql-adapter/version"
@@ -0,0 +1,3 @@
1
+ module ActiverecordMysqlAdapter
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-mysql-adapter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrey Deryabin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mysql
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.9.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: activerecord
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.9
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.2.9
46
+ - !ruby/object:Gem::Dependency
47
+ name: activesupport
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 3.2.9
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.9
62
+ description: An ActiveRecord adapter for MySQL, based on mysql gem.
63
+ email:
64
+ - deriabin@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - activerecord-mysql-adapter.gemspec
75
+ - lib/active_record/connection_adapters/mysql_adapter.rb
76
+ - lib/activerecord-mysql-adapter.rb
77
+ - lib/activerecord-mysql-adapter/version.rb
78
+ homepage: ''
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.24
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: An ActiveRecord adapter for MySQL, based on mysql gem.
102
+ test_files: []