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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +137 -4
- data/README.rdoc +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +9 -1
- data/lib/active_record/associations/collection_association.rb +3 -3
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/attributes.rb +35 -24
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -4
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +4 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +7 -5
- data/lib/active_record/database_configurations/hash_config.rb +8 -2
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/encryption/encryptable_record.rb +1 -1
- data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
- data/lib/active_record/encryption/encryptor.rb +27 -25
- data/lib/active_record/enum.rb +13 -12
- data/lib/active_record/errors.rb +3 -3
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/migration.rb +5 -5
- data/lib/active_record/query_logs.rb +4 -0
- data/lib/active_record/querying.rb +4 -4
- data/lib/active_record/railtie.rb +2 -2
- data/lib/active_record/railties/databases.rake +8 -16
- data/lib/active_record/relation/calculations.rb +15 -16
- data/lib/active_record/relation/finder_methods.rb +10 -10
- data/lib/active_record/relation/query_methods.rb +4 -4
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +8 -2
- data/lib/active_record/relation.rb +14 -4
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +3 -3
- data/lib/active_record/tasks/database_tasks.rb +22 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +9 -1
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/transactions.rb +3 -1
- data/lib/active_record.rb +3 -2
- data/lib/arel/crud.rb +2 -0
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/select_manager.rb +6 -2
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -0
- data/lib/arel/visitors/to_sql.rb +2 -0
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a201047b227b7615aae35a9525320e7a9427be7166babc345db794205c0fd1f0
|
4
|
+
data.tar.gz: d16f7b5c723974f806bedd838e23158930014c605ec466061cc096f212e78c13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
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
|
|
@@ -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
|
-
#
|
25
|
-
# column which this will persist to.
|
24
|
+
# ==== Parameters
|
26
25
|
#
|
27
|
-
# +
|
28
|
-
#
|
29
|
-
#
|
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
|
-
#
|
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
|
-
#
|
37
|
+
# ==== Options
|
36
38
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
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
|
-
#
|
42
|
-
#
|
45
|
+
# [+:array+]
|
46
|
+
# (PostgreSQL only) Specifies that the type should be an array. See the
|
47
|
+
# examples below.
|
43
48
|
#
|
44
|
-
#
|
45
|
-
#
|
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
|
-
#
|
226
|
+
# ==== Parameters
|
227
|
+
#
|
228
|
+
# [+name+]
|
229
|
+
# The name of the attribute being defined. Expected to be a +String+.
|
221
230
|
#
|
222
|
-
# +cast_type+
|
231
|
+
# [+cast_type+]
|
232
|
+
# The type object to use for this attribute.
|
223
233
|
#
|
224
|
-
# +default+
|
225
|
-
#
|
226
|
-
#
|
227
|
-
# will be
|
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+
|
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 !=
|
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.
|
data/lib/active_record/base.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
-
|
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
|
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 =
|
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 =
|
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
|
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.
|
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
|
118
|
-
#
|
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','
|
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
|
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
|