activerecord 8.0.2.1 → 8.0.3

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +137 -4
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/associations/belongs_to_association.rb +9 -1
  5. data/lib/active_record/associations/collection_association.rb +3 -3
  6. data/lib/active_record/attribute_methods/query.rb +34 -0
  7. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  8. data/lib/active_record/attribute_methods.rb +1 -1
  9. data/lib/active_record/attributes.rb +35 -24
  10. data/lib/active_record/autosave_association.rb +1 -1
  11. data/lib/active_record/base.rb +2 -2
  12. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +1 -1
  13. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -4
  14. data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -6
  15. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +4 -1
  16. data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -1
  17. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -2
  18. data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -2
  19. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +2 -2
  20. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
  21. data/lib/active_record/connection_handling.rb +1 -1
  22. data/lib/active_record/core.rb +7 -5
  23. data/lib/active_record/database_configurations/hash_config.rb +8 -2
  24. data/lib/active_record/delegated_type.rb +1 -1
  25. data/lib/active_record/encryption/encryptable_record.rb +1 -1
  26. data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
  27. data/lib/active_record/encryption/encryptor.rb +27 -25
  28. data/lib/active_record/enum.rb +13 -12
  29. data/lib/active_record/errors.rb +3 -3
  30. data/lib/active_record/fixture_set/table_row.rb +19 -2
  31. data/lib/active_record/gem_version.rb +2 -2
  32. data/lib/active_record/migration.rb +5 -5
  33. data/lib/active_record/query_logs.rb +4 -0
  34. data/lib/active_record/querying.rb +4 -4
  35. data/lib/active_record/railtie.rb +2 -2
  36. data/lib/active_record/railties/databases.rake +8 -16
  37. data/lib/active_record/relation/calculations.rb +15 -16
  38. data/lib/active_record/relation/finder_methods.rb +10 -10
  39. data/lib/active_record/relation/query_methods.rb +4 -4
  40. data/lib/active_record/relation/spawn_methods.rb +6 -6
  41. data/lib/active_record/relation/where_clause.rb +8 -2
  42. data/lib/active_record/relation.rb +14 -4
  43. data/lib/active_record/secure_token.rb +3 -3
  44. data/lib/active_record/signed_id.rb +3 -3
  45. data/lib/active_record/tasks/database_tasks.rb +22 -14
  46. data/lib/active_record/tasks/postgresql_database_tasks.rb +9 -1
  47. data/lib/active_record/test_databases.rb +1 -1
  48. data/lib/active_record/transactions.rb +3 -1
  49. data/lib/active_record.rb +3 -2
  50. data/lib/arel/crud.rb +2 -0
  51. data/lib/arel/delete_manager.rb +5 -0
  52. data/lib/arel/nodes/delete_statement.rb +4 -2
  53. data/lib/arel/nodes/update_statement.rb +4 -2
  54. data/lib/arel/select_manager.rb +6 -2
  55. data/lib/arel/update_manager.rb +5 -0
  56. data/lib/arel/visitors/dot.rb +2 -0
  57. data/lib/arel/visitors/to_sql.rb +2 -0
  58. metadata +8 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a386262cea6480a1111d0bea26f46ba8ff64342b6ef2faa1f8c3f85a0d5c200a
4
- data.tar.gz: 1446cc8e23077a219b71642128ab56d5fc56058c6e1129b32ea8631db41ade63
3
+ metadata.gz: a201047b227b7615aae35a9525320e7a9427be7166babc345db794205c0fd1f0
4
+ data.tar.gz: d16f7b5c723974f806bedd838e23158930014c605ec466061cc096f212e78c13
5
5
  SHA512:
6
- metadata.gz: 8e750c4eb94685b402467c7a7633fcd6420e5de128046a9b77d9d9975264fb7b308f0636eebe2f13a9a9ed9363eb12fd03d6b8808a14ec0e7e5a79e984017242
7
- data.tar.gz: 601127d94e501e2f48d0d43d51dde347fb2904587d2d5d51fb5102c168184d74f2b2d95b063c09fa15e0c1bc839398d9d530302840e2785a24a93b016daeff70
6
+ metadata.gz: f28650737b1284686b6eefb1396354f4a34d7fb39cf66a969cc1d189dc3f2259cd7f11abda795d8836adf699059a3120f088470a8387d159b89f2a295cfecdaa
7
+ data.tar.gz: 803f535ac6e7b962d6433a3e5f1ee58e3e6e1ba452bddfba559ea09f3952c804e3c73a21501da1376b60cdda5af51597e725126108e8c8c5345b25036aecbc20
data/CHANGELOG.md CHANGED
@@ -1,3 +1,140 @@
1
+ ## Rails 8.0.3 (September 22, 2025) ##
2
+
3
+ * Fix query cache for pinned connections in multi threaded transactional tests
4
+
5
+ When a pinned connection is used across separate threads, they now use a separate cache store
6
+ for each thread.
7
+
8
+ This improve accuracy of system tests, and any test using multiple threads.
9
+
10
+ *Heinrich Lee Yu*, *Jean Boussier*
11
+
12
+ * Don't add `id_value` attribute alias when attribute/column with that name already exists.
13
+
14
+ *Rob Lewis*
15
+
16
+ * Fix false positive change detection involving STI and polymorphic has one relationships.
17
+
18
+ Polymorphic `has_one` relationships would always be considered changed when defined in a STI child
19
+ class, causing nedless extra autosaves.
20
+
21
+ *David Fritsch*
22
+
23
+ * Skip calling `PG::Connection#cancel` in `cancel_any_running_query`
24
+ when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
25
+ Rollback still runs, but may take longer.
26
+
27
+ *Yasuo Honda*, *Lars Kanis*
28
+
29
+ * Fix stale association detection for polymorphic `belongs_to`.
30
+
31
+ *Florent Beaurain*, *Thomas Crambert*
32
+
33
+ * Fix removal of PostgreSQL version comments in `structure.sql` for latest PostgreSQL versions which include `\restrict`
34
+
35
+ *Brendan Weibrecht*
36
+
37
+ * Allow setting `schema_format` in database configuration.
38
+
39
+ ```
40
+ primary:
41
+ schema_format: ruby
42
+ ```
43
+
44
+ Useful in multi-database setups to have different formats per-database.
45
+
46
+ *T S Vallender*
47
+
48
+ * Use ntuples to populate row_count instead of count for Postgres
49
+
50
+ *Jonathan Calvert*
51
+
52
+ * Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
53
+
54
+ ```ruby
55
+ base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
56
+ puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
57
+ ```
58
+
59
+ Before:
60
+
61
+ ```SQL
62
+ SELECT "comments".* FROM "comments"
63
+ INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
64
+ WHERE (recent = 1)
65
+ AND (
66
+ "comments"."user_id" = 1
67
+ AND (recent = 1)
68
+ AND "comments"."draft" = 1
69
+ OR "posts"."archived" = 1
70
+ )
71
+ ```
72
+
73
+ After:
74
+
75
+ ```SQL
76
+ SELECT "comments".* FROM "comments"
77
+ INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
78
+ WHERE "comments"."user_id" = 1
79
+ AND (recent = 1)
80
+ AND (
81
+ "comments"."user_id" = 1
82
+ AND (recent = 1)
83
+ AND "comments"."draft" = 1
84
+ OR "posts"."archived" = 1
85
+ )
86
+ ```
87
+
88
+ *Joshua Young*
89
+
90
+ * Fix inline `has_and_belongs_to_many` fixtures for tables with composite primary keys.
91
+
92
+ *fatkodima*
93
+
94
+ * Fix migration log message for down operations.
95
+
96
+ *Bernardo Barreto*
97
+
98
+ * Prepend `extra_flags` in postgres' `structure_load`
99
+
100
+ When specifying `structure_load_flags` with a postgres adapter, the flags
101
+ were appended to the default flags, instead of prepended.
102
+ This caused issues with flags not being taken into account by postgres.
103
+
104
+ *Alice Loeser*
105
+
106
+ * Fix `annotate` comments to propagate to `update_all`/`delete_all`.
107
+
108
+ *fatkodima*
109
+
110
+ * Fix checking whether an unpersisted record is `include?`d in a strictly
111
+ loaded `has_and_belongs_to_many` association.
112
+
113
+ *Hartley McGuire*
114
+
115
+ * `create_or_find_by` will now correctly rollback a transaction.
116
+
117
+ When using `create_or_find_by`, raising a ActiveRecord::Rollback error
118
+ in a `after_save` callback had no effect, the transaction was committed
119
+ and a record created.
120
+
121
+ *Edouard Chin*
122
+
123
+ * Gracefully handle `Timeout.timeout` firing during connection configuration.
124
+
125
+ Use of `Timeout.timeout` could result in improperly initialized database connection.
126
+
127
+ This could lead to a partially configured connection being used, resulting in various exceptions,
128
+ the most common being with the PostgreSQLAdapter raising `undefined method 'key?' for nil`
129
+ or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
130
+
131
+ *Jean Boussier*
132
+
133
+ * Fix stale state for composite foreign keys in belongs_to associations.
134
+
135
+ *Varun Sharma*
136
+
137
+
1
138
  ## Rails 8.0.2.1 (August 13, 2025) ##
2
139
 
3
140
  * Call inspect on ids in RecordNotFound error
@@ -6,10 +143,6 @@
6
143
 
7
144
  *Gannon McGibbon*, *John Hawthorn*
8
145
 
9
- ## Rails 8.0.2 (March 12, 2025) ##
10
-
11
- * No changes.
12
-
13
146
 
14
147
  ## Rails 8.0.2 (March 12, 2025) ##
15
148
 
data/README.rdoc CHANGED
@@ -214,6 +214,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
214
214
 
215
215
  * https://github.com/rails/rails/issues
216
216
 
217
- Feature requests should be discussed on the rails-core mailing list here:
217
+ Feature requests should be discussed on the rubyonrails-core forum here:
218
218
 
219
219
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -162,7 +162,15 @@ module ActiveRecord
162
162
  end
163
163
 
164
164
  def stale_state
165
- owner._read_attribute(reflection.foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
165
+ foreign_key = reflection.foreign_key
166
+ if foreign_key.is_a?(Array)
167
+ attributes = foreign_key.map do |fk|
168
+ owner._read_attribute(fk) { |n| owner.send(:missing_attribute, n, caller) }
169
+ end
170
+ attributes if attributes.any?
171
+ else
172
+ owner._read_attribute(foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
173
+ end
166
174
  end
167
175
  end
168
176
  end
@@ -259,10 +259,10 @@ module ActiveRecord
259
259
  klass = reflection.klass
260
260
  return false unless record.is_a?(klass)
261
261
 
262
- if record.new_record?
263
- include_in_memory?(record)
264
- elsif loaded?
262
+ if loaded?
265
263
  target.include?(record)
264
+ elsif record.new_record?
265
+ include_in_memory?(record)
266
266
  else
267
267
  record_id = klass.composite_primary_key? ? klass.primary_key.zip(record.id).to_h : record.id
268
268
  scope.exists?(record_id)
@@ -3,6 +3,38 @@
3
3
  module ActiveRecord
4
4
  module AttributeMethods
5
5
  # = Active Record Attribute Methods \Query
6
+ #
7
+ # Adds query methods for attributes that return either +true+ or +false+
8
+ # depending on the attribute type and value.
9
+ #
10
+ # For Boolean attributes this will return +true+ if the value is present
11
+ # and return +false+ otherwise:
12
+ #
13
+ # class Product < ActiveRecord::Base
14
+ # end
15
+ #
16
+ # product = Product.new(archived: false)
17
+ # product.archived? # => false
18
+ # product.archived = true
19
+ # product.archived? # => true
20
+ #
21
+ # For Numeric attributes this will return +true+ if the value is a non-zero
22
+ # number and return +false+ otherwise:
23
+ #
24
+ # product.inventory_count = 0
25
+ # product.inventory_count? # => false
26
+ # product.inventory_count = 1
27
+ # product.inventory_count? # => true
28
+ #
29
+ # For other attributes it will return +true+ if the value is present
30
+ # and return +false+ otherwise:
31
+ #
32
+ # product.name = nil
33
+ # product.name? # => false
34
+ # product.name = " "
35
+ # product.name? # => false
36
+ # product.name = "Orange"
37
+ # product.name? # => true
6
38
  module Query
7
39
  extend ActiveSupport::Concern
8
40
 
@@ -10,6 +42,8 @@ module ActiveRecord
10
42
  attribute_method_suffix "?", parameters: false
11
43
  end
12
44
 
45
+ # Returns +true+ or +false+ for the attribute identified by +attr_name+,
46
+ # depending on the attribute type and value.
13
47
  def query_attribute(attr_name)
14
48
  value = self.public_send(attr_name)
15
49
 
@@ -130,7 +130,7 @@ module ActiveRecord
130
130
  # silently cast unsupported types to +String+:
131
131
  #
132
132
  # >> JSON.parse(JSON.dump(Struct.new(:foo)))
133
- # => "#<Class:0x000000013090b4c0>"
133
+ # # => "#<Class:0x000000013090b4c0>"
134
134
  #
135
135
  # ==== Examples
136
136
  #
@@ -113,7 +113,7 @@ module ActiveRecord
113
113
  unless abstract_class?
114
114
  load_schema
115
115
  super(attribute_names)
116
- alias_attribute :id_value, :id if _has_attribute?("id")
116
+ alias_attribute :id_value, :id if _has_attribute?("id") && !_has_attribute?("id_value")
117
117
  end
118
118
 
119
119
  generate_alias_attributes
@@ -21,28 +21,34 @@ module ActiveRecord
21
21
  # your domain objects across much of Active Record, without having to
22
22
  # rely on implementation details or monkey patching.
23
23
  #
24
- # +name+ The name of the methods to define attribute methods for, and the
25
- # column which this will persist to.
24
+ # ==== Parameters
26
25
  #
27
- # +cast_type+ A symbol such as +:string+ or +:integer+, or a type object
28
- # to be used for this attribute. If this parameter is not passed, the previously
29
- # defined type (if any) will be used.
30
- # Otherwise, the type will be ActiveModel::Type::Value.
31
- # See the examples below for more information about providing custom type objects.
26
+ # [+name+]
27
+ # The name of the methods to define attribute methods for, and the
28
+ # column which this will persist to.
32
29
  #
33
- # ==== Options
30
+ # [+cast_type+]
31
+ # A symbol such as +:string+ or +:integer+, or a type object to be used
32
+ # for this attribute. If this parameter is not passed, the previously
33
+ # defined type (if any) will be used. Otherwise, the type will be
34
+ # ActiveModel::Type::Value. See the examples below for more information
35
+ # about providing custom type objects.
34
36
  #
35
- # The following options are accepted:
37
+ # ==== Options
36
38
  #
37
- # +default+ The default value to use when no value is provided. If this option
38
- # is not passed, the previously defined default value (if any) on the superclass or in the schema will be used.
39
- # Otherwise, the default will be +nil+.
39
+ # [+:default+]
40
+ # The default value to use when no value is provided. If this option is
41
+ # not passed, the previously defined default value (if any) on the
42
+ # superclass or in the schema will be used. Otherwise, the default will
43
+ # be +nil+.
40
44
  #
41
- # +array+ (PostgreSQL only) specifies that the type should be an array (see the
42
- # examples below).
45
+ # [+:array+]
46
+ # (PostgreSQL only) Specifies that the type should be an array. See the
47
+ # examples below.
43
48
  #
44
- # +range+ (PostgreSQL only) specifies that the type should be a range (see the
45
- # examples below).
49
+ # [+:range+]
50
+ # (PostgreSQL only) Specifies that the type should be a range. See the
51
+ # examples below.
46
52
  #
47
53
  # When using a symbol for +cast_type+, extra options are forwarded to the
48
54
  # constructor of the type object.
@@ -217,17 +223,22 @@ module ActiveRecord
217
223
  # is provided so it can be used by plugin authors, application code
218
224
  # should probably use ClassMethods#attribute.
219
225
  #
220
- # +name+ The name of the attribute being defined. Expected to be a +String+.
226
+ # ==== Parameters
227
+ #
228
+ # [+name+]
229
+ # The name of the attribute being defined. Expected to be a +String+.
221
230
  #
222
- # +cast_type+ The type object to use for this attribute.
231
+ # [+cast_type+]
232
+ # The type object to use for this attribute.
223
233
  #
224
- # +default+ The default value to use when no value is provided. If this option
225
- # is not passed, the previous default value (if any) will be used.
226
- # Otherwise, the default will be +nil+. A proc can also be passed, and
227
- # will be called once each time a new value is needed.
234
+ # [+default+]
235
+ # The default value to use when no value is provided. If this option
236
+ # is not passed, the previous default value (if any) will be used.
237
+ # Otherwise, the default will be +nil+. A proc can also be passed, and
238
+ # will be called once each time a new value is needed.
228
239
  #
229
- # +user_provided_default+ Whether the default value should be cast using
230
- # +cast+ or +deserialize+.
240
+ # [+user_provided_default+]
241
+ # Whether the default value should be cast using +cast+ or +deserialize+.
231
242
  def define_attribute(
232
243
  name,
233
244
  cast_type,
@@ -527,7 +527,7 @@ module ActiveRecord
527
527
  return false unless reflection.inverse_of&.polymorphic?
528
528
 
529
529
  class_name = record._read_attribute(reflection.inverse_of.foreign_type)
530
- reflection.active_record != record.class.polymorphic_class_for(class_name)
530
+ reflection.active_record.polymorphic_name != class_name
531
531
  end
532
532
 
533
533
  # Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
@@ -256,13 +256,13 @@ module ActiveRecord # :nodoc:
256
256
  # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
257
257
  # specified in the association definition.
258
258
  # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
259
- # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
259
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:ActiveModel::AttributeAssignment#attributes=] method.
260
260
  # You can inspect the +attribute+ property of the exception object to determine which attribute
261
261
  # triggered the error.
262
262
  # * ConnectionNotEstablished - No connection has been established.
263
263
  # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
264
264
  # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
265
- # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
265
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:ActiveModel::AttributeAssignment#attributes=] method.
266
266
  # The +errors+ property of this exception contains an array of
267
267
  # AttributeAssignmentError
268
268
  # objects that should be inspected to determine which attributes triggered the errors.
@@ -168,7 +168,7 @@ module ActiveRecord
168
168
  end
169
169
  end
170
170
 
171
- # Clears the cache which maps classes.
171
+ # Clears reloadable connection caches in all connection pools.
172
172
  #
173
173
  # See ConnectionPool#clear_reloadable_connections! for details.
174
174
  def clear_reloadable_connections!(role = nil)
@@ -36,6 +36,7 @@ module ActiveRecord
36
36
  end
37
37
 
38
38
  def schema_cache; end
39
+ def query_cache; end
39
40
  def connection_descriptor; end
40
41
  def checkin(_); end
41
42
  def remove(_); end
@@ -124,7 +125,7 @@ module ActiveRecord
124
125
  else
125
126
  class WeakThreadKeyMap # :nodoc:
126
127
  # FIXME: On 3.3 we could use ObjectSpace::WeakKeyMap
127
- # but it currently cause GC crashes: https://github.com/byroot/rails/pull/3
128
+ # but it currently causes GC crashes: https://github.com/byroot/rails/pull/3
128
129
  def initialize
129
130
  @map = {}
130
131
  end
@@ -314,8 +315,9 @@ module ActiveRecord
314
315
  # held in a cache keyed by a thread.
315
316
  def lease_connection
316
317
  lease = connection_lease
317
- lease.sticky = true
318
318
  lease.connection ||= checkout
319
+ lease.sticky = true
320
+ lease.connection
319
321
  end
320
322
 
321
323
  def permanent_lease? # :nodoc:
@@ -333,6 +335,7 @@ module ActiveRecord
333
335
  end
334
336
 
335
337
  @pinned_connection.lock_thread = ActiveSupport::IsolatedExecutionState.context if lock_thread
338
+ @pinned_connection.pinned = true
336
339
  @pinned_connection.verify! # eagerly validate the connection
337
340
  @pinned_connection.begin_transaction joinable: false, _lazy: false
338
341
  end
@@ -355,6 +358,7 @@ module ActiveRecord
355
358
  end
356
359
 
357
360
  if @pinned_connection.nil?
361
+ connection.pinned = false
358
362
  connection.steal!
359
363
  connection.lock_thread = nil
360
364
  checkin(connection)
@@ -495,7 +499,7 @@ module ActiveRecord
495
499
  @connections.nil?
496
500
  end
497
501
 
498
- # Clears the cache which maps classes and re-connects connections that
502
+ # Clears reloadable connections from the pool and re-connects connections that
499
503
  # require reloading.
500
504
  #
501
505
  # Raises:
@@ -518,7 +522,7 @@ module ActiveRecord
518
522
  end
519
523
  end
520
524
 
521
- # Clears the cache which maps classes and re-connects connections that
525
+ # Clears reloadable connections from the pool and re-connects connections that
522
526
  # require reloading.
523
527
  #
524
528
  # The pool first tries to gain ownership of all connections. If unable to
@@ -191,15 +191,26 @@ module ActiveRecord
191
191
  end
192
192
  end
193
193
 
194
- attr_accessor :query_cache
195
-
196
194
  def initialize(*)
197
195
  super
198
196
  @query_cache = nil
199
197
  end
200
198
 
199
+ attr_writer :query_cache
200
+
201
+ def query_cache
202
+ if @pinned && @owner != ActiveSupport::IsolatedExecutionState.context
203
+ # With transactional tests, if the connection is pinned, any thread
204
+ # other than the one that pinned the connection need to go through the
205
+ # query cache pool, so each thread get a different cache.
206
+ pool.query_cache
207
+ else
208
+ @query_cache
209
+ end
210
+ end
211
+
201
212
  def query_cache_enabled
202
- @query_cache&.enabled?
213
+ query_cache&.enabled?
203
214
  end
204
215
 
205
216
  # Enable the query cache within the block.
@@ -238,7 +249,7 @@ module ActiveRecord
238
249
 
239
250
  # If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
240
251
  # Such queries should not be cached.
241
- if @query_cache&.enabled? && !(arel.respond_to?(:locked) && arel.locked)
252
+ if query_cache_enabled && !(arel.respond_to?(:locked) && arel.locked)
242
253
  sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable)
243
254
 
244
255
  if async
@@ -262,7 +273,7 @@ module ActiveRecord
262
273
 
263
274
  result = nil
264
275
  @lock.synchronize do
265
- result = @query_cache[key]
276
+ result = query_cache[key]
266
277
  end
267
278
 
268
279
  if result
@@ -281,7 +292,7 @@ module ActiveRecord
281
292
  hit = true
282
293
 
283
294
  @lock.synchronize do
284
- result = @query_cache.compute_if_absent(key) do
295
+ result = query_cache.compute_if_absent(key) do
285
296
  hit = false
286
297
  yield
287
298
  end
@@ -186,6 +186,9 @@ module ActiveRecord
186
186
  # Join tables for {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] should set it to false.
187
187
  #
188
188
  # A Symbol can be used to specify the type of the generated primary key column.
189
+ #
190
+ # A Hash can be used to specify the generated primary key column creation options.
191
+ # See {add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column] for available options.
189
192
  # [<tt>:primary_key</tt>]
190
193
  # The name of the primary key, if one is to be added automatically.
191
194
  # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
@@ -548,7 +551,7 @@ module ActiveRecord
548
551
  #
549
552
  # See {ActiveRecord::ConnectionAdapters::TableDefinition.column}[rdoc-ref:ActiveRecord::ConnectionAdapters::TableDefinition#column].
550
553
  #
551
- # The +type+ parameter is normally one of the migrations native types,
554
+ # The +type+ parameter is normally one of the migration's native types,
552
555
  # which is one of the following:
553
556
  # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
554
557
  # <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
@@ -42,6 +42,7 @@ module ActiveRecord
42
42
 
43
43
  attr_reader :pool
44
44
  attr_reader :visitor, :owner, :logger, :lock
45
+ attr_accessor :pinned # :nodoc:
45
46
  alias :in_use? :owner
46
47
 
47
48
  def pool=(value)
@@ -150,6 +151,7 @@ module ActiveRecord
150
151
  end
151
152
 
152
153
  @owner = nil
154
+ @pinned = false
153
155
  @pool = ActiveRecord::ConnectionAdapters::NullPool.new
154
156
  @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
155
157
  @visitor = arel_visitor
@@ -1215,7 +1217,7 @@ module ActiveRecord
1215
1217
 
1216
1218
  def attempt_configure_connection
1217
1219
  configure_connection
1218
- rescue
1220
+ rescue Exception # Need to handle things such as Timeout::ExitException
1219
1221
  disconnect!
1220
1222
  raise
1221
1223
  end
@@ -127,7 +127,14 @@ module ActiveRecord
127
127
  def cancel_any_running_query
128
128
  return if @raw_connection.nil? || IDLE_TRANSACTION_STATUSES.include?(@raw_connection.transaction_status)
129
129
 
130
- @raw_connection.cancel
130
+ # Skip @raw_connection.cancel (PG::Connection#cancel) when using libpq >= 18 with pg < 1.6.0,
131
+ # because the pg gem cannot obtain the backend_key in that case.
132
+ # This method is only called from exec_rollback_db_transaction and exec_restart_db_transaction.
133
+ # Even without cancel, rollback will still run. However, since any running
134
+ # query must finish first, the rollback may take longer.
135
+ if !(PG.library_version >= 18_00_00 && Gem::Version.new(PG::VERSION) < Gem::Version.new("1.6.0"))
136
+ @raw_connection.cancel
137
+ end
131
138
  @raw_connection.block
132
139
  rescue PG::Error
133
140
  end
@@ -164,7 +171,7 @@ module ActiveRecord
164
171
 
165
172
  verified!
166
173
  handle_warnings(result)
167
- notification_payload[:row_count] = result.count
174
+ notification_payload[:row_count] = result.ntuples
168
175
  result
169
176
  end
170
177
 
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
  #
26
26
  # The PostgreSQL adapter works with the native C (https://github.com/ged/ruby-pg) driver.
27
27
  #
28
- # Options:
28
+ # ==== Options
29
29
  #
30
30
  # * <tt>:host</tt> - Defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets,
31
31
  # the default is to connect to localhost.
@@ -616,7 +616,7 @@ module ActiveRecord
616
616
  }
617
617
  end
618
618
 
619
- # Returns the configured supported identifier length supported by PostgreSQL
619
+ # Returns the configured maximum supported identifier length supported by PostgreSQL
620
620
  def max_identifier_length
621
621
  @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
622
622
  end
@@ -114,8 +114,8 @@ module ActiveRecord
114
114
  end
115
115
 
116
116
  def cast_result(result)
117
- # Given that SQLite3 doesn't really a Result type, raw_execute already return an ActiveRecord::Result
118
- # and we have nothing to cast here.
117
+ # Given that SQLite3 doesn't have a Result type, raw_execute already returns an ActiveRecord::Result
118
+ # so we have nothing to cast here.
119
119
  result
120
120
  end
121
121
 
@@ -24,7 +24,7 @@ module ActiveRecord
24
24
  # The SQLite3 adapter works with the sqlite3-ruby drivers
25
25
  # (available as gem from https://rubygems.org/gems/sqlite3).
26
26
  #
27
- # Options:
27
+ # ==== Options
28
28
  #
29
29
  # * <tt>:database</tt> - Path to the database file.
30
30
  class SQLite3Adapter < AbstractAdapter
@@ -309,7 +309,7 @@ module ActiveRecord
309
309
  # Creates a virtual table
310
310
  #
311
311
  # Example:
312
- # create_virtual_table :emails, :fts5, ['sender', 'title',' body']
312
+ # create_virtual_table :emails, :fts5, ['sender', 'title', 'body']
313
313
  def create_virtual_table(table_name, module_name, values)
314
314
  exec_query "CREATE VIRTUAL TABLE IF NOT EXISTS #{table_name} USING #{module_name} (#{values.join(", ")})"
315
315
  end
@@ -301,7 +301,7 @@ module ActiveRecord
301
301
 
302
302
  # Checkouts a connection from the pool, yield it and then check it back in.
303
303
  # If a connection was already leased via #lease_connection or a parent call to
304
- # #with_connection, that same connection is yieled.
304
+ # #with_connection, that same connection is yielded.
305
305
  # If #lease_connection is called inside the block, the connection won't be checked
306
306
  # back in.
307
307
  # If #connection is called inside the block, the connection won't be checked back in