activerecord 3.2.22.5 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1024 -543
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +20 -29
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +55 -44
  7. data/lib/active_record/aggregations.rb +40 -34
  8. data/lib/active_record/associations.rb +204 -276
  9. data/lib/active_record/associations/alias_tracker.rb +1 -1
  10. data/lib/active_record/associations/association.rb +30 -35
  11. data/lib/active_record/associations/association_scope.rb +40 -40
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -2
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +35 -57
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +92 -88
  21. data/lib/active_record/associations/collection_proxy.rb +913 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
  23. data/lib/active_record/associations/has_many_association.rb +35 -9
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -14
  25. data/lib/active_record/associations/has_one_association.rb +33 -13
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +2 -2
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  30. data/lib/active_record/associations/join_helper.rb +1 -11
  31. data/lib/active_record/associations/preloader.rb +14 -17
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/singular_association.rb +11 -11
  39. data/lib/active_record/associations/through_association.rb +2 -2
  40. data/lib/active_record/attribute_assignment.rb +133 -153
  41. data/lib/active_record/attribute_methods.rb +196 -93
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  43. data/lib/active_record/attribute_methods/dirty.rb +31 -28
  44. data/lib/active_record/attribute_methods/primary_key.rb +38 -30
  45. data/lib/active_record/attribute_methods/query.rb +5 -4
  46. data/lib/active_record/attribute_methods/read.rb +62 -91
  47. data/lib/active_record/attribute_methods/serialization.rb +97 -66
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
  49. data/lib/active_record/attribute_methods/write.rb +32 -39
  50. data/lib/active_record/autosave_association.rb +56 -70
  51. data/lib/active_record/base.rb +53 -450
  52. data/lib/active_record/callbacks.rb +53 -18
  53. data/lib/active_record/coders/yaml_column.rb +11 -9
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
  65. data/lib/active_record/connection_adapters/column.rb +46 -24
  66. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  67. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  68. data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
  69. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  70. data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
  71. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  75. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
  76. data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
  77. data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
  79. data/lib/active_record/connection_handling.rb +98 -0
  80. data/lib/active_record/core.rb +428 -0
  81. data/lib/active_record/counter_cache.rb +106 -108
  82. data/lib/active_record/dynamic_matchers.rb +110 -63
  83. data/lib/active_record/errors.rb +25 -8
  84. data/lib/active_record/explain.rb +8 -58
  85. data/lib/active_record/explain_subscriber.rb +6 -3
  86. data/lib/active_record/fixture_set/file.rb +56 -0
  87. data/lib/active_record/fixtures.rb +146 -148
  88. data/lib/active_record/inheritance.rb +77 -59
  89. data/lib/active_record/integration.rb +5 -5
  90. data/lib/active_record/locale/en.yml +8 -1
  91. data/lib/active_record/locking/optimistic.rb +38 -42
  92. data/lib/active_record/locking/pessimistic.rb +4 -4
  93. data/lib/active_record/log_subscriber.rb +19 -9
  94. data/lib/active_record/migration.rb +318 -153
  95. data/lib/active_record/migration/command_recorder.rb +90 -31
  96. data/lib/active_record/migration/join_table.rb +15 -0
  97. data/lib/active_record/model_schema.rb +69 -92
  98. data/lib/active_record/nested_attributes.rb +113 -148
  99. data/lib/active_record/null_relation.rb +65 -0
  100. data/lib/active_record/persistence.rb +188 -97
  101. data/lib/active_record/query_cache.rb +18 -36
  102. data/lib/active_record/querying.rb +19 -15
  103. data/lib/active_record/railtie.rb +91 -36
  104. data/lib/active_record/railties/console_sandbox.rb +0 -2
  105. data/lib/active_record/railties/controller_runtime.rb +2 -2
  106. data/lib/active_record/railties/databases.rake +90 -309
  107. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  108. data/lib/active_record/readonly_attributes.rb +7 -3
  109. data/lib/active_record/reflection.rb +72 -56
  110. data/lib/active_record/relation.rb +241 -157
  111. data/lib/active_record/relation/batches.rb +25 -22
  112. data/lib/active_record/relation/calculations.rb +143 -121
  113. data/lib/active_record/relation/delegation.rb +96 -18
  114. data/lib/active_record/relation/finder_methods.rb +117 -183
  115. data/lib/active_record/relation/merger.rb +133 -0
  116. data/lib/active_record/relation/predicate_builder.rb +90 -42
  117. data/lib/active_record/relation/query_methods.rb +666 -136
  118. data/lib/active_record/relation/spawn_methods.rb +43 -150
  119. data/lib/active_record/result.rb +33 -6
  120. data/lib/active_record/sanitization.rb +24 -50
  121. data/lib/active_record/schema.rb +19 -12
  122. data/lib/active_record/schema_dumper.rb +31 -39
  123. data/lib/active_record/schema_migration.rb +36 -0
  124. data/lib/active_record/scoping.rb +0 -124
  125. data/lib/active_record/scoping/default.rb +48 -45
  126. data/lib/active_record/scoping/named.rb +74 -103
  127. data/lib/active_record/serialization.rb +6 -2
  128. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  129. data/lib/active_record/store.rb +119 -15
  130. data/lib/active_record/tasks/database_tasks.rb +158 -0
  131. data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
  132. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  133. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  134. data/lib/active_record/test_case.rb +61 -38
  135. data/lib/active_record/timestamp.rb +8 -9
  136. data/lib/active_record/transactions.rb +65 -51
  137. data/lib/active_record/validations.rb +17 -15
  138. data/lib/active_record/validations/associated.rb +20 -14
  139. data/lib/active_record/validations/presence.rb +65 -0
  140. data/lib/active_record/validations/uniqueness.rb +93 -52
  141. data/lib/active_record/version.rb +4 -4
  142. data/lib/rails/generators/active_record.rb +3 -5
  143. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
  144. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  145. data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
  146. data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
  147. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  148. metadata +53 -46
  149. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  150. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  151. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  152. data/lib/active_record/dynamic_finder_match.rb +0 -68
  153. data/lib/active_record/dynamic_scope_match.rb +0 -23
  154. data/lib/active_record/fixtures/file.rb +0 -65
  155. data/lib/active_record/identity_map.rb +0 -162
  156. data/lib/active_record/observer.rb +0 -121
  157. data/lib/active_record/session_store.rb +0 -360
  158. data/lib/rails/generators/active_record/migration.rb +0 -15
  159. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  160. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  161. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  162. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -4,16 +4,18 @@ gem 'mysql2', '~> 0.3.10'
