Skip to content
This repository

Break support mysql adapter #6030

Closed
wants to merge 2 commits into from
Andrey Deryabin

In continue of break support antiquity I suggest to break support mysql adapter (to use only mysql2).

Really, what is reason to have 2 adapters for one DBMS? mysql gem doesn't support EXPLAIN. It's really funny and sad.

Jeremy Kemper
Owner

:+1:

Would be a good idea to extract as a activerecord-mysql-adapter gem for folks who want to continue using it (for whatever reason)

José Valim
Owner

I am José Valim and I approve this message.

Larz Conwell

:+1: I like this idea, I saw this earlier and thought it was weird to keep it.

Piotr Sarnacki
Collaborator

@jeremy I would assume that no one will be using it in 4.0 ;) If that's not the case someone can still extract it based on that commit, but I would not wait with merging this.

Rafael Mendonça França
Owner

Remember that mysql2 doesn't work very well on Windows.

Piotr Sarnacki
Collaborator

@rafaelfranca bummer, I didn't know that.

Erich Menge

@aderyabin I was thinking about doing the same thing. @carlosantoniodasilva pointed me to this PR. Were you planning on extracting the mysql adapter out into a gem?

Guillermo Iguaran
Owner

is possible get mysql2 gem working fine under Windows?

I have a project running under a Windows machine using mysql2 and is working without any problems, I'm using Ruby 1.9.3 and Rails 3.2 (installed both with RailsInstaller)

cc @luislavena

Edit:
http://github.com/brianmario/mysql2/issues#issue/8
http://paul-wong-jr.blogspot.com/2011/06/getting-mysql2-gem-to-work-with-ruby-on.html
http://rorguide.blogspot.com/2011/03/installing-mysql2-gem-on-ruby-192-and.html

Andrey Deryabin
Luis Lavena

I haven't played with mysql2 in long time, but it had issues on Windows (like blocking operations) that made really hard get some stuff done.

This was caused by the way Ruby 1.8 differs from Ruby 1.9: changes to make Ruby 1.9 work broke Ruby 1.8 functionality.

If mysql2 works on a version that is only 1.9.x (lets say 0.4 or something) then I think things could work.

I still need to test it out.

Francesco Rodríguez

@aderyabin any news? Could you rebase this?

Rafael Mendonça França

@aderyabin are you still interessed to work on this pull request? I think if extract it to a adapter like @jeremy pointed we don't need to worry about Windows failures.

Andrey Deryabin

I''ll end work on this pull request this week.

Rafael Mendonça França

Awesome!! I look forward to see this merged before Rails 4.0

Andrey Deryabin

@rafaelfranca I finished work. Please review and merge.

Steve Klabnik
Collaborator

Doesn't merge cleanly.

Rafael Mendonça França

@aderyabin we need to review/move the tests under activerecord/test/cases/adapters/mysql to the gem

Aaron Patterson
Owner

So, I'm kind of :-1: on this pull request. One, I know that folks at twitter use Rails 3.2.x with mysql (and won't use mysql2). So there are > 0 users of the mysql adapter. The second reason is that it's likely that I'll end up maintaining the adapter, and it's just easier for me to maintain it while it's in core.

If this is just to break it out of core, but no maintainer is volunteering, then :-1:. To casual observers, it may seem strange that we ship to mysql adapters, but I know for a fact that people use both mysql and mysql2. Which means this becomes a question of "who will maintain the adapter?".

Currently the answer is @tenderlove. If the answer is to remain @tenderlove, then we should not remove this from core.

Rafael Mendonça França

It is a good reason. I'll close this pull request. If anyone want to take the project we can reopen.

@aderyabin thank you so much for the pull request.

Rafael Mendonça França rafaelfranca closed this November 29, 2012
Andrey Deryabin

@tenderlove. It's very strange. Why folks at Twitter can move to rails4 and can't to mysql2? Moving from rails 2 to rails 3 had more troubles than from mysql to mysql2.

Aaron Patterson
Owner

@aderyabin AFAIK, it's because they maintain a fork of the mysql gem. But I'm not 100% certain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
1  .travis.yml
@@ -7,7 +7,6 @@ rvm:
7 7
 env:
8 8
   - "GEM=railties"
