activerecord 7.1.1 → 7.1.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +177 -0
  3. data/README.rdoc +1 -0
  4. data/lib/active_record/associations/association.rb +2 -1
  5. data/lib/active_record/associations/preloader/association.rb +4 -1
  6. data/lib/active_record/associations.rb +15 -15
  7. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  8. data/lib/active_record/attribute_methods/dirty.rb +13 -9
  9. data/lib/active_record/attribute_methods.rb +1 -1
  10. data/lib/active_record/callbacks.rb +2 -2
  11. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +11 -8
  12. data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -2
  13. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +13 -4
  15. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +3 -0
  16. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +4 -1
  17. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  18. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -5
  19. data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -33
  20. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -3
  21. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +1 -0
  22. data/lib/active_record/connection_adapters/trilogy_adapter.rb +9 -1
  23. data/lib/active_record/connection_handling.rb +1 -1
  24. data/lib/active_record/core.rb +41 -7
  25. data/lib/active_record/delegated_type.rb +1 -1
  26. data/lib/active_record/encryption/encryptable_record.rb +7 -1
  27. data/lib/active_record/encryption/encrypted_attribute_type.rb +4 -0
  28. data/lib/active_record/encryption/extended_deterministic_queries.rb +0 -15
  29. data/lib/active_record/enum.rb +6 -9
  30. data/lib/active_record/errors.rb +5 -4
  31. data/lib/active_record/fixtures.rb +16 -0
  32. data/lib/active_record/future_result.rb +1 -0
  33. data/lib/active_record/gem_version.rb +1 -1
  34. data/lib/active_record/insert_all.rb +3 -3
  35. data/lib/active_record/internal_metadata.rb +1 -1
  36. data/lib/active_record/middleware/database_selector.rb +1 -1
  37. data/lib/active_record/migration/compatibility.rb +8 -0
  38. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  39. data/lib/active_record/migration.rb +9 -5
  40. data/lib/active_record/model_schema.rb +5 -5
  41. data/lib/active_record/nested_attributes.rb +3 -3
  42. data/lib/active_record/normalization.rb +8 -0
  43. data/lib/active_record/persistence.rb +4 -3
  44. data/lib/active_record/promise.rb +1 -1
  45. data/lib/active_record/railties/controller_runtime.rb +2 -1
  46. data/lib/active_record/railties/databases.rake +5 -5
  47. data/lib/active_record/reflection.rb +13 -1
  48. data/lib/active_record/relation/calculations.rb +28 -1
  49. data/lib/active_record/relation/delegation.rb +1 -1
  50. data/lib/active_record/relation.rb +18 -3
  51. data/lib/active_record/runtime_registry.rb +15 -1
  52. data/lib/active_record/schema_migration.rb +1 -1
  53. data/lib/active_record/secure_token.rb +1 -1
  54. data/lib/active_record/tasks/database_tasks.rb +5 -5
  55. data/lib/arel/nodes/homogeneous_in.rb +1 -1
  56. metadata +10 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3595eee8065caff3100f00f5ce54d1b3a34935759766cb16b4d8229a57ebc97e
4
- data.tar.gz: 5fbab431bcbc3b56cae5b2d8400c893071c72ccc7feea3eb6d9343418c650ec6
3
+ metadata.gz: 9f7c51f040979b7650eb209b0dc856a0877bccc968dd99cde06e3cf1776dd638
4
+ data.tar.gz: b81eca56b185f087c95b6691b307ff1c9c63d0d03ff650b729e943888f053152
5
5
  SHA512:
6
- metadata.gz: c75c3da922f3b0089112bb07c115787bedc1bb57a6e05aa04df893262554e09bf81e71898ac7ed24b1c80a00071818e14267cbffc2bb2b789755867b85f76d78
7
- data.tar.gz: 5f6684e9a76e3a2a7156b687d4ac0701b9ddd840edd9c671f51031c534bdbd1e920b2aad65a479299383cb8555346a585e3167c353f33f95ecf8e05115438205
6
+ metadata.gz: 6f68dc9e6cdccf23f5467810a68083564760601aa3c82b4c85720cfb2c39500439a86bb63c2ce8fea37337de6fc4f157722300c691cfd239e92732569b5c20f6
7
+ data.tar.gz: 6f8382df74c2c16b873cab0effeda0a3ef3e578d5087e435d7d2f8c6890dcf0d85e2211f2bc890182af49e836b09e4e345e2b9bc37eb8472814e98bb6636b005
data/CHANGELOG.md CHANGED
@@ -1,3 +1,176 @@
1
+ ## Rails 7.1.3 (January 16, 2024) ##
2
+
3
+ * Fix Migrations with versions older than 7.1 validating options given to
4
+ `add_reference`.
5
+
6
+ *Hartley McGuire*
7
+
8
+ * Ensure `reload` sets correct owner for each association.
9
+
10
+ *Dmytro Savochkin*
11
+
12
+ * Fix view runtime for controllers with async queries.
13
+
14
+ *fatkodima*
15
+
16
+ * Fix `load_async` to work with query cache.
17
+
18
+ *fatkodima*
19
+
20
+ * Fix polymorphic `belongs_to` to correctly use parent's `query_constraints`.
21
+
22
+ *fatkodima*
23
+
24
+ * Fix `Preloader` to not generate a query for already loaded association with `query_constraints`.
25
+
26
+ *fatkodima*
27
+
28
+ * Fix multi-database polymorphic preloading with equivalent table names.
29
+
30
+ When preloading polymorphic associations, if two models pointed to two
31
+ tables with the same name but located in different databases, the
32
+ preloader would only load one.
33
+
34
+ *Ari Summer*
35
+
36
+ * Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
37
+
38
+ *Maxime Réty*
39
+
40
+ * Fix `find_by` to work correctly in presence of composite primary keys.
41
+
42
+ *fatkodima*
43
+
44
+ * Fix async queries sometimes returning a raw result if they hit the query cache.
45
+
46
+ `ShipPart.async_count` could return a raw integer rather than a Promise
47
+ if it found the result in the query cache.
48
+
49
+ *fatkodima*
50
+
51
+ * Fix `Relation#transaction` to not apply a default scope.
52
+
53
+ The method was incorrectly setting a default scope around its block:
54
+
55
+ ```ruby
56
+ Post.where(published: true).transaction do
57
+ Post.count # SELECT COUNT(*) FROM posts WHERE published = FALSE;
58
+ end
59
+ ```
60
+
61
+ *Jean Boussier*
62
+
63
+ * Fix calling `async_pluck` on a `none` relation.
64
+
65
+ `Model.none.async_pluck(:id)` was returning a naked value
66
+ instead of a promise.
67
+
68
+ *Jean Boussier*
69
+
70
+ * Fix calling `load_async` on a `none` relation.
71
+
72
+ `Model.none.load_async` was returning a broken result.
73
+
74
+ *Lucas Mazza*
75
+
76
+ * TrilogyAdapter: ignore `host` if `socket` parameter is set.
77
+
78
+ This allows to configure a connection on a UNIX socket via DATABASE_URL:
79
+
80
+ ```
81
+ DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
82
+ ```
83
+
84
+ *Jean Boussier*
85
+
86
+ * Fix `has_secure_token` calls the setter method on initialize.
87
+
88
+ *Abeid Ahmed*
89
+
90
+ * Allow using `object_id` as a database column name.
91
+ It was available before rails 7.1 and may be used as a part of polymorphic relationship to `object` where `object` can be any other database record.
92
+
93
+ *Mikhail Doronin*
94
+
95
+ * Fix `rails db:create:all` to not touch databases before they are created.
96
+
97
+ *fatkodima*
98
+
99
+
100
+ ## Rails 7.1.2 (November 10, 2023) ##
101
+
102
+ * Fix renaming primary key index when renaming a table with a UUID primary key
103
+ in PostgreSQL.
104
+
105
+ *fatkodima*
106
+
107
+ * Fix `where(field: values)` queries when `field` is a serialized attribute
108
+ (for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
109
+ column).
110
+
111
+ *João Alves*
112
+
113
+ * Prevent marking broken connections as verified.
114
+
115
+ *Daniel Colson*
116
+
117
+ * Don't mark Float::INFINITY as changed when reassigning it
118
+
119
+ When saving a record with a float infinite value, it shouldn't mark as changed
120
+
121
+ *Maicol Bentancor*
122
+
123
+ * `ActiveRecord::Base.table_name` now returns `nil` instead of raising
124
+ "undefined method `abstract_class?` for Object:Class".
125
+
126
+ *a5-stable*
127
+
128
+ * Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all
129
+ inserts keys.
130
+
131
+ *fatkodima*
132
+
133
+ * Fixed an [issue](https://github.com/rails/rails/issues/49809) where saving a
134
+ record could innappropriately `dup` its attributes.
135
+
136
+ *Jonathan Hefner*
137
+
138
+ * Dump schema only for a specific db for rollback/up/down tasks for multiple dbs.
139
+
140
+ *fatkodima*
141
+
142
+ * Fix `NoMethodError` when casting a PostgreSQL `money` value that uses a
143
+ comma as its radix point and has no leading currency symbol. For example,
144
+ when casting `"3,50"`.
145
+
146
+ *Andreas Reischuck* and *Jonathan Hefner*
147
+
148
+ * Re-enable support for using `enum` with non-column-backed attributes.
149
+ Non-column-backed attributes must be previously declared with an explicit
150
+ type. For example:
151
+
152
+ ```ruby
153
+ class Post < ActiveRecord::Base
154
+ attribute :topic, :string
155
+ enum topic: %i[science tech engineering math]
156
+ end
157
+ ```
158
+
159
+ *Jonathan Hefner*
160
+
161
+ * Raise on `foreign_key:` being passed as an array in associations
162
+
163
+ *Nikita Vasilevsky*
164
+
165
+ * Return back maximum allowed PostgreSQL table name to 63 characters.
166
+
167
+ *fatkodima*
168
+
169
+ * Fix detecting `IDENTITY` columns for PostgreSQL < 10.
170
+
171
+ *fatkodima*
172
+
173
+
1
174
  ## Rails 7.1.1 (October 11, 2023) ##
2
175
 
3
176
  * Fix auto populating IDENTITY columns for PostgreSQL.
@@ -165,6 +338,10 @@
165
338
 
166
339
  *Adam Hess*
167
340
 
341
+ * Deprecate aliasing non-attributes with `alias_attribute`.
342
+
343
+ *Ian Candy*
344
+
168
345
  * Fix unscope is not working in specific case
169
346
 
170
347
  Before:
data/README.rdoc CHANGED
@@ -166,6 +166,7 @@ Active Record is an implementation of the object-relational mapping (ORM)
166
166
  pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
167
167
  name described by Martin Fowler:
168
168
 
169
+ >>>
169
170
  "An object that wraps a row in a database table or view,
170
171
  encapsulates the database access, and adds domain logic on that data."
171
172
 
@@ -33,7 +33,8 @@ module ActiveRecord
33
33
  # <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
34
34
  # the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
35
35
  class Association # :nodoc:
36
- attr_reader :owner, :target, :reflection, :disable_joins
36
+ attr_accessor :owner
37
+ attr_reader :target, :reflection, :disable_joins
37
38
 
38
39
  delegate :options, to: :reflection
39
40
 
@@ -17,11 +17,12 @@ module ActiveRecord
17
17
  def eql?(other)
18
18
  association_key_name == other.association_key_name &&
19
19
  scope.table_name == other.scope.table_name &&
20
+ scope.connection_specification_name == other.scope.connection_specification_name &&
20
21
  scope.values_for_queries == other.scope.values_for_queries
21
22
  end
22
23
 
23
24
  def hash
24
- [association_key_name, scope.table_name, scope.values_for_queries].hash
25
+ [association_key_name, scope.table_name, scope.connection_specification_name, scope.values_for_queries].hash
25
26
  end
26
27
 
27
28
  def records_for(loaders)
@@ -38,6 +39,8 @@ module ActiveRecord
38
39
  end
39
40
 
40
41
  def load_records_for_keys(keys, &block)
42
+ return [] if keys.empty?
43
+
41
44
  if association_key_name.is_a?(Array)
42
45
  query_constraints = Hash.new { |hsh, key| hsh[key] = Set.new }
43
46
 
@@ -1050,7 +1050,7 @@ module ActiveRecord
1050
1050
  # query per addressable type.
1051
1051
  # For example, if all the addressables are either of class Person or Company, then a total
1052
1052
  # of 3 queries will be executed. The list of addressable types to load is determined on
1053
- # the back of the addresses loaded. This is not supported if Active Record has to fallback
1053
+ # the back of the addresses loaded. This is not supported if Active Record has to fall back
1054
1054
  # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
1055
1055
  # The reason is that the parent model's type is a column value so its corresponding table
1056
1056
  # name cannot be put in the +FROM+/+JOIN+ clauses of that query.
@@ -1339,7 +1339,7 @@ module ActiveRecord
1339
1339
  # Returns a Relation of all of the associated objects, forcing a database read.
1340
1340
  # An empty Relation is returned if none are found.
1341
1341
  #
1342
- # === Example
1342
+ # ==== Example
1343
1343
  #
1344
1344
  # class Firm < ActiveRecord::Base
1345
1345
  # has_many :clients
@@ -1369,7 +1369,7 @@ module ActiveRecord
1369
1369
  #
1370
1370
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1371
1371
  #
1372
- # === Scopes
1372
+ # ==== Scopes
1373
1373
  #
1374
1374
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1375
1375
  # lambda) to retrieve a specific set of records or customize the generated
@@ -1380,7 +1380,7 @@ module ActiveRecord
1380
1380
  # has_many :employees, -> { joins(:address) }
1381
1381
  # has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
1382
1382
  #
1383
- # === Extensions
1383
+ # ==== Extensions
1384
1384
  #
1385
1385
  # The +extension+ argument allows you to pass a block into a has_many
1386
1386
  # association. This is useful for adding new finders, creators, and other
@@ -1394,7 +1394,7 @@ module ActiveRecord
1394
1394
  # end
1395
1395
  # end
1396
1396
  #
1397
- # === Options
1397
+ # ==== Options
1398
1398
  # [+:class_name+]
1399
1399
  # Specify the class name of the association. Use it only if that name can't be inferred
1400
1400
  # from the association name. So <tt>has_many :products</tt> will by default be linked
@@ -1556,7 +1556,7 @@ module ActiveRecord
1556
1556
  # [<tt>reset_association</tt>]
1557
1557
  # Unloads the associated object. The next access will query it from the database.
1558
1558
  #
1559
- # === Example
1559
+ # ==== Example
1560
1560
  #
1561
1561
  # class Account < ActiveRecord::Base
1562
1562
  # has_one :beneficiary
@@ -1575,7 +1575,7 @@ module ActiveRecord
1575
1575
  # account.reload_beneficiary
1576
1576
  # account.reset_beneficiary
1577
1577
  #
1578
- # === Scopes
1578
+ # ==== Scopes
1579
1579
  #
1580
1580
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1581
1581
  # lambda) to retrieve a specific record or customize the generated query
@@ -1586,7 +1586,7 @@ module ActiveRecord
1586
1586
  # has_one :employer, -> { joins(:company) }
1587
1587
  # has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
1588
1588
  #
1589
- # === Options
1589
+ # ==== Options
1590
1590
  #
1591
1591
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1592
1592
  #
@@ -1745,7 +1745,7 @@ module ActiveRecord
1745
1745
  # [<tt>association_previously_changed?</tt>]
1746
1746
  # Returns true if the previous save updated the association to reference a new associate object.
1747
1747
  #
1748
- # === Example
1748
+ # ==== Example
1749
1749
  #
1750
1750
  # class Post < ActiveRecord::Base
1751
1751
  # belongs_to :author
@@ -1766,7 +1766,7 @@ module ActiveRecord
1766
1766
  # post.author_changed?
1767
1767
  # post.author_previously_changed?
1768
1768
  #
1769
- # === Scopes
1769
+ # ==== Scopes
1770
1770
  #
1771
1771
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1772
1772
  # lambda) to retrieve a specific record or customize the generated query
@@ -1777,7 +1777,7 @@ module ActiveRecord
1777
1777
  # belongs_to :user, -> { joins(:friends) }
1778
1778
  # belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
1779
1779
  #
1780
- # === Options
1780
+ # ==== Options
1781
1781
  #
1782
1782
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1783
1783
  #
@@ -1964,7 +1964,7 @@ module ActiveRecord
1964
1964
  # Returns a Relation of all of the associated objects, forcing a database read.
1965
1965
  # An empty Relation is returned if none are found.
1966
1966
  #
1967
- # === Example
1967
+ # ==== Example
1968
1968
  #
1969
1969
  # class Developer < ActiveRecord::Base
1970
1970
  # has_and_belongs_to_many :projects
@@ -1993,7 +1993,7 @@ module ActiveRecord
1993
1993
  #
1994
1994
  # The declaration may include an +options+ hash to specialize the behavior of the association.
1995
1995
  #
1996
- # === Scopes
1996
+ # ==== Scopes
1997
1997
  #
1998
1998
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1999
1999
  # lambda) to retrieve a specific set of records or customize the generated
@@ -2005,7 +2005,7 @@ module ActiveRecord
2005
2005
  # where("default_category = ?", post.default_category)
2006
2006
  # }
2007
2007
  #
2008
- # === Extensions
2008
+ # ==== Extensions
2009
2009
  #
2010
2010
  # The +extension+ argument allows you to pass a block into a
2011
2011
  # has_and_belongs_to_many association. This is useful for adding new
@@ -2020,7 +2020,7 @@ module ActiveRecord
2020
2020
  # end
2021
2021
  # end
2022
2022
  #
2023
- # === Options
2023
+ # ==== Options
2024
2024
  #
2025
2025
  # [+:class_name+]
2026
2026
  # Specify the class name of the association. Use it only if that name can't be inferred
@@ -56,7 +56,7 @@ module ActiveRecord
56
56
  # serialization.
57
57
  #
58
58
  # class Book < ActiveRecord::Base
59
- # enum status: { draft: 1, published: 2 }
59
+ # enum :status, { draft: 1, published: 2 }
60
60
  # end
61
61
  #
62
62
  # book = Book.new(status: "published")
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  # class Person < ActiveRecord::Base
15
15
  # end
16
16
  #
17
- # person = Person.create(name: "Alisson")
17
+ # person = Person.create(name: "Allison")
18
18
  # person.changed? # => false
19
19
  #
20
20
  # Change the name:
@@ -76,11 +76,13 @@ module ActiveRecord
76
76
  #
77
77
  # ==== Options
78
78
  #
79
- # +from+ When passed, this method will return false unless the original
80
- # value is equal to the given option
79
+ # [+from+]
80
+ # When specified, this method will return false unless the original
81
+ # value is equal to the given value.
81
82
  #
82
- # +to+ When passed, this method will return false unless the value was
83
- # changed to the given value
83
+ # [+to+]
84
+ # When specified, this method will return false unless the value will be
85
+ # changed to the given value.
84
86
  def saved_change_to_attribute?(attr_name, **options)
85
87
  mutations_before_last_save.changed?(attr_name.to_s, **options)
86
88
  end
@@ -126,11 +128,13 @@ module ActiveRecord
126
128
  #
127
129
  # ==== Options
128
130
  #
129
- # +from+ When passed, this method will return false unless the original
130
- # value is equal to the given option
131
+ # [+from+]
132
+ # When specified, this method will return false unless the original
133
+ # value is equal to the given value.
131
134
  #
132
- # +to+ When passed, this method will return false unless the value will be
133
- # changed to the given value
135
+ # [+to+]
136
+ # When specified, this method will return false unless the value will be
137
+ # changed to the given value.
134
138
  def will_save_change_to_attribute?(attr_name, **options)
135
139
  mutations_from_database.changed?(attr_name.to_s, **options)
136
140
  end
@@ -34,7 +34,7 @@ module ActiveRecord
34
34
  Base.private_instance_methods -
35
35
  Base.superclass.instance_methods -
36
36
  Base.superclass.private_instance_methods +
37
- %i[__id__ dup freeze frozen? hash object_id class clone]
37
+ %i[__id__ dup freeze frozen? hash class clone]
38
38
  ).map { |m| -m.to_s }.to_set.freeze
39
39
  end
40
40
  end
@@ -241,8 +241,8 @@ module ActiveRecord
241
241
  #
242
242
  # config.active_record.run_after_transaction_callbacks_in_order_defined = false
243
243
  #
244
- # If +true+ (the default from \Rails 7.1), callbacks are executed in the order they
245
- # are defined, just like the example above. If +false+, the order is reversed, so
244
+ # When set to +true+ (the default from \Rails 7.1), callbacks are executed in the order they
245
+ # are defined, just like the example above. When set to +false+, the order is reversed, so
246
246
  # +do_something_else+ is executed before +log_children+.
247
247
  #
248
248
  # == \Transactions
@@ -58,12 +58,10 @@ module ActiveRecord
58
58
  # Connections can be obtained and used from a connection pool in several
59
59
  # ways:
60
60
  #
61
- # 1. Simply use {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling.connection]
62
- # as with Active Record 2.1 and
63
- # earlier (pre-connection-pooling). Eventually, when you're done with
64
- # the connection(s) and wish it to be returned to the pool, you call
61
+ # 1. Simply use {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling.connection].
62
+ # When you're done with the connection(s) and wish it to be returned to the pool, you call
65
63
  # {ActiveRecord::Base.connection_handler.clear_active_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_active_connections!].
66
- # This will be the default behavior for Active Record when used in conjunction with
64
+ # This is the default behavior for Active Record when used in conjunction with
67
65
  # Action Pack's request handling cycle.
68
66
  # 2. Manually check out a connection from the pool with
69
67
  # {ActiveRecord::Base.connection_pool.checkout}[rdoc-ref:#checkout]. You are responsible for
@@ -465,8 +463,7 @@ module ActiveRecord
465
463
  @available.num_waiting
466
464
  end
467
465
 
468
- # Return connection pool's usage statistic
469
- # Example:
466
+ # Returns the connection pool's usage statistic.
470
467
  #
471
468
  # ActiveRecord::Base.connection_pool.stat # => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }
472
469
  def stat
@@ -658,7 +655,13 @@ module ActiveRecord
658
655
  conn
659
656
  else
660
657
  reap
661
- @available.poll(checkout_timeout)
658
+ # Retry after reaping, which may return an available connection,
659
+ # remove an inactive connection, or both
660
+ if conn = @available.poll || try_to_checkout_new_connection
661
+ conn
662
+ else
663
+ @available.poll(checkout_timeout)
664
+ end
662
665
  end
663
666
  end
664
667
 
@@ -189,8 +189,10 @@ module ActiveRecord
189
189
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
190
190
  sql, binds = to_sql_and_binds(arel, binds)
191
191
  value = exec_insert(sql, name, binds, pk, sequence_name, returning: returning)
192
- return id_value if id_value
193
- returning.nil? ? last_inserted_id(value) : returning_column_values(value)
192
+
193
+ return returning_column_values(value) unless returning.nil?
194
+
195
+ id_value || last_inserted_id(value)
194
196
  end
195
197
  alias create insert
196
198
 
@@ -106,7 +106,8 @@ module ActiveRecord
106
106
  sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
107
107
 
108
108
  if async
109
- lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
109
+ result = lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
110
+ FutureResult::Complete.new(result)
110
111
  else
111
112
  cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
112
113
  end
@@ -970,7 +970,11 @@ module ActiveRecord
970
970
  # If +allow_retry+ is true, a connection-related exception will
971
971
  # cause an automatic reconnect and re-run of the block, up to
972
972
  # the connection's configured +connection_retries+ setting
973
- # and the configured +retry_deadline+ limit.
973
+ # and the configured +retry_deadline+ limit. (Note that when
974
+ # +allow_retry+ is true, it's possible to return without having marked
975
+ # the connection as verified. If the block is guaranteed to exercise the
976
+ # connection, consider calling `verified!` to avoid needless
977
+ # verification queries in subsequent calls.)
974
978
  #
975
979
  # If +materialize_transactions+ is false, the block will be run without
976
980
  # ensuring virtual transactions have been materialized in the DB
@@ -1021,9 +1025,7 @@ module ActiveRecord
1021
1025
  end
1022
1026
 
1023
1027
  begin
1024
- result = yield @raw_connection
1025
- @verified = true
1026
- result
1028
+ yield @raw_connection
1027
1029
  rescue => original_exception
1028
1030
  translated_exception = translate_exception_class(original_exception, nil, nil)
1029
1031
  invalidate_transaction(translated_exception)
@@ -1058,6 +1060,13 @@ module ActiveRecord
1058
1060
  end
1059
1061
  end
1060
1062
 
1063
+ # Mark the connection as verified. Call this inside a
1064
+ # `with_raw_connection` block only when the block is guaranteed to
1065
+ # exercise the raw connection.
1066
+ def verified!
1067
+ @verified = true
1068
+ end
1069
+
1061
1070
  def retryable_connection_error?(exception)
1062
1071
  exception.is_a?(ConnectionNotEstablished) || exception.is_a?(ConnectionFailed)
1063
1072
  end
@@ -98,6 +98,7 @@ module ActiveRecord
98
98
  with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
99
99
  sync_timezone_changes(conn)
100
100
  result = conn.query(sql)
101
+ verified!
101
102
  handle_warnings(sql)
102
103
  result
103
104
  end
@@ -126,6 +127,8 @@ module ActiveRecord
126
127
  result = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
127
128
  stmt.execute(*type_casted_binds)
128
129
  end
130
+ verified!
131
+ result
129
132
  rescue ::Mysql2::Error => e
130
133
  if cache_stmt
131
134
  @statements.delete(sql)
@@ -16,7 +16,9 @@ module ActiveRecord
16
16
 
17
17
  log(sql, name) do
18
18
  with_raw_connection do |conn|
19
- conn.async_exec(sql).map_types!(@type_map_for_results).values
19
+ result = conn.async_exec(sql).map_types!(@type_map_for_results).values
20
+ verified!
21
+ result
20
22
  end
21
23
  end
22
24
  end
@@ -51,6 +53,7 @@ module ActiveRecord
51
53
  log(sql, name, async: async) do
52
54
  with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
53
55
  result = conn.async_exec(sql)
56
+ verified!
54
57
  handle_warnings(result)
55
58
  result
56
59
  end
@@ -27,9 +27,10 @@ module ActiveRecord
27
27
  value = value.sub(/^\((.+)\)$/, '-\1') # (4)
28
28
  case value
29
29
  when /^-?\D*+[\d,]+\.\d{2}$/ # (1)
30
- value.gsub!(/[^-\d.]/, "")
30
+ value.delete!("^-0-9.")
31
31
  when /^-?\D*+[\d.]+,\d{2}$/ # (2)
32
- value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
32
+ value.delete!("^-0-9,")
33
+ value.tr!(",", ".")
33
34
  end
34
35
 
35
36
  super(value)
@@ -341,7 +341,7 @@ module ActiveRecord
341
341
  JOIN pg_namespace nsp ON (t.relnamespace = nsp.oid)
342
342
  WHERE t.oid = #{quote(quote_table_name(table))}::regclass
343
343
  AND cons.contype = 'p'
344
- AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
344
+ AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate|gen_random_uuid'
345
345
  SQL
346
346
  end
347
347
 
@@ -385,11 +385,18 @@ module ActiveRecord
385
385
  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
386
386
  pk, seq = pk_and_sequence_for(new_name)
387
387
  if pk
388
- idx = "#{table_name}_pkey"
389
- new_idx = "#{new_name}_pkey"
388
+ # PostgreSQL automatically creates an index for PRIMARY KEY with name consisting of
389
+ # truncated table name and "_pkey" suffix fitting into max_identifier_length number of characters.
390
+ max_pkey_prefix = max_identifier_length - "_pkey".size
391
+ idx = "#{table_name[0, max_pkey_prefix]}_pkey"
392
+ new_idx = "#{new_name[0, max_pkey_prefix]}_pkey"
390
393
  execute "ALTER INDEX #{quote_table_name(idx)} RENAME TO #{quote_table_name(new_idx)}"
391
- if seq && seq.identifier == "#{table_name}_#{pk}_seq"
392
- new_seq = "#{new_name}_#{pk}_seq"
394
+
395
+ # PostgreSQL automatically creates a sequence for PRIMARY KEY with name consisting of
396
+ # truncated table name and "#{primary_key}_seq" suffix fitting into max_identifier_length number of characters.
397
+ max_seq_prefix = max_identifier_length - "_#{pk}_seq".size
398
+ if seq && seq.identifier == "#{table_name[0, max_seq_prefix]}_#{pk}_seq"
399
+ new_seq = "#{new_name[0, max_seq_prefix]}_#{pk}_seq"
393
400
  execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
394
401
  end
395
402
  end