activerecord 7.1.1 → 7.1.3

Sign up to get free protection for your applications and to get access to all the features.
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