4
4
  require 'mysql2'
5
5
 
6
6
  module ActiveRecord
7
- class Base
7
+ module ConnectionHandling
8
8
  # Establishes a connection to the database that's used by all Active Record objects.
9
- def self.mysql2_connection(config)
9
+ def mysql2_connection(config)
10
+ config = config.symbolize_keys
11
+
10
12
  config[:username] = 'root' if config[:username].nil?
11
13
 
12
14
  if Mysql2::Client.const_defined? :FOUND_ROWS
13
15
  config[:flags] = Mysql2::Client::FOUND_ROWS
14
16
  end
15
17
 
16
- client = Mysql2::Client.new(config.symbolize_keys)
18
+ client = Mysql2::Client.new(config)
17
19
  options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
18
20
  ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
19
21
  end
@@ -53,7 +55,7 @@ module ActiveRecord
53
55
  end
54
56
 
55
57
  def new_column(field, default, type, null, collation) # :nodoc:
56
- Column.new(field, default, type, null, collation)
58
+ Column.new(field, default, type, null, collation, strict_mode?)
57
59
  end
58
60
 
59
61
  def error_number(exception)
@@ -74,24 +76,22 @@ module ActiveRecord
74
76
  end
75
77
 
76
78
  def reconnect!
79
+ super
77
80
  disconnect!
78
81
  connect
79
82
  end
83
+ alias :reset! :reconnect!
80
84
 
81
85
  # Disconnects from the database if already connected.
