activerecord 3.1.11 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. data/CHANGELOG.md +6294 -97
  2. data/README.rdoc +2 -2
  3. data/examples/performance.rb +55 -31
  4. data/lib/active_record/aggregations.rb +2 -2
  5. data/lib/active_record/associations/association.rb +2 -42
  6. data/lib/active_record/associations/association_scope.rb +3 -30
  7. data/lib/active_record/associations/builder/association.rb +6 -4
  8. data/lib/active_record/associations/builder/belongs_to.rb +3 -3
  9. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  10. data/lib/active_record/associations/builder/has_many.rb +4 -4
  11. data/lib/active_record/associations/builder/has_one.rb +5 -6
  12. data/lib/active_record/associations/builder/singular_association.rb +3 -16
  13. data/lib/active_record/associations/collection_association.rb +55 -28
  14. data/lib/active_record/associations/collection_proxy.rb +1 -35
  15. data/lib/active_record/associations/has_many_association.rb +5 -1
  16. data/lib/active_record/associations/has_many_through_association.rb +11 -8
  17. data/lib/active_record/associations/join_dependency.rb +1 -1
  18. data/lib/active_record/associations/preloader/association.rb +3 -1
  19. data/lib/active_record/associations.rb +82 -69
  20. data/lib/active_record/attribute_assignment.rb +221 -0
  21. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  22. data/lib/active_record/attribute_methods/dirty.rb +3 -3
  23. data/lib/active_record/attribute_methods/primary_key.rb +62 -25
  24. data/lib/active_record/attribute_methods/read.rb +72 -83
  25. data/lib/active_record/attribute_methods/serialization.rb +93 -0
  26. data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -14
  27. data/lib/active_record/attribute_methods/write.rb +27 -5
  28. data/lib/active_record/attribute_methods.rb +209 -30
  29. data/lib/active_record/autosave_association.rb +23 -8
  30. data/lib/active_record/base.rb +217 -1709
  31. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +98 -132
  32. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +82 -29
  33. data/lib/active_record/connection_adapters/abstract/database_statements.rb +13 -42
  34. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/quoting.rb +9 -12
  36. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
  37. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +43 -22
  38. data/lib/active_record/connection_adapters/abstract_adapter.rb +78 -43
  39. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +653 -0
  40. data/lib/active_record/connection_adapters/column.rb +2 -2
  41. data/lib/active_record/connection_adapters/mysql2_adapter.rb +138 -578
  42. data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -658
  43. data/lib/active_record/connection_adapters/postgresql_adapter.rb +144 -94
  44. data/lib/active_record/connection_adapters/schema_cache.rb +50 -0
  45. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
  46. data/lib/active_record/connection_adapters/sqlite_adapter.rb +43 -22
  47. data/lib/active_record/counter_cache.rb +4 -3
  48. data/lib/active_record/dynamic_matchers.rb +79 -0
  49. data/lib/active_record/errors.rb +11 -1
  50. data/lib/active_record/explain.rb +83 -0
  51. data/lib/active_record/explain_subscriber.rb +21 -0
  52. data/lib/active_record/fixtures/file.rb +65 -0
  53. data/lib/active_record/fixtures.rb +31 -76
  54. data/lib/active_record/identity_map.rb +4 -11
  55. data/lib/active_record/inheritance.rb +167 -0
  56. data/lib/active_record/integration.rb +49 -0
  57. data/lib/active_record/locking/optimistic.rb +30 -25
  58. data/lib/active_record/locking/pessimistic.rb +23 -1
  59. data/lib/active_record/log_subscriber.rb +3 -3
  60. data/lib/active_record/migration/command_recorder.rb +8 -8
  61. data/lib/active_record/migration.rb +47 -30
  62. data/lib/active_record/model_schema.rb +366 -0
  63. data/lib/active_record/nested_attributes.rb +3 -2
  64. data/lib/active_record/persistence.rb +51 -9
  65. data/lib/active_record/querying.rb +58 -0
  66. data/lib/active_record/railtie.rb +24 -28
  67. data/lib/active_record/railties/controller_runtime.rb +3 -1
  68. data/lib/active_record/railties/databases.rake +134 -77
  69. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  70. data/lib/active_record/readonly_attributes.rb +26 -0
  71. data/lib/active_record/reflection.rb +7 -15
  72. data/lib/active_record/relation/batches.rb +5 -2
  73. data/lib/active_record/relation/calculations.rb +27 -6
  74. data/lib/active_record/relation/delegation.rb +49 -0
  75. data/lib/active_record/relation/finder_methods.rb +6 -5
  76. data/lib/active_record/relation/predicate_builder.rb +12 -19
  77. data/lib/active_record/relation/query_methods.rb +76 -10
  78. data/lib/active_record/relation/spawn_methods.rb +11 -2
  79. data/lib/active_record/relation.rb +77 -34
  80. data/lib/active_record/result.rb +1 -1
  81. data/lib/active_record/sanitization.rb +194 -0
  82. data/lib/active_record/schema_dumper.rb +5 -2
  83. data/lib/active_record/scoping/default.rb +142 -0
  84. data/lib/active_record/scoping/named.rb +202 -0
  85. data/lib/active_record/scoping.rb +152 -0
  86. data/lib/active_record/serialization.rb +1 -43
  87. data/lib/active_record/serializers/xml_serializer.rb +2 -44
  88. data/lib/active_record/session_store.rb +15 -15
  89. data/lib/active_record/store.rb +50 -0
  90. data/lib/active_record/test_case.rb +11 -7
  91. data/lib/active_record/timestamp.rb +16 -3
  92. data/lib/active_record/transactions.rb +5 -5
  93. data/lib/active_record/translation.rb +22 -0
  94. data/lib/active_record/validations/associated.rb +5 -4
  95. data/lib/active_record/validations/uniqueness.rb +4 -4
  96. data/lib/active_record/validations.rb +1 -1
  97. data/lib/active_record/version.rb +2 -2
  98. data/lib/active_record.rb +28 -2
  99. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  100. data/lib/rails/generators/active_record/migration/templates/migration.rb +9 -3
  101. data/lib/rails/generators/active_record/model/model_generator.rb +5 -1
  102. data/lib/rails/generators/active_record/model/templates/migration.rb +3 -5
  103. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
  104. metadata +50 -40
  105. checksums.yaml +0 -7
  106. data/lib/active_record/named_scope.rb +0 -200
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
  require 'monitor'
3
3
  require 'set'
4
- require 'active_support/core_ext/module/synchronization'
4
+ require 'active_support/core_ext/module/deprecation'
5
5
 
6
6
  module ActiveRecord
7
7
  # Raised when a connection could not be obtained within the connection
@@ -57,10 +57,10 @@ module ActiveRecord
57
57
  # * +wait_timeout+: number of seconds to block and wait for a connection
58
58
  # before giving up and raising a timeout error (default 5 seconds).
59
59
  class ConnectionPool
60
+ include MonitorMixin
61
+
60
62
  attr_accessor :automatic_reconnect
61
63
  attr_reader :spec, :connections
62
- attr_reader :columns, :columns_hash, :primary_keys, :tables
63
- attr_reader :column_defaults
64
64
 
65
65
  # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
66
66
  # object which describes database connection information (e.g. adapter,
@@ -69,88 +69,21 @@ module ActiveRecord
69
69
  #
70
70
  # The default ConnectionPool maximum size is 5.
71
71
  def initialize(spec)
72
+ super()
73
+
72
74
  @spec = spec
73
75
 
74
76
  # The cache of reserved connections mapped to threads
75
77
  @reserved_connections = {}
76
78
 
77
- # The mutex used to synchronize pool access
78
- @connection_mutex = Monitor.new
79
- @queue = @connection_mutex.new_cond
79
+ @queue = new_cond
80
80
  @timeout = spec.config[:wait_timeout] || 5
81
81
 
82
82
  # default max pool size to 5
83
83
  @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
84
84
 
85
85
  @connections = []
86
- @checked_out = []
87
86
  @automatic_reconnect = true
88
- @tables = {}
89
- @visitor = nil
90
-
91
- @columns = Hash.new do |h, table_name|
92
- h[table_name] = with_connection do |conn|
93
-
94
- # Fetch a list of columns
95
- conn.columns(table_name, "#{table_name} Columns").tap do |columns|
96
-
97
- # set primary key information
98
- columns.each do |column|
99
- column.primary = column.name == primary_keys[table_name]
100
- end
101
- end
102
- end
103
- end
104
-
105
- @columns_hash = Hash.new do |h, table_name|
106
- h[table_name] = Hash[columns[table_name].map { |col|
107
- [col.name, col]
108
- }]
109
- end
110
-
111
- @column_defaults = Hash.new do |h, table_name|
112
- h[table_name] = Hash[columns[table_name].map { |col|
113
- [col.name, col.default]
114
- }]
115
- end
116
-
117
- @primary_keys = Hash.new do |h, table_name|
118
- h[table_name] = with_connection do |conn|
119
- table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
120
- end
121
- end
122
- end
123
-
124
- # A cached lookup for table existence.
125
- def table_exists?(name)
126
- return true if @tables.key? name
127
-
128
- with_connection do |conn|
129
- conn.tables.each { |table| @tables[table] = true }
130
- @tables[name] = true if !@tables.key?(name) && conn.table_exists?(name)
131
- end
132
-
133
- @tables.key? name
134
- end
135
-
136
- # Clears out internal caches:
137
- #
138
- # * columns
139
- # * columns_hash
140
- # * tables
141
- def clear_cache!
142
- @columns.clear
143
- @columns_hash.clear
144
- @column_defaults.clear
145
- @tables.clear
146
- end
147
-
148
- # Clear out internal caches for table with +table_name+.
149
- def clear_table_cache!(table_name)
150
- @columns.delete table_name
151
- @columns_hash.delete table_name
152
- @column_defaults.delete table_name
153
- @primary_keys.delete table_name
154
87
  end
155
88
 
156
89
  # Retrieve the connection associated with the current thread, or call
@@ -165,7 +98,7 @@ module ActiveRecord
165
98
  # Check to see if there is an active connection in this connection
166
99
  # pool.
167
100
  def active_connection?
168
- @reserved_connections.key? current_connection_id
101
+ active_connections.any?
169
102
  end
170
103
 
171
104
  # Signal that the thread is finished with the current connection.
@@ -176,12 +109,12 @@ module ActiveRecord
176
109
  checkin conn if conn
177
110
  end
178
111
 
179
- # If a connection already exists yield it to the block. If no connection
112
+ # If a connection already exists yield it to the block. If no connection
180
113
  # exists checkout a connection, yield it to the block, and checkin the
181
114
  # connection when finished.
182
115
  def with_connection
183
116
  connection_id = current_connection_id
184
- fresh_connection = true unless @reserved_connections[connection_id]
117
+ fresh_connection = true unless active_connection?
185
118
  yield connection
186
119
  ensure
187
120
  release_connection(connection_id) if fresh_connection
@@ -189,43 +122,73 @@ module ActiveRecord
189
122
 
190
123
  # Returns true if a connection has already been opened.
191
124
  def connected?
192
- !@connections.empty?
125
+ synchronize { @connections.any? }
193
126
  end
194
127
 
195
128
  # Disconnects all connections in the pool, and clears the pool.
196
129
  def disconnect!
197
- @reserved_connections.each do |name,conn|
198
- checkin conn
199
- end
200
- @reserved_connections = {}
201
- @connections.each do |conn|
202
- conn.disconnect!
130
+ synchronize do
131
+ @reserved_connections = {}
132
+ @connections.each do |conn|
133
+ checkin conn
134
+ conn.disconnect!
135
+ end
136
+ @connections = []
203
137
  end
204
- @connections = []
205
138
  end
206
139
 
207
140
  # Clears the cache which maps classes.
208
141
  def clear_reloadable_connections!
209
- @reserved_connections.each do |name, conn|
210
- checkin conn
211
- end
212
- @reserved_connections = {}
213
- @connections.each do |conn|
214
- conn.disconnect! if conn.requires_reloading?
215
- end
216
- @connections.delete_if do |conn|
217
- conn.requires_reloading?
142
+ synchronize do
143
+ @reserved_connections = {}
144
+ @connections.each do |conn|
145
+ checkin conn
146
+ conn.disconnect! if conn.requires_reloading?
147
+ end
148
+ @connections.delete_if do |conn|
149
+ conn.requires_reloading?
150
+ end
218
151
  end
219
152
  end
220
153
 
221
154
  # Verify active connections and remove and disconnect connections
222
155
  # associated with stale threads.
223
156
  def verify_active_connections! #:nodoc:
224
- clear_stale_cached_connections!
225
- @connections.each do |connection|
226
- connection.verify!
157
+ synchronize do
158
+ clear_stale_cached_connections!
159
+ @connections.each do |connection|
160
+ connection.verify!
161
+ end
162
+ end
163
+ end
164
+
165
+ def columns
166
+ with_connection do |c|
167
+ c.schema_cache.columns
168
+ end
169
+ end
170
+ deprecate :columns
171
+
172
+ def columns_hash
173
+ with_connection do |c|
174
+ c.schema_cache.columns_hash
175
+ end
176
+ end
177
+ deprecate :columns_hash
178
+
179
+ def primary_keys
180
+ with_connection do |c|
181
+ c.schema_cache.primary_keys
182
+ end
183
+ end
184
+ deprecate :primary_keys
185
+
186
+ def clear_cache!
187
+ with_connection do |c|
188
+ c.schema_cache.clear!
227
189
  end
228
190
  end
191
+ deprecate :clear_cache!
229
192
 
230
193
  # Return any checked-out connections back to the pool by threads that
231
194
  # are no longer alive.
@@ -234,7 +197,13 @@ module ActiveRecord
234
197
  t.alive?
235
198
  }.map { |thread| thread.object_id }
236
199
  keys.each do |key|
237
- checkin @reserved_connections[key]
200
+ conn = @reserved_connections[key]
201
+ ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
202
+ Database connections will not be closed automatically, please close your
203
+ database connection at the end of the thread by calling `close` on your
204
+ connection. For example: ActiveRecord::Base.connection.close
205
+ eowarn
206
+ checkin conn
238
207
  @reserved_connections.delete(key)
239
208
  end
240
209
  end
@@ -257,23 +226,30 @@ module ActiveRecord
257
226
  # within the timeout period.
258
227
  def checkout
259
228
  # Checkout an available connection
260
- @connection_mutex.synchronize do
229
+ synchronize do
261
230
  loop do
262
- conn = if @checked_out.size < @connections.size
263
- checkout_existing_connection
264
- elsif @connections.size < @size
265
- checkout_new_connection
266
- end
267
- return conn if conn
231
+ conn = @connections.find { |c| c.lease }
232
+
233
+ unless conn
234
+ if @connections.size < @size
235
+ conn = checkout_new_connection
236
+ conn.lease
237
+ end
238
+ end
239
+
240
+ if conn
241
+ checkout_and_verify conn
242
+ return conn
243
+ end
268
244
 
269
245
  @queue.wait(@timeout)
270
246
 
271
- if(@checked_out.size < @connections.size)
247
+ if(active_connections.size < @connections.size)
272
248
  next
273
249
  else
274
250
  clear_stale_cached_connections!
275
- if @size == @checked_out.size
276
- raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
251
+ if @size == active_connections.size
252
+ raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
277
253
  end
278
254
  end
279
255
 
@@ -287,30 +263,18 @@ module ActiveRecord
287
263
  # +conn+: an AbstractAdapter object, which was obtained by earlier by
288
264
  # calling +checkout+ on this pool.
289
265
  def checkin(conn)
290
- @connection_mutex.synchronize do
266
+ synchronize do
291
267
  conn.run_callbacks :checkin do
292
- @checked_out.delete conn
268
+ conn.expire
293
269
  @queue.signal
294
270
  end
295
271
  end
296
272
  end
297
273
 
298
- synchronize :clear_reloadable_connections!, :verify_active_connections!,
299
- :connected?, :disconnect!, :with => :@connection_mutex
300
-
301
274
  private
302
275
 
303
276
  def new_connection
304
- connection = ActiveRecord::Base.send(spec.adapter_method, spec.config)
305
-
306
- # TODO: This is a bit icky, and in the long term we may want to change the method
307
- # signature for connections. Also, if we switch to have one visitor per
308
- # connection (and therefore per thread), we can get rid of the thread-local
309
- # variable in Arel::Visitors::ToSql.
310
- @visitor ||= connection.class.visitor_for(self)
311
- connection.visitor = @visitor
312
-
313
- connection
277
+ ActiveRecord::Base.send(spec.adapter_method, spec.config)
314
278
  end
315
279
 
316
280
  def current_connection_id #:nodoc:
@@ -321,22 +285,21 @@ module ActiveRecord
321
285
  raise ConnectionNotEstablished unless @automatic_reconnect
322
286
 
323
287
  c = new_connection
288
+ c.pool = self
324
289
  @connections << c
325
- checkout_and_verify(c)
326
- end
327
-
328
- def checkout_existing_connection
329
- c = (@connections - @checked_out).first
330
- checkout_and_verify(c)
290
+ c
331
291
  end
332
292
 
333
293
  def checkout_and_verify(c)
334
294
  c.run_callbacks :checkout do
335
295
  c.verify!
336
- @checked_out << c
337
296
  end
338
297
  c
339
298
  end
299
+
300
+ def active_connections
301
+ @connections.find_all { |c| c.in_use? }
302
+ end
340
303
  end
341
304
 
342
305
  # ConnectionHandler is a collection of ConnectionPool objects. It is used
@@ -367,10 +330,12 @@ module ActiveRecord
367
330
 
368
331
  def initialize(pools = {})
369
332
  @connection_pools = pools
333
+ @class_to_pool = {}
370
334
  end
371
335
 
372
336
  def establish_connection(name, spec)
373
- @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
337
+ @connection_pools[spec] ||= ConnectionAdapters::ConnectionPool.new(spec)
338
+ @class_to_pool[name] = @connection_pools[spec]
374
339
  end
375
340
 
376
341
  # Returns true if there are any active connections among the connection
@@ -421,16 +386,17 @@ module ActiveRecord
421
386
  # can be used as an argument for establish_connection, for easily
422
387
  # re-establishing the connection.
423
388
  def remove_connection(klass)
424
- pool = @connection_pools.delete(klass.name)
389
+ pool = @class_to_pool.delete(klass.name)
425
390
  return nil unless pool
426
391
 
392
+ @connection_pools.delete pool.spec
427
393
  pool.automatic_reconnect = false
428
394
  pool.disconnect!
429
395
  pool.spec.config
430
396
  end
431
397
 
432
398
  def retrieve_connection_pool(klass)
433
- pool = @connection_pools[klass.name]
399
+ pool = @class_to_pool[klass.name]
434
400
  return pool if pool
435
401
  return nil if ActiveRecord::Base == klass
436
402
  retrieve_connection_pool klass.superclass
@@ -5,6 +5,74 @@ module ActiveRecord
5
5
  def initialize (config, adapter_method)
6
6
  @config, @adapter_method = config, adapter_method
7
7
  end
8
+
9
+ ##
10
+ # Builds a ConnectionSpecification from user input
11
+ class Resolver # :nodoc:
12
+ attr_reader :config, :klass, :configurations
13
+
14
+ def initialize(config, configurations)
15
+ @config = config
16
+ @configurations = configurations
17
+ end
18
+
19
+ def spec
20
+ case config
21
+ when nil
22
+ raise AdapterNotSpecified unless defined?(Rails.env)
23
+ resolve_string_connection Rails.env
24
+ when Symbol, String
25
+ resolve_string_connection config.to_s
26
+ when Hash
27
+ resolve_hash_connection config
28
+ end
29
+ end
30
+
31
+ private
32
+ def resolve_string_connection(spec) # :nodoc:
33
+ hash = configurations.fetch(spec) do |k|
34
+ connection_url_to_hash(k)
35
+ end
36
+
37
+ raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
38
+
39
+ resolve_hash_connection hash
40
+ end
41
+
42
+ def resolve_hash_connection(spec) # :nodoc:
43
+ spec = spec.symbolize_keys
44
+
45
+ raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
46
+
47
+ begin
48
+ require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
49
+ rescue LoadError => e
50
+ raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
51
+ end
52
+
53
+ adapter_method = "#{spec[:adapter]}_connection"
54
+
55
+ ConnectionSpecification.new(spec, adapter_method)
56
+ end
57
+
58
+ def connection_url_to_hash(url) # :nodoc:
59
+ config = URI.parse url
60
+ adapter = config.scheme
61
+ adapter = "postgresql" if adapter == "postgres"
62
+ spec = { :adapter => adapter,
63
+ :username => config.user,
64
+ :password => config.password,
65
+ :port => config.port,
66
+ :database => config.path.sub(%r{^/},""),
67
+ :host => config.host }
68
+ spec.reject!{ |_,value| !value }
69
+ if config.query
70
+ options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
71
+ spec.merge!(options)
72
+ end
73
+ spec
74
+ end
75
+ end
8
76
  end
9
77
 
10
78
  ##
@@ -46,39 +114,24 @@ module ActiveRecord
46
114
  # "database" => "path/to/dbfile"
47
115
  # )
48
116
  #
117
+ # Or a URL:
118
+ #
119
+ # ActiveRecord::Base.establish_connection(
120
+ # "postgres://myuser:mypass@localhost/somedatabase"
121
+ # )
122
+ #
49
123
  # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
50
124
  # may be returned on an error.
51
- def self.establish_connection(spec = nil)
52
- case spec
53
- when nil
54
- raise AdapterNotSpecified unless defined?(Rails.env)
55
- establish_connection(Rails.env)
56
- when ConnectionSpecification
57
- self.connection_handler.establish_connection(name, spec)
58
- when Symbol, String
59
- if configuration = configurations[spec.to_s]
60
- establish_connection(configuration)
61
- else
62
- raise AdapterNotSpecified, "#{spec} database is not configured"
63
- end
64
- else
65
- spec = spec.symbolize_keys
66
- unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
125
+ def self.establish_connection(spec = ENV["DATABASE_URL"])
126
+ resolver = ConnectionSpecification::Resolver.new spec, configurations
127
+ spec = resolver.spec
67
128
 
68
- begin
69
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
70
- rescue LoadError => e
71
- raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e})"
72
- end
73
-
74
- adapter_method = "#{spec[:adapter]}_connection"
75
- unless respond_to?(adapter_method)
76
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
77
- end
78
-
79
- remove_connection
80
- establish_connection(ConnectionSpecification.new(spec, adapter_method))
129
+ unless respond_to?(spec.adapter_method)
130
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
81
131
  end
132
+
133
+ remove_connection
134
+ connection_handler.establish_connection name, spec
82
135
  end
83
136
 
84
137
  class << self
@@ -1,14 +1,10 @@
1
- require 'active_support/core_ext/module/deprecation'
2
-
3
1
  module ActiveRecord
4
2
  module ConnectionAdapters # :nodoc:
5
3
  module DatabaseStatements
6
4
  # Converts an arel AST to SQL
7
- def to_sql(arel, binds = [])
5
+ def to_sql(arel)
8
6
  if arel.respond_to?(:ast)
9
- visitor.accept(arel.ast) do
10
- quote(*binds.shift.reverse)
11
- end
7
+ visitor.accept(arel.ast)
12
8
  else
13
9
  arel
14
10
  end
@@ -17,7 +13,7 @@ module ActiveRecord
17
13
  # Returns an array of record hashes with the column names as keys and
18
14
  # column values as values.
19
15
  def select_all(arel, name = nil, binds = [])
20
- select(to_sql(arel, binds), name, binds)
16
+ select(to_sql(arel), name, binds)
21
17
  end
22
18
 
23
19
  # Returns a record hash with the column names as keys and column values
@@ -37,7 +33,7 @@ module ActiveRecord
37
33
  # Returns an array of the values of the first column in a select:
38
34
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
39
35
  def select_values(arel, name = nil)
40
- result = select_rows(to_sql(arel, []), name)
36
+ result = select_rows(to_sql(arel), name)
41
37
  result.map { |v| v[0] }
42
38
  end
43
39
 
@@ -53,7 +49,7 @@ module ActiveRecord
53
49
  undef_method :execute
54
50
 
55
51
  # Executes +sql+ statement in the context of this connection using
56
- # +binds+ as the bind substitutes. +name+ is logged along with
52
+ # +binds+ as the bind substitutes. +name+ is logged along with
57
53
  # the executed +sql+ statement.
58
54
  def exec_query(sql, name = 'SQL', binds = [])
59
55
  end
@@ -88,19 +84,19 @@ module ActiveRecord
88
84
  # If the next id was calculated in advance (as in Oracle), it should be
89
85
  # passed in as +id_value+.
90
86
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
91
- sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
87
+ sql, binds = sql_for_insert(to_sql(arel), pk, id_value, sequence_name, binds)
92
88
  value = exec_insert(sql, name, binds)
93
89
  id_value || last_inserted_id(value)
94
90
  end
95
91
 
96
92
  # Executes the update statement and returns the number of rows affected.
97
93
  def update(arel, name = nil, binds = [])
98
- exec_update(to_sql(arel, binds), name, binds)
94
+ exec_update(to_sql(arel), name, binds)
99
95
  end
100
96
 
101
97
  # Executes the delete statement and returns the number of rows affected.
102
98
  def delete(arel, name = nil, binds = [])
103
- exec_delete(to_sql(arel, binds), name, binds)
99
+ exec_delete(to_sql(arel), name, binds)
104
100
  end
105
101
 
106
102
  # Checks whether there is currently no transaction active. This is done
@@ -256,38 +252,13 @@ module ActiveRecord
256
252
  # done if the transaction block raises an exception or returns false.
257
253
  def rollback_db_transaction() end
258
254
 
259
- # Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
260
- # fragment that has the same semantics as LIMIT and OFFSET.
261
- #
262
- # +options+ must be a Hash which contains a +:limit+ option
263
- # and an +:offset+ option.
264
- #
265
- # This method *modifies* the +sql+ parameter.
266
- #
267
- # This method is deprecated!! Stop using it!
268
- #
269
- # ===== Examples
270
- # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
271
- # generates
272
- # SELECT * FROM suppliers LIMIT 10 OFFSET 50
273
- def add_limit_offset!(sql, options)
274
- if limit = options[:limit]
275
- sql << " LIMIT #{sanitize_limit(limit)}"
276
- end
277
- if offset = options[:offset]
278
- sql << " OFFSET #{offset.to_i}"
279
- end
280
- sql
281
- end
282
- deprecate :add_limit_offset!
283
-
284
255
  def default_sequence_name(table, column)
285
256
  nil
286
257
  end
287
258
 
288
259
  # Set the sequence to the max value of the table's column.
289
260
  def reset_sequence!(table, column, sequence = nil)
290
- # Do nothing by default. Implement for PostgreSQL, Oracle, ...
261
+ # Do nothing by default. Implement for PostgreSQL, Oracle, ...
291
262
  end
292
263
 
293
264
  # Inserts the given fixture into the table. Overridden in adapters that require
@@ -319,10 +290,10 @@ module ActiveRecord
319
290
  # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
320
291
  #
321
292
  # The +limit+ may be anything that can evaluate to a string via #to_s. It
322
- # should look like an integer, or a comma-delimited list of integers, or
293
+ # should look like an integer, or a comma-delimited list of integers, or
323
294
  # an Arel SQL literal.
324
295
  #
325
- # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
296
+ # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
326
297
  # Returns the sanitized limit parameter, either as an integer, or as a
327
298
  # string which contains a comma-delimited list of integers.
328
299
  def sanitize_limit(limit)
@@ -370,7 +341,7 @@ module ActiveRecord
370
341
 
371
342
  # Send a rollback message to all records after they have been rolled back. If rollback
372
343
  # is false, only rollback records since the last save point.
373
- def rollback_transaction_records(rollback) #:nodoc
344
+ def rollback_transaction_records(rollback)
374
345
  if rollback
375
346
  records = @_current_transaction_records.flatten
376
347
  @_current_transaction_records.clear
@@ -390,7 +361,7 @@ module ActiveRecord
390
361
  end
391
362
 
392
363
  # Send a commit message to all records after they have been committed.
393
- def commit_transaction_records #:nodoc
364
+ def commit_transaction_records
394
365
  records = @_current_transaction_records.flatten
395
366
  @_current_transaction_records.clear
396
367
  unless records.blank?
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
 
58
58
  def select_all(arel, name = nil, binds = [])
59
59
  if @query_cache_enabled
60
- sql = to_sql(arel, binds)
60
+ sql = to_sql(arel)
61
61
  cache_sql(sql, binds) { super(sql, name, binds) }
62
62
  else
63
63
  super
@@ -25,19 +25,13 @@ module ActiveRecord
25
25
  when true, false
26
26
  if column && column.type == :integer
27
27
  value ? '1' : '0'
28
- elsif column && [:text, :string, :binary].include?(column.type)
29
- value ? "'1'" : "'0'"
30
28
  else
31
29
  value ? quoted_true : quoted_false
32
30
  end
33
31
  # BigDecimals need to be put in a non-normalized form and quoted.
34
32
  when nil then "NULL"
35
- when Numeric, ActiveSupport::Duration
36
- value = BigDecimal === value ? value.to_s('F') : value.to_s
37
- if column && ![:integer, :float, :decimal].include?(column.type)
38
- value = "'#{value}'"
39
- end
40
- value
33
+ when BigDecimal then value.to_s('F')
34
+ when Numeric then value.to_s
41
35
  when Date, Time then "'#{quoted_date(value)}'"
42
36
  when Symbol then "'#{quote_string(value.to_s)}'"
43
37
  else
@@ -108,10 +102,13 @@ module ActiveRecord
108
102
  def quoted_date(value)
109
103
  if value.acts_like?(:time)
110
104
  zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
111
- value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
112
- else
113
- value
114
- end.to_s(:db)
105
+
106
+ if value.respond_to?(zone_conversion_method)
107
+ value = value.send(zone_conversion_method)
108
+ end
109
+ end
110
+
111
+ value.to_s(:db)
115
112
  end
116
113
  end
117
114
  end