9 9
   - "GEM=ap,am,amo,as"
10  
-  - "GEM=ar:mysql"
11 10
   - "GEM=ar:mysql2"
12 11
   - "GEM=ar:sqlite3"
13 12
   - "GEM=ar:postgresql"
1  Gemfile
@@ -51,7 +51,6 @@ platforms :ruby do
51 51
 
52 52
   group :db do
53 53
     gem 'pg', '>= 0.11.0'
54  
-    gem 'mysql', '>= 2.9.0'
55 54
     gem 'mysql2', '>= 0.3.10'
56 55
   end
57 56
 end
4  activerecord/CHANGELOG.md
Source Rendered
... ...
@@ -1,5 +1,9 @@
1 1
 ## Rails 4.0.0 (unreleased) ##
2 2
 
  3
+    *Andrey Deryabin*
  4
+
  5
+*   Move `mysql` adapter from core to `activerecord-mysql-adapter` gem.
  6
+
3 7
 *   Prevent mass assignment to the type column of polymorphic associations when using `build`
4 8
     Fix #8265
5 9
 
2  activerecord/README.rdoc
Source Rendered
@@ -136,7 +136,7 @@ A short rundown of some of the major features:
136 136
     )
137 137
 
138 138
   {Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
139  
-  MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html],
  139
+  MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
140 140
   PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
141 141
   SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
142 142
 
4  activerecord/RUNNING_UNIT_TESTS
@@ -21,9 +21,9 @@ environment variable:
21 21
 
22 22
 You can run all the tests for a given database via rake:
23 23
 
24  
-  $ rake test_mysql
  24
+  $ rake test_mysql2
25 25
 
26  
-The 'rake test' task will run all the tests for mysql, mysql2, sqlite3 and postgresql.
  26
+The 'rake test' task will run all the tests for mysql2, sqlite3 and postgresql.
27 27
 
28 28
 == Custom Config file
29 29
 
12  activerecord/Rakefile
@@ -19,14 +19,14 @@ def run_without_aborting(*tasks)
19 19
   abort "Errors running #{errors.join(', ')}" if errors.any?
20 20
 end
21 21
 
22  
-desc 'Run mysql, mysql2, sqlite, and postgresql tests by default'
  22
+desc 'Run mysql2, sqlite, and postgresql tests by default'
23 23
 task :default => :test
24 24
 
25  
-desc 'Run mysql, mysql2, sqlite, and postgresql tests'
  25
+desc 'Run mysql2, sqlite, and postgresql tests'
26 26
 task :test do
27 27
   tasks = defined?(JRUBY_VERSION) ?
28 28
     %w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) :
29  
-    %w(test_mysql test_mysql2 test_sqlite3 test_postgresql)
  29
+    %w(test_mysql2 test_sqlite3 test_postgresql)
30 30
   run_without_aborting(*tasks)
31 31
 end
32 32
 
@@ -34,7 +34,7 @@ namespace :test do
34 34
   task :isolated do
35 35
     tasks = defined?(JRUBY_VERSION) ?
36 36
       %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) :
37  
-      %w(isolated_test_mysql isolated_test_mysql2 isolated_test_sqlite3 isolated_test_postgresql)
  37
+      %w(isolated_test_mysql2 isolated_test_sqlite3 isolated_test_postgresql)
38 38
     run_without_aborting(*tasks)
39 39
   end
40 40
 end
