activerecord-mysql-adapter 0.0.1

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,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: []