activerecord 3.0.20 → 3.1.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 (122) hide show
  1. data/CHANGELOG +220 -91
  2. data/README.rdoc +3 -3
  3. data/examples/performance.rb +88 -109
  4. data/lib/active_record.rb +6 -2
  5. data/lib/active_record/aggregations.rb +22 -45
  6. data/lib/active_record/associations.rb +264 -991
  7. data/lib/active_record/associations/alias_tracker.rb +85 -0
  8. data/lib/active_record/associations/association.rb +231 -0
  9. data/lib/active_record/associations/association_scope.rb +120 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +40 -60
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
  12. data/lib/active_record/associations/builder/association.rb +53 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +85 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
  16. data/lib/active_record/associations/builder/has_many.rb +65 -0
  17. data/lib/active_record/associations/builder/has_one.rb +63 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +524 -0
  20. data/lib/active_record/associations/collection_proxy.rb +125 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
  22. data/lib/active_record/associations/has_many_association.rb +50 -79
  23. data/lib/active_record/associations/has_many_through_association.rb +98 -67
  24. data/lib/active_record/associations/has_one_association.rb +45 -115
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency.rb +215 -0
  27. data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_helper.rb +56 -0
  31. data/lib/active_record/associations/preloader.rb +177 -0
  32. data/lib/active_record/associations/preloader/association.rb +126 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/singular_association.rb +55 -0
  43. data/lib/active_record/associations/through_association.rb +80 -0
  44. data/lib/active_record/attribute_methods.rb +19 -5
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
  46. data/lib/active_record/attribute_methods/dirty.rb +8 -2
  47. data/lib/active_record/attribute_methods/primary_key.rb +33 -13
  48. data/lib/active_record/attribute_methods/read.rb +17 -17
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
  50. data/lib/active_record/attribute_methods/write.rb +2 -1
  51. data/lib/active_record/autosave_association.rb +66 -45
  52. data/lib/active_record/base.rb +445 -273
  53. data/lib/active_record/callbacks.rb +24 -33
  54. data/lib/active_record/coders/yaml_column.rb +41 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
  62. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
  64. data/lib/active_record/connection_adapters/column.rb +268 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
  67. data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
  68. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
  69. data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
  70. data/lib/active_record/counter_cache.rb +7 -4
  71. data/lib/active_record/fixtures.rb +174 -192
  72. data/lib/active_record/identity_map.rb +131 -0
  73. data/lib/active_record/locking/optimistic.rb +20 -14
  74. data/lib/active_record/locking/pessimistic.rb +4 -4
  75. data/lib/active_record/log_subscriber.rb +24 -4
  76. data/lib/active_record/migration.rb +265 -144
  77. data/lib/active_record/migration/command_recorder.rb +103 -0
  78. data/lib/active_record/named_scope.rb +68 -25
  79. data/lib/active_record/nested_attributes.rb +58 -15
  80. data/lib/active_record/observer.rb +3 -7
  81. data/lib/active_record/persistence.rb +58 -38
  82. data/lib/active_record/query_cache.rb +25 -3
  83. data/lib/active_record/railtie.rb +21 -12
  84. data/lib/active_record/railties/console_sandbox.rb +6 -0
  85. data/lib/active_record/railties/databases.rake +147 -116
  86. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  87. data/lib/active_record/reflection.rb +176 -44
  88. data/lib/active_record/relation.rb +125 -49
  89. data/lib/active_record/relation/batches.rb +7 -5
  90. data/lib/active_record/relation/calculations.rb +50 -18
  91. data/lib/active_record/relation/finder_methods.rb +47 -26
  92. data/lib/active_record/relation/predicate_builder.rb +24 -21
  93. data/lib/active_record/relation/query_methods.rb +117 -101
  94. data/lib/active_record/relation/spawn_methods.rb +27 -20
  95. data/lib/active_record/result.rb +34 -0
  96. data/lib/active_record/schema.rb +5 -6
  97. data/lib/active_record/schema_dumper.rb +11 -13
  98. data/lib/active_record/serialization.rb +2 -2
  99. data/lib/active_record/serializers/xml_serializer.rb +10 -10
  100. data/lib/active_record/session_store.rb +8 -2
  101. data/lib/active_record/test_case.rb +9 -20
  102. data/lib/active_record/timestamp.rb +21 -9
  103. data/lib/active_record/transactions.rb +16 -15
  104. data/lib/active_record/validations.rb +21 -22
  105. data/lib/active_record/validations/associated.rb +3 -1
  106. data/lib/active_record/validations/uniqueness.rb +48 -58
  107. data/lib/active_record/version.rb +3 -3
  108. data/lib/rails/generators/active_record.rb +6 -0
  109. data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
  110. data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
  111. data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
  112. data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
  113. data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
  114. data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
  115. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
  116. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
  117. metadata +106 -77
  118. checksums.yaml +0 -7
  119. data/lib/active_record/association_preload.rb +0 -431
  120. data/lib/active_record/associations/association_collection.rb +0 -572
  121. data/lib/active_record/associations/association_proxy.rb +0 -304
  122. data/lib/active_record/associations/through_association_scope.rb +0 -160
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  #
32
32
  # That's a total of twelve callbacks, which gives you immense power to react and prepare for each state in the