@@ -87,14 +87,14 @@ task :test_sqlite3 => [
87 87
 namespace :mysql do
88 88
   desc 'Build the MySQL test databases'
89 89
   task :build_databases do
90  
-    config = ARTest.config['connections']['mysql']
  90
+    config = ARTest.config['connections']['mysql2']
91 91
     %x( mysql --user=#{config['arunit']['username']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
92 92
     %x( mysql --user=#{config['arunit2']['username']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
93 93
   end
94 94
 
95 95
   desc 'Drop the MySQL test databases'
96 96
   task :drop_databases do
97  
-    config = ARTest.config['connections']['mysql']
  97
+    config = ARTest.config['connections']['mysql2']
98 98
     %x( mysqladmin --user=#{config['arunit']['username']} -f drop #{config['arunit']['database']} )
99 99
     %x( mysqladmin --user=#{config['arunit2']['username']} -f drop #{config['arunit2']['database']} )
100 100
   end
2  activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -241,7 +241,7 @@ def verify!(*ignored)
241 241
       end
242 242
 
243 243
       # Provides access to the underlying database driver for this adapter. For
244  
-      # example, this method returns a Mysql object in case of MysqlAdapter,
  244
+      # example, this method returns a Mysql2 object in case of Mysql2Adapter,
245 245
       # and a PGconn object in case of PostgreSQLAdapter.
246 246
       #
247 247
       # This is useful for when you need to call a proprietary method such as
1  activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -66,6 +66,7 @@ def connection_url_to_hash(url) # :nodoc:
66 66
           config = URI.parse url
67 67
           adapter = config.scheme
68 68
           adapter = "postgresql" if adapter == "postgres"
  69
+          adapter = "mysql2"     if adapter == "mysql"
69 70
           spec = { :adapter  => adapter,
70 71
                    :username => config.user,
71 72
                    :password => config.password,
565  activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
... ...
@@ -1,565 +0,0 @@
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
2  activerecord/lib/active_record/connection_handling.rb
@@ -5,7 +5,7 @@ module ConnectionHandling
5 5
     # example for regular databases (MySQL, Postgresql, etc):
6 6
     #
7 7
     #   ActiveRecord::Base.establish_connection(
8  
-    #     adapter:  "mysql",
  8
+    #     adapter:  "mysql2",
9 9
     #     host:     "localhost",
10 10
     #     username: "myuser",
11 11
     #     password: "mypass",
1  activerecord/lib/active_record/validations/uniqueness.rb
@@ -208,7 +208,6 @@ module ClassMethods
208 208
       #
209 209
       # The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:
210 210
       #
211  
-      # * ActiveRecord::ConnectionAdapters::MysqlAdapter.
212 211
       # * ActiveRecord::ConnectionAdapters::Mysql2Adapter.
213 212
       # * ActiveRecord::ConnectionAdapters::SQLite3Adapter.
214 213
       # * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.
6  activerecord/test/cases/connection_specification/resolver_test.rb
@@ -12,7 +12,7 @@ def test_url_host_no_db
12 12
           skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
13 13
           spec = resolve 'mysql://foo?encoding=utf8'
14 14
           assert_equal({
15  
-            :adapter  => "mysql",
  15
+            :adapter  => "mysql2",
16 16
             :host     => "foo",
17 17
             :encoding => "utf8" }, spec)
18 18
         end
@@ -21,7 +21,7 @@ def test_url_host_db
21 21
           skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
22 22
           spec = resolve 'mysql://foo/bar?encoding=utf8'
23 23
           assert_equal({
24  
-            :adapter  => "mysql",
  24
+            :adapter  => "mysql2",
25 25
             :database => "bar",
26 26
             :host     => "foo",
27 27
             :encoding => "utf8" }, spec)
@@ -31,7 +31,7 @@ def test_url_port
31 31
           skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
32 32
           spec = resolve 'mysql://foo:123?encoding=utf8'
33 33
           assert_equal({
34  
-            :adapter  => "mysql",
  34
+            :adapter  => "mysql2",
35 35
             :port     => 123,
36 36
             :host     => "foo",
37 37
             :encoding => "utf8" }, spec)
2  activerecord/test/cases/helper.rb
@@ -22,8 +22,6 @@
22 22
 # Connect to the database
23 23
 ARTest.connect
24 24
 
25  
-require 'support/mysql'
26  
-
27 25
 # Quote "type" if it's a reserved word for the current connection.
28 26
 QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
29 27
 
11  activerecord/test/support/mysql.rb
... ...
@@ -1,11 +0,0 @@
1  
-if defined?(Mysql)
2  
-  class Mysql
3  
-    class Error
4  
-      # This monkey patch fixes annoy warning with mysql-2.8.1.gem when executing testcases.
5  
-      def errno_with_fix_warnings
6  
-        silence_warnings { errno_without_fix_warnings }
7  
-      end
8  
-      alias_method_chain :errno, :fix_warnings
9  
-    end
10  
-  end
11  
-end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.