82
86
  # Otherwise, this method does nothing.
83
87
  def disconnect!
88
+ super
84
89
  unless @connection.nil?
85
90
  @connection.close
86
91
  @connection = nil
87
92
  end
88
93
  end
89
94
 
90
- def reset!
91
- disconnect!
92
- connect
93
- end
94
-
95
95
  # DATABASE STATEMENTS ======================================
96
96
 
97
97
  def explain(arel, binds = [])
@@ -177,7 +177,7 @@ module ActiveRecord
177
177
  # # as values.
178
178
  # def select_one(sql, name = nil)
179
179
  # result = execute(sql, name)
180
- # result.each(:as => :hash) do |r|
180
+ # result.each(as: :hash) do |r|
181
181
  # return r
182
182
  # end
183
183
  # end
@@ -204,11 +204,9 @@ module ActiveRecord
204
204
 
205
205
  # Executes the SQL statement in the context of this connection.
206
206
  def execute(sql, name = nil)
207
- if @connection
208
- # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
209
- # made since we established the connection
210
- @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
211
- end
207
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
208
+ # made since we established the connection
209
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
212
210
 
213
211
  super
214
212
  end
@@ -223,7 +221,7 @@ module ActiveRecord
223
221
  # Returns an array of record hashes with the column names as keys and
224
222
  # column values as values.
225
223
  def select(sql, name = nil, binds = [])
226
- exec_query(sql, name).to_a
224
+ exec_query(sql, name)
227
225
  end
228
226
 
229
227
  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
@@ -232,7 +230,7 @@ module ActiveRecord
232
230
  end
233
231
  alias :create :insert_sql
234
232
 
235
- def exec_insert(sql, name, binds)
233
+ def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
236
234
  execute to_sql(sql, binds), name
237
235
  end
238
236
 
@@ -255,21 +253,7 @@ module ActiveRecord
255
253
 
256
254
  def configure_connection
257
255
  @connection.query_options.merge!(:as => :array)
258
-
259
- # By default, MySQL 'where id is null' selects the last inserted id.
260
- # Turn this off. http://dev.rubyonrails.org/ticket/6778
261
- variable_assignments = ['SQL_AUTO_IS_NULL=0']
262
- encoding = @config[:encoding]
263
-
264
- # make sure we set the encoding
265
- variable_assignments << "NAMES '#{encoding}'" if encoding
266
-
267
- # increase timeout so mysql server doesn't disconnect us
268
- wait_timeout = @config[:wait_timeout]
269
- wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
270
- variable_assignments << "@@wait_timeout = #{wait_timeout}"
271
-
272
- execute("SET #{variable_assignments.join(', ')}", :skip_logging)
256
+ super
273
257
  end
274
258
 
275
259
  def version
@@ -2,13 +2,11 @@ require 'active_record/connection_adapters/abstract_mysql_adapter'
2
2
  require 'active_record/connection_adapters/statement_pool'
3
3
  require 'active_support/core_ext/hash/keys'
4
4
 
5
- gem 'mysql', '~> 2.8'
5
+ gem 'mysql', '~> 2.9'
6
6
  require 'mysql'
7
7
 
8
8
  class Mysql
9
9
  class Time
10
- ###
11
- # This monkey patch is for test_additional_columns_from_join_table
12
10
  def to_date
13
11
  Date.new(year, month, day)
14
12
  end
@@ -18,9 +16,9 @@ class Mysql
18
16
  end
19
17
 
20
18
  module ActiveRecord
21
- class Base
19
+ module ConnectionHandling
22
20
  # Establishes a connection to the database that's used by all Active Record objects.
23
- def self.mysql_connection(config) # :nodoc:
21
+ def mysql_connection(config) # :nodoc:
24
22
  config = config.symbolize_keys
25
23
  host = config[:host]
26
24
  port = config[:port]
@@ -53,6 +51,8 @@ module ActiveRecord
53
51
  # * <tt>:database</tt> - The name of the database. No default, must be provided.
54
52
  # * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