33
33
  # Active Record life cycle. The sequence for calling <tt>Base#save</tt> for an existing record is similar,
34
- # except that each <tt>_on_create</tt> callback is replaced by the corresponding <tt>_on_update</tt> callback.
34
+ # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
35
35
  #
36
36
  # Examples:
37
37
  # class CreditCard < ActiveRecord::Base
@@ -73,7 +73,7 @@ module ActiveRecord
73
73
  #
74
74
  # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
75
75
  # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
76
- # where the +before_destroy+ methis is overriden:
76
+ # where the +before_destroy+ method is overridden:
77
77
  #
78
78
  # class Topic < ActiveRecord::Base
79
79
  # def before_destroy() destroy_author end
@@ -215,15 +215,23 @@ module ActiveRecord
215
215
  # instead of quietly returning +false+.
216
216
  #
217
217
  # == Debugging callbacks
218
- #
219
- # To list the methods and procs registered with a particular callback, append <tt>_callback_chain</tt> to
220
- # the callback name that you wish to list and send that to your class from the Rails console:
221
- #
222
- # >> Topic.after_save_callback_chain
223
- # => [#<ActiveSupport::Callbacks::Callback:0x3f6a448
224
- # @method=#<Proc:0x03f9a42c@/Users/foo/bar/app/models/topic.rb:43>, kind:after_save, identifiernil,
225
- # options{}]
226
- #
218
+ #
219
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
220
+ # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
221
+ # defines what part of the chain the callback runs in.
222
+ #
223
+ # To find all callbacks in the before_save callback chain:
224
+ #
225
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
226
+ #
227
+ # Returns an array of callback objects that form the before_save chain.
228
+ #
229
+ # To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
230
+ #
231
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
232
+ #
233
+ # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
234
+ #
227
235
  module Callbacks
228
236
  extend ActiveSupport::Concern
229
237
 
@@ -242,43 +250,26 @@ module ActiveRecord
242
250
  define_model_callbacks :save, :create, :update, :destroy
243
251
  end
244
252
 
245
- module ClassMethods
246
- def method_added(meth)
247
- super
248
- if CALLBACKS.include?(meth.to_sym)
249
- ActiveSupport::Deprecation.warn("Base##{meth} has been deprecated, please use Base.#{meth} :method instead", caller[0,1])
250
- send(meth.to_sym, meth.to_sym)
251
- end
252
- end
253
- end
254
-
255
253
  def destroy #:nodoc:
256
- _run_destroy_callbacks { super }
254
+ run_callbacks(:destroy) { super }
257
255
  end
258
256
 
259
257
  def touch(*) #:nodoc:
260
- _run_touch_callbacks { super }
261
- end
262
-
263
- def deprecated_callback_method(symbol) #:nodoc:
264
- if respond_to?(symbol, true)
265
- ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base.#{symbol} :method_name instead")
266
- send(symbol)
267
- end
258
+ run_callbacks(:touch) { super }
268
259
  end
269
260
 
270
261
  private
271
262
 
272
263
  def create_or_update #:nodoc:
273
- _run_save_callbacks { super }
264
+ run_callbacks(:save) { super }
274
265
  end
275
266
 
276
267
  def create #:nodoc:
277
- _run_create_callbacks { super }
268
+ run_callbacks(:create) { super }
278
269
  end
279
270
 
280
271
  def update(*) #:nodoc:
281
- _run_update_callbacks { super }
272
+ run_callbacks(:update) { super }
282
273
  end
283
274
  end
284
275
  end