55
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.0/en/server-sql-mode.html)
55
+ # * <tt>:variables</tt> - (Optional) A hash session variables to send as `SET @@SESSION.key = value` on each database connection. Use the value `:default` to set a variable to its DEFAULT value. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/set-statement.html).
56
56
  # * <tt>:sslca</tt> - Necessary to use MySQL with an SSL connection.
57
57
  # * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
58
58
  # * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
@@ -119,14 +119,14 @@ module ActiveRecord
119
119
 
120
120
  private
121
121
  def cache
122
- @cache[$$]
122
+ @cache[Process.pid]
123
123
  end
124
124
  end
125
125
 
126
126
  def initialize(connection, logger, connection_options, config)
127
127
  super
128
128
  @statements = StatementPool.new(@connection,
129
- config.fetch(:statement_limit) { 1000 })
129
+ self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
130
130
  @client_encoding = nil
131
131
  connect
132
132
  end
@@ -151,7 +151,7 @@ module ActiveRecord
151
151
  end
152
152
 
153
153
  def new_column(field, default, type, null, collation) # :nodoc:
154
- Column.new(field, default, type, null, collation)
154
+ Column.new(field, default, type, null, collation, strict_mode?)
155
155
  end
156
156
 
157
157
  def error_number(exception) # :nodoc:
@@ -190,14 +190,15 @@ module ActiveRecord
190
190
  end
191
191
 
192
192
  def reconnect!
193
+ super
193
194
  disconnect!
194
- clear_cache!
195
195
  connect
196
196
  end
197
197
 
198
198
  # Disconnects from the database if already connected. Otherwise, this
199
199
  # method does nothing.
200
200
  def disconnect!
201
+ super
201
202
  @connection.close rescue nil
202
203
  end
203
204
 
@@ -224,52 +225,48 @@ module ActiveRecord
224
225
  @statements.clear
225
226
  end
226
227
 
227
- if "<3".respond_to?(:encode)
228
- # Taken from here:
229
- # https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
230
- # Author: TOMITA Masahiro <tommy@tmtm.org>
231
- ENCODINGS = {
232
- "armscii8" => nil,
233
- "ascii" => Encoding::US_ASCII,
234
- "big5" => Encoding::Big5,
235
- "binary" => Encoding::ASCII_8BIT,
236
- "cp1250" => Encoding::Windows_1250,
237
- "cp1251" => Encoding::Windows_1251,
238
- "cp1256" => Encoding::Windows_1256,
239
- "cp1257" => Encoding::Windows_1257,
240
- "cp850" => Encoding::CP850,
241
- "cp852" => Encoding::CP852,
242
- "cp866" => Encoding::IBM866,
243
- "cp932" => Encoding::Windows_31J,
244
- "dec8" => nil,
245
- "eucjpms" => Encoding::EucJP_ms,
246
- "euckr" => Encoding::EUC_KR,
247
- "gb2312" => Encoding::EUC_CN,
248
- "gbk" => Encoding::GBK,
249
- "geostd8" => nil,
250
- "greek" => Encoding::ISO_8859_7,
251
- "hebrew" => Encoding::ISO_8859_8,
252
- "hp8" => nil,
253
- "keybcs2" => nil,
254
- "koi8r" => Encoding::KOI8_R,
255
- "koi8u" => Encoding::KOI8_U,
256
- "latin1" => Encoding::ISO_8859_1,
257
- "latin2" => Encoding::ISO_8859_2,
258
- "latin5" => Encoding::ISO_8859_9,
259
- "latin7" => Encoding::ISO_8859_13,
260
- "macce" => Encoding::MacCentEuro,
261
- "macroman" => Encoding::MacRoman,
262
- "sjis" => Encoding::SHIFT_JIS,
263
- "swe7" => nil,
264
- "tis620" => Encoding::TIS_620,
265
- "ucs2" => Encoding::UTF_16BE,
266
- "ujis" => Encoding::EucJP_ms,
267
- "utf8" => Encoding::UTF_8,
268
- "utf8mb4" => Encoding::UTF_8,
269
- }
270
- else
271
- ENCODINGS = Hash.new { |h,k| h[k] = k }
272
- end
228
+ # Taken from here:
229
+ # https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
230
+ # Author: TOMITA Masahiro <tommy@tmtm.org>
231
+ ENCODINGS = {
232
+ "armscii8" => nil,
233
+ "ascii" => Encoding::US_ASCII,
234
+ "big5" => Encoding::Big5,
235
+ "binary" => Encoding::ASCII_8BIT,
236
+ "cp1250" => Encoding::Windows_1250,
237
+ "cp1251" => Encoding::Windows_1251,
238
+ "cp1256" => Encoding::Windows_1256,
239
+ "cp1257" => Encoding::Windows_1257,
240
+ "cp850" => Encoding::CP850,
241
+ "cp852" => Encoding::CP852,
242
+ "cp866" => Encoding::IBM866,
243
+ "cp932" => Encoding::Windows_31J,
244
+ "dec8" => nil,
245
+ "eucjpms" => Encoding::EucJP_ms,
246
+ "euckr" => Encoding::EUC_KR,
247
+ "gb2312" => Encoding::EUC_CN,
248
+ "gbk" => Encoding::GBK,
249
+ "geostd8" => nil,
250
+ "greek" => Encoding::ISO_8859_7,
251
+ "hebrew" => Encoding::ISO_8859_8,
252
+ "hp8" => nil,
253
+ "keybcs2" => nil,
254
+ "koi8r" => Encoding::KOI8_R,
255
+ "koi8u" => Encoding::KOI8_U,
256
+ "latin1" => Encoding::ISO_8859_1,
257
+ "latin2" => Encoding::ISO_8859_2,
258
+ "latin5" => Encoding::ISO_8859_9,
259
+ "latin7" => Encoding::ISO_8859_13,
260
+ "macce" => Encoding::MacCentEuro,
261
+ "macroman" => Encoding::MacRoman,
262
+ "sjis" => Encoding::SHIFT_JIS,
263
+ "swe7" => nil,
264
+ "tis620" => Encoding::TIS_620,
265
+ "ucs2" => Encoding::UTF_16BE,
266
+ "ujis" => Encoding::EucJP_ms,
267
+ "utf8" => Encoding::UTF_8,
268
+ "utf8mb4" => Encoding::UTF_8,
269
+ }
273
270
 
274
271
  # Get the client encoding for this database
275
272
  def client_encoding
@@ -301,6 +298,120 @@ module ActiveRecord
301
298
  @connection.insert_id
302
299
  end
303
300
 
301
+ module Fields
302
+ class Type
303
+ def type; end
304
+
305
+ def type_cast_for_write(value)
306
+ value
307
+ end
308
+ end
309
+
310
+ class Identity < Type
311
+ def type_cast(value); value; end
312
+ end
313
+
314
+ class Integer < Type
315
+ def type_cast(value)
316
+ return if value.nil?
317
+
318
+ value.to_i rescue value ? 1 : 0
319
+ end
320
+ end
321
+
322
+ class Date < Type
323
+ def type; :date; end
324
+
325
+ def type_cast(value)
326
+ return if value.nil?
327
+
328
+ # FIXME: probably we can improve this since we know it is mysql
329
+ # specific
330
+ ConnectionAdapters::Column.value_to_date value
331
+ end
332
+ end
333
+
334
+ class DateTime < Type
335
+ def type; :datetime; end
336
+
337
+ def type_cast(value)
338
+ return if value.nil?
339
+
340
+ # FIXME: probably we can improve this since we know it is mysql
341
+ # specific
342
+ ConnectionAdapters::Column.string_to_time value
343
+ end
344
+ end
345
+
346
+ class Time < Type
347
+ def type; :time; end
348
+
349
+ def type_cast(value)
350
+ return if value.nil?
351
+
352
+ # FIXME: probably we can improve this since we know it is mysql
353
+ # specific
354
+ ConnectionAdapters::Column.string_to_dummy_time value
355
+ end
356
+ end
357
+
358
+ class Float < Type
359
+ def type; :float; end
360
+
361
+ def type_cast(value)
362
+ return if value.nil?
363
+
364
+ value.to_f
365
+ end
366
+ end
367
+
368
+ class Decimal < Type
369
+ def type_cast(value)
370
+ return if value.nil?
371
+
372
+ ConnectionAdapters::Column.value_to_decimal value
373
+ end
374
+ end
375
+
376
+ class Boolean < Type
377
+ def type_cast(value)
378
+ return if value.nil?
379
+
380
+ ConnectionAdapters::Column.value_to_boolean value
381
+ end
382
+ end
383
+
384
+ TYPES = {}
385
+
386
+ # Register an MySQL +type_id+ with a typcasting object in
387
+ # +type+.
388
+ def self.register_type(type_id, type)
389
+ TYPES[type_id] = type
390
+ end
391
+
392
+ def self.alias_type(new, old)
393
+ TYPES[new] = TYPES[old]
394
+ end
395
+
396
+ register_type Mysql::Field::TYPE_TINY, Fields::Boolean.new
397
+ register_type Mysql::Field::TYPE_LONG, Fields::Integer.new
398
+ alias_type Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_LONG
399
+ alias_type Mysql::Field::TYPE_NEWDECIMAL, Mysql::Field::TYPE_LONG
400
+
401
+ register_type Mysql::Field::TYPE_VAR_STRING, Fields::Identity.new
402
+ register_type Mysql::Field::TYPE_BLOB, Fields::Identity.new
403
+ register_type Mysql::Field::TYPE_DATE, Fields::Date.new
404
+ register_type Mysql::Field::TYPE_DATETIME, Fields::DateTime.new
405
+ register_type Mysql::Field::TYPE_TIME, Fields::Time.new
406
+ register_type Mysql::Field::TYPE_FLOAT, Fields::Float.new
407
+
408
+ Mysql::Field.constants.grep(/TYPE/).map { |class_name|
409
+ Mysql::Field.const_get class_name
410
+ }.reject { |const| TYPES.key? const }.each do |const|
411
+ register_type const, Fields::Identity.new
412
+ end
413
+ end
414
+
304
415
  def exec_without_stmt(sql, name = 'SQL') # :nodoc:
305
416
  # Some queries, like SHOW CREATE TABLE don't work through the prepared
306
417
  # statement API. For those queries, we need to use this method. :'(
@@ -309,8 +420,17 @@ module ActiveRecord
309
420
  affected_rows = @connection.affected_rows
310
421
 
311
422
  if result
312
- cols = result.fetch_fields.map { |field| field.name }
313
- result_set = ActiveRecord::Result.new(cols, result.to_a)
423
+ types = {}
424
+ result.fetch_fields.each { |field|
425
+ if field.decimals > 0
426
+ types[field.name] = Fields::Decimal.new
427
+ else
428
+ types[field.name] = Fields::TYPES.fetch(field.type) {
429
+ Fields::Identity.new
430
+ }
431
+ end
432
+ }
433
+ result_set = ActiveRecord::Result.new(types.keys, result.to_a, types)
314
434
  result.free
315
435
  else
316
436
  result_set = ActiveRecord::Result.new([], [])
@@ -416,18 +536,15 @@ module ActiveRecord
416
536
  configure_connection
417
537
  end
418
538
 
539
+ # Many Rails applications monkey-patch a replacement of the configure_connection method
540
+ # and don't call 'super', so leave this here even though it looks superfluous.
419
541
  def configure_connection
420
- encoding = @config[:encoding]
421
- execute("SET NAMES '#{encoding}'", :skip_logging) if encoding
422
-
423
- # By default, MySQL 'where id is null' selects the last inserted id.
424
- # Turn this off. http://dev.rubyonrails.org/ticket/6778
425
- execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
542
+ super
426
543
  end
427
544
 
428
545
  def select(sql, name = nil, binds = [])
429
546
  @connection.query_with_result = true
430
- rows = exec_query(sql, name, binds).to_a
547
+ rows = exec_query(sql, name, binds)
431
548
  @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
432
549
  rows
433
550
  end