@@ -0,0 +1,41 @@
1
+ module ActiveRecord
2
+ # :stopdoc:
3
+ module Coders
4
+ class YAMLColumn
5
+ RESCUE_ERRORS = [ ArgumentError ]
6
+
7
+ if defined?(Psych) && defined?(Psych::SyntaxError)
8
+ RESCUE_ERRORS << Psych::SyntaxError
9
+ end
10
+
11
+ attr_accessor :object_class
12
+
13
+ def initialize(object_class = Object)
14
+ @object_class = object_class
15
+ end
16
+
17
+ def dump(obj)
18
+ YAML.dump obj
19
+ end
20
+
21
+ def load(yaml)
22
+ return object_class.new if object_class != Object && yaml.nil?
23
+ return yaml unless yaml.is_a?(String) && yaml =~ /^---/
24
+ begin
25
+ obj = YAML.load(yaml)
26
+
27
+ unless obj.is_a?(object_class) || obj.nil?
28
+ raise SerializationTypeMismatch,
29
+ "Attribute was supposed to be a #{object_class}, but was a #{obj.class}"
30
+ end
31
+ obj ||= object_class.new if object_class != Object
32
+
33
+ obj
34
+ rescue *RESCUE_ERRORS
35
+ yaml
36
+ end
37
+ end
38
+ end
39
+ end
40
+ # :startdoc
41
+ end
@@ -57,7 +57,9 @@ 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
+ attr_accessor :automatic_reconnect
60
61
  attr_reader :spec, :connections
62
+ attr_reader :columns, :columns_hash, :primary_keys, :tables
61
63
 
62
64
  # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
63
65
  # object which describes database connection information (e.g. adapter,
@@ -74,8 +76,6 @@ module ActiveRecord
74
76
  # The mutex used to synchronize pool access
75
77
  @connection_mutex = Monitor.new
76
78
  @queue = @connection_mutex.new_cond
77
-
78
- # default 5 second timeout unless on ruby 1.9
79
79
  @timeout = spec.config[:wait_timeout] || 5
80
80
 
81
81
  # default max pool size to 5
@@ -83,6 +83,63 @@ module ActiveRecord
83
83
 
84
84
  @connections = []
85
85
  @checked_out = []
86
+ @automatic_reconnect = true
87
+ @tables = {}
88
+
89
+ @columns = Hash.new do |h, table_name|
90
+ h[table_name] = with_connection do |conn|
91
+
92
+ # Fetch a list of columns
93
+ conn.columns(table_name, "#{table_name} Columns").tap do |columns|
94
+
95
+ # set primary key information
96
+ columns.each do |column|
97
+ column.primary = column.name == primary_keys[table_name]
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ @columns_hash = Hash.new do |h, table_name|
104
+ h[table_name] = Hash[columns[table_name].map { |col|
105
+ [col.name, col]
106
+ }]
107
+ end
108
+
109
+ @primary_keys = Hash.new do |h, table_name|
110
+ h[table_name] = with_connection do |conn|
111
+ table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
112
+ end
113
+ end
114
+ end
115
+
116
+ # A cached lookup for table existence.
117
+ def table_exists?(name)
118
+ return true if @tables.key? name
119
+
120
+ with_connection do |conn|
121
+ conn.tables.each { |table| @tables[table] = true }
122
+ end
123
+
124
+ @tables.key? name
125
+ end
126
+
127
+ # Clears out internal caches:
128
+ #
129
+ # * columns
130
+ # * columns_hash
131
+ # * tables
132
+ def clear_cache!
133
+ @columns.clear
134
+ @columns_hash.clear
135
+ @tables.clear
136
+ end
137
+
138
+ # Clear out internal caches for table with +table_name+.
139
+ def clear_table_cache!(table_name)
140
+ @columns.delete table_name
141
+ @columns_hash.delete table_name
142
+ @primary_keys.delete table_name
86
143
  end
87
144
 
88
145
  # Retrieve the connection associated with the current thread, or call
@@ -94,6 +151,12 @@ module ActiveRecord
94
151
  @reserved_connections[current_connection_id] ||= checkout
95
152
  end
96
153
 
154
+ # Check to see if there is an active connection in this connection
155
+ # pool.
156
+ def active_connection?
157
+ @reserved_connections.key? current_connection_id
158
+ end
159
+
97
160
  # Signal that the thread is finished with the current connection.
98
161
  # #release_connection releases the connection-thread association
99
162
  # and returns the connection to the pool.
@@ -130,7 +193,7 @@ module ActiveRecord
130
193
  @connections = []
131
194
  end
132
195
 
133
- # Clears the cache which maps classes
196
+ # Clears the cache which maps classes.
134
197
  def clear_reloadable_connections!
135
198
  @reserved_connections.each do |name, conn|
136
199
  checkin conn
@@ -214,7 +277,7 @@ module ActiveRecord
214
277
  # calling +checkout+ on this pool.
215
278
  def checkin(conn)
216
279
  @connection_mutex.synchronize do
217
- conn.send(:_run_checkin_callbacks) do
280
+ conn.run_callbacks :checkin do
218
281
  @checked_out.delete conn
219
282
  @queue.signal
220
283
  end
@@ -234,6 +297,8 @@ module ActiveRecord
234
297
  end
235
298
 
236
299
  def checkout_new_connection
300
+ raise ConnectionNotEstablished unless @automatic_reconnect
301
+
237
302
  c = new_connection
238
303
  @connections << c
239
304
  checkout_and_verify(c)
@@ -287,6 +352,12 @@ module ActiveRecord
287
352
  @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
288
353
  end
289
354
 
355
+ # Returns true if there are any active connections among the connection
356
+ # pools that the ConnectionHandler is managing.
357
+ def active_connections?
358
+ connection_pools.values.any? { |pool| pool.active_connection? }
359
+ end
360
+
290
361
  # Returns any connections in use by the current thread back to the pool,
291
362
  # and also returns connections to the pool cached by threads that are no
292
363
  # longer alive.
@@ -294,7 +365,7 @@ module ActiveRecord
294
365
  @connection_pools.each_value {|pool| pool.release_connection }
295
366
  end
296
367
 
297
- # Clears the cache which maps classes
368
+ # Clears the cache which maps classes.
298
369
  def clear_reloadable_connections!
299
370
  @connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
300
371
  end
@@ -332,7 +403,7 @@ module ActiveRecord
332
403
  pool = @connection_pools[klass.name]
333
404
  return nil unless pool
334
405
 
335
- @connection_pools.delete_if { |key, value| value == pool }
406
+ pool.automatic_reconnect = false
336
407
  pool.disconnect!
337
408
  pool.spec.config
338
409
  end
@@ -346,18 +417,40 @@ module ActiveRecord
346
417
  end
347
418
 
348
419
  class ConnectionManagement
420
+ class Proxy # :nodoc:
421
+ attr_reader :body, :testing
422
+
423
+ def initialize(body, testing = false)
424
+ @body = body
425
+ @testing = testing
426
+ end
427
+
428
+ def each(&block)
429
+ body.each(&block)
430
+ end
431
+
432
+ def close
433
+ body.close if body.respond_to?(:close)
434
+
435
+ # Don't return connection (and perform implicit rollback) if
436
+ # this request is a part of integration test
437
+ ActiveRecord::Base.clear_active_connections! unless testing
438
+ end
439
+ end
440
+
349
441
  def initialize(app)
350
442
  @app = app
351
443
  end
352
444
 
353
445
  def call(env)
354
- @app.call(env)
355
- ensure
356
- # Don't return connection (and perform implicit rollback) if
357
- # this request is a part of integration test
358
- unless env.key?("rack.test")
359
- ActiveRecord::Base.clear_active_connections!
360
- end
446
+ testing = env.key?('rack.test')
447
+
448
+ status, headers, body = @app.call(env)
449
+
450
+ [status, headers, Proxy.new(body, testing)]
451
+ rescue
452
+ ActiveRecord::Base.clear_active_connections! unless testing
453
+ raise
361
454
  end
362
455
  end
363
456
  end
@@ -72,7 +72,7 @@ module ActiveRecord
72
72
  end
73
73
 
74
74
  adapter_method = "#{spec[:adapter]}_connection"
75
- if !respond_to?(adapter_method)
75
+ unless respond_to?(adapter_method)
76
76
  raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
77
77
  end
78
78
 
@@ -89,6 +89,16 @@ module ActiveRecord
89
89
  retrieve_connection
90
90
  end
91
91
 
92
+ # Returns the configuration of the associated connection as a hash:
93
+ #
94
+ # ActiveRecord::Base.connection_config
95
+ # # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
96
+ #
97
+ # Please use only for reading.
98
+ def connection_config
99
+ connection_pool.spec.config
100
+ end
101
+
92
102
  def connection_pool
93
103
  connection_handler.retrieve_connection_pool(self)
94
104
  end
@@ -106,7 +116,11 @@ module ActiveRecord
106
116
  connection_handler.remove_connection(klass)
107
117
  end
108
118
 
109
- delegate :clear_active_connections!, :clear_reloadable_connections!,
119
+ def clear_active_connections!
120
+ connection_handler.clear_active_connections!
121
+ end
122
+
123
+ delegate :clear_reloadable_connections!,
110
124
  :clear_all_connections!,:verify_active_connections!, :to => :connection_handler
111
125
  end
112
126
  end
@@ -2,52 +2,53 @@ module ActiveRecord
2
2
  module ConnectionAdapters # :nodoc:
3
3
  module DatabaseLimits
4
4
 
5
- # the maximum length of a table alias
5
+ # Returns the maximum length of a table alias.
6
6
  def table_alias_length
7
7
  255
8
8
  end
9
9
 
10
- # the maximum length of a column name
10
+ # Returns the maximum length of a column name.
11
11
  def column_name_length
12
12
  64
13
13
  end
14
14
 
15
- # the maximum length of a table name
15
+ # Returns the maximum length of a table name.
16
16
  def table_name_length
17
17
  64
18
18
  end
19
19
 
20
- # the maximum length of an index name
20
+ # Returns the maximum length of an index name.
21
21
  def index_name_length
22
22
  64
23
23
  end
24
24
 
25
- # the maximum number of columns per table
25
+ # Returns the maximum number of columns per table.
26
26
  def columns_per_table
27
27
  1024
28
28
  end
29
29
 
30
- # the maximum number of indexes per table
30
+ # Returns the maximum number of indexes per table.
31
31
  def indexes_per_table
32
32
  16
33
33
  end
34
34
 
35
- # the maximum number of columns in a multicolumn index
35
+ # Returns the maximum number of columns in a multicolumn index.
36
36
  def columns_per_multicolumn_index
37
37
  16
38
38
  end
39
39
 
40
- # the maximum number of elements in an IN (x,y,z) clause
40
+ # Returns the maximum number of elements in an IN (x,y,z) clause.
41
+ # nil means no limit.
41
42
  def in_clause_length
42
- 65535
43
+ nil
43
44
  end
44
45
 
45
- # the maximum length of an SQL query
46
+ # Returns the maximum length of an SQL query.
46
47
  def sql_query_length
47
48
  1048575
48
49
  end
49
50
 
50
- # maximum number of joins in a single query
51
+ # Returns maximum number of joins in a single query.
51
52
  def joins_per_query
52
53
  256
53
54
  end
@@ -1,10 +1,20 @@
1
+ require 'active_support/core_ext/module/deprecation'
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module DatabaseStatements
4
6
  # Returns an array of record hashes with the column names as keys and
5
7
  # column values as values.
6
- def select_all(sql, name = nil)
7
- select(sql, name)
8
+ def select_all(sql, name = nil, binds = [])
9
+ if supports_statement_cache?
10
+ select(sql, name, binds)
11
+ else
12
+ return select(sql, name) if binds.empty?
13
+ binds = binds.dup
14
+ select sql.gsub('?') {
15
+ quote(*binds.shift.reverse)
16
+ }, name
17
+ end
8
18
  end
9
19
 
10
20
  # Returns a record hash with the column names as keys and column values
@@ -35,23 +45,59 @@ module ActiveRecord
35
45
  undef_method :select_rows
36
46
 
37
47
  # Executes the SQL statement in the context of this connection.
38
- def execute(sql, name = nil, skip_logging = false)
48
+ def execute(sql, name = nil)
39
49
  end
40
50
  undef_method :execute
41
51
 
52
+ # Executes +sql+ statement in the context of this connection using
53
+ # +binds+ as the bind substitutes. +name+ is logged along with
54
+ # the executed +sql+ statement.
55
+ def exec_query(sql, name = 'SQL', binds = [])
56
+ end
57
+
58
+ # Executes insert +sql+ statement in the context of this connection using
59
+ # +binds+ as the bind substitutes. +name+ is the logged along with
60
+ # the executed +sql+ statement.
61
+ def exec_insert(sql, name, binds)
62
+ exec_query(sql, name, binds)
63
+ end
64
+
65
+ # Executes delete +sql+ statement in the context of this connection using
66
+ # +binds+ as the bind substitutes. +name+ is the logged along with
67
+ # the executed +sql+ statement.
68
+ def exec_delete(sql, name, binds)
69
+ exec_query(sql, name, binds)
70
+ end
71
+
72
+ # Executes update +sql+ statement in the context of this connection using
73
+ # +binds+ as the bind substitutes. +name+ is the logged along with
74
+ # the executed +sql+ statement.
75
+ def exec_update(sql, name, binds)
76
+ exec_query(sql, name, binds)
77
+ end
78
+
42
79
  # Returns the last auto-generated ID from the affected table.
43
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
44
- insert_sql(sql, name, pk, id_value, sequence_name)
80
+ #
81
+ # +id_value+ will be returned unless the value is nil, in
82
+ # which case the database will attempt to calculate the last inserted
83
+ # id and return that value.
84
+ #
85
+ # If the next id was calculated in advance (as in Oracle), it should be
86
+ # passed in as +id_value+.
87
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
88
+ sql, binds = sql_for_insert(sql, pk, id_value, sequence_name, binds)
89
+ value = exec_insert(sql, name, binds)
90
+ id_value || last_inserted_id(value)
45
91
  end
46
92
 
47
93
  # Executes the update statement and returns the number of rows affected.
48
- def update(sql, name = nil)
49
- update_sql(sql, name)
94
+ def update(sql, name = nil, binds = [])
95
+ exec_update(sql, name, binds)
50
96
  end
51
97
 
52
98
  # Executes the delete statement and returns the number of rows affected.
53
- def delete(sql, name = nil)
54
- delete_sql(sql, name)
99
+ def delete(sql, name = nil, binds = [])
100
+ exec_delete(sql, name, binds)
55
101
  end
56
102
 
57
103
  # Checks whether there is currently no transaction active. This is done
@@ -68,6 +114,12 @@ module ActiveRecord
68
114
  nil
69
115
  end
70
116
 
117
+ # Returns +true+ when the connection adapter supports prepared statement
118
+ # caching, otherwise returns +false+
119
+ def supports_statement_cache?
120
+ false
121
+ end
122
+
71
123
  # Runs the given block in a database transaction, and returns the result
72
124
  # of the block.
73
125
  #
@@ -209,11 +261,12 @@ module ActiveRecord
209
261
  #
210
262
  # This method *modifies* the +sql+ parameter.
211
263
  #
264
+ # This method is deprecated!! Stop using it!
265
+ #
212
266
  # ===== Examples
213
267
  # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
214
268
  # generates
215
269
  # SELECT * FROM suppliers LIMIT 10 OFFSET 50
216
-
217
270
  def add_limit_offset!(sql, options)
218
271
  if limit = options[:limit]
219
272
  sql << " LIMIT #{sanitize_limit(limit)}"
@@ -223,6 +276,7 @@ module ActiveRecord
223
276
  end
224
277
  sql
225
278
  end
279
+ deprecate :add_limit_offset!
226
280
 
227
281
  def default_sequence_name(table, column)
228
282
  nil
@@ -236,7 +290,15 @@ module ActiveRecord
236
290
  # Inserts the given fixture into the table. Overridden in adapters that require
237
291
  # something beyond a simple insert (eg. Oracle).
238
292
  def insert_fixture(fixture, table_name)
239
- execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
293
+ columns = Hash[columns(table_name).map { |c| [c.name, c] }]
294
+
295
+ key_list = []
296
+ value_list = fixture.map do |name, value|
297
+ key_list << quote_column_name(name)
298
+ quote(value, columns[name])
299
+ end
300
+
301
+ execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
240
302
  end
241
303
 
242
304
  def empty_insert_statement_value
@@ -273,7 +335,7 @@ module ActiveRecord
273
335
  protected
274
336
  # Returns an array of record hashes with the column names as keys and
275
337
  # column values as values.
276
- def select(sql, name = nil)
338
+ def select(sql, name = nil, binds = [])
277
339
  end
278
340
  undef_method :select
279
341
 
@@ -328,6 +390,15 @@ module ActiveRecord
328
390
  end
329
391
  end
330
392
  end
393
+
394
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
395
+ [sql, binds]
396
+ end
397
+
398
+ def last_inserted_id(result)
399
+ row = result.rows.first
400
+ row && row.first
401
+ end
331
402
  end
332
403
  end
333
404
  end