activerecord 8.0.0.beta1 → 8.0.0.rc2

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 +102 -2
  3. data/lib/active_record/association_relation.rb +1 -0
  4. data/lib/active_record/associations/association.rb +9 -5
  5. data/lib/active_record/associations/has_many_through_association.rb +7 -1
  6. data/lib/active_record/associations.rb +28 -16
  7. data/lib/active_record/attribute_methods/primary_key.rb +2 -7
  8. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
  9. data/lib/active_record/callbacks.rb +1 -1
  10. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +26 -8
  11. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
  12. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -1
  13. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -2
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -1
  15. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -4
  16. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  17. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  18. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -10
  19. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
  20. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
  21. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +11 -10
  22. data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -10
  23. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +1 -1
  24. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +0 -2
  25. data/lib/active_record/connection_adapters.rb +0 -56
  26. data/lib/active_record/core.rb +43 -14
  27. data/lib/active_record/database_configurations/database_config.rb +4 -0
  28. data/lib/active_record/database_configurations/hash_config.rb +8 -0
  29. data/lib/active_record/enum.rb +9 -22
  30. data/lib/active_record/fixtures.rb +0 -1
  31. data/lib/active_record/gem_version.rb +1 -1
  32. data/lib/active_record/locking/optimistic.rb +1 -1
  33. data/lib/active_record/log_subscriber.rb +5 -11
  34. data/lib/active_record/marshalling.rb +4 -1
  35. data/lib/active_record/migration/command_recorder.rb +5 -5
  36. data/lib/active_record/migration.rb +0 -5
  37. data/lib/active_record/model_schema.rb +2 -3
  38. data/lib/active_record/query_cache.rb +0 -4
  39. data/lib/active_record/query_logs.rb +5 -11
  40. data/lib/active_record/querying.rb +2 -2
  41. data/lib/active_record/railtie.rb +2 -25
  42. data/lib/active_record/railties/databases.rake +2 -17
  43. data/lib/active_record/reflection.rb +14 -19
  44. data/lib/active_record/relation/calculations.rb +24 -28
  45. data/lib/active_record/relation/predicate_builder.rb +8 -0
  46. data/lib/active_record/relation/query_methods.rb +76 -38
  47. data/lib/active_record/relation.rb +8 -1
  48. data/lib/active_record/result.rb +10 -9
  49. data/lib/active_record/table_metadata.rb +1 -3
  50. data/lib/active_record/tasks/database_tasks.rb +26 -34
  51. data/lib/active_record/testing/query_assertions.rb +2 -2
  52. data/lib/active_record.rb +0 -45
  53. data/lib/arel/table.rb +3 -7
  54. data/lib/arel/visitors/sqlite.rb +25 -0
  55. metadata +9 -10
  56. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e4bbfe90a91599557f1804b34ccb34ca5db162d8ffb8c61a7bf87c3db518b16
4
- data.tar.gz: a84a3f17fe43e75642b2d293df3916062ef9fcc77cc6485f4b8e9183bb90f234
3
+ metadata.gz: 5b6b5ce7951d63889da24f22f9635d27371d6fc733e400d1510cd0ffe27f669e
4
+ data.tar.gz: 68f851f76e82b3969bc3a7125b3700ce3623ed7cf1717064f26202b4a5c062cd
5
5
  SHA512:
6
- metadata.gz: 8e0c9d489c0baade86104d8f1f2be0595c1eb3b2a9f1f02328cc3de9d941c8d46302daf74547b2a2c508bd03f418312b0557e1274b14ada1d6bb2f2ae3fc17d5
7
- data.tar.gz: '04599d4f24baede9df806c5b0abc1627bb468f365581acd71ee30ef058faeadd3de22074f4752727633df01b8578258cffdab7e709a7e849e332af2de08b3f2d'
6
+ metadata.gz: ef1e91d706ec3c79e71b2e59780a831a63fe82ab45a8e123748c5d073bc120c3d9506d3e8b43b68aa77dc90a5f564b8ef45cb1d5abc19e008127757966bf32dc
7
+ data.tar.gz: 35e7644e3037334b724042c5f26539c2489c579fede36d461e3661cf04ca79b5c8ca0b3e3c29d8edfc9eab3de15af0b8dcee33a7d88f2f4985c46acfce26a324
data/CHANGELOG.md CHANGED
@@ -1,3 +1,103 @@
1
+ ## Rails 8.0.0.rc2 (October 30, 2024) ##
2
+
3
+ * NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
4
+
5
+ *Ryuta Kamizono*
6
+
7
+ * The `db:prepare` task no longer loads seeds when a non-primary database is created.
8
+
9
+ Previously, the `db:prepare` task would load seeds whenever a new database
10
+ is created, leading to potential loss of data if a database is added to an
11
+ existing environment.
12
+
13
+ Introduces a new database config property `seeds` to control whether seeds
14
+ are loaded during `db:prepare` which defaults to `true` for primary database
15
+ configs and `false` otherwise.
16
+
17
+ Fixes #53348.
18
+
19
+ *Mike Dalessio*
20
+
21
+ * `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
22
+
23
+ *Kazuma Watanabe*
24
+
25
+ * Fix strict loading propagation even if statement cache is not used.
26
+
27
+ *Ryuta Kamizono*
28
+
29
+ * Allow `rename_enum` accepts two from/to name arguments as `rename_table` does so.
30
+
31
+ *Ryuta Kamizono*
32
+
33
+
34
+ ## Rails 8.0.0.rc1 (October 19, 2024) ##
35
+
36
+ * Remove deprecated support to setting `ENV["SCHEMA_CACHE"]`.
37
+
38
+ *Rafael Mendonça França*
39
+
40
+ * Remove deprecated support to passing a database name to `cache_dump_filename`.
41
+
42
+ *Rafael Mendonça França*
43
+
44
+ * Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
45
+
46
+ *Rafael Mendonça França*
47
+
48
+ * Remove deprecated `config.active_record.sqlite3_deprecated_warning`.
49
+
50
+ *Rafael Mendonça França*
51
+
52
+ * Remove deprecated `config.active_record.warn_on_records_fetched_greater_than`.
53
+
54
+ *Rafael Mendonça França*
55
+
56
+ * Remove deprecated support for defining `enum` with keyword arguments.
57
+
58
+ *Rafael Mendonça França*
59
+
60
+ * Remove deprecated support to finding database adapters that aren't registered to Active Record.
61
+
62
+ *Rafael Mendonça França*
63
+
64
+ * Remove deprecated `config.active_record.allow_deprecated_singular_associations_name`.
65
+
66
+ *Rafael Mendonça França*
67
+
68
+ * Remove deprecated `config.active_record.commit_transaction_on_non_local_return`.
69
+
70
+ *Rafael Mendonça França*
71
+
72
+ * Fix incorrect SQL query when passing an empty hash to `ActiveRecord::Base.insert`.
73
+
74
+ *David Stosik*
75
+
76
+ * Allow to save records with polymorphic join tables that have `inverse_of`
77
+ specified.
78
+
79
+ *Markus Doits*
80
+
81
+ * Fix association scopes applying on the incorrect join when using a polymorphic `has_many through:`.
82
+
83
+ *Joshua Young*
84
+
85
+ * Allow `ActiveRecord::Base#pluck` to accept hash arguments with symbol and string values.
86
+
87
+ ```ruby
88
+ Post.joins(:comments).pluck(:id, comments: :id)
89
+ Post.joins(:comments).pluck("id", "comments" => "id")
90
+ ```
91
+
92
+ *Joshua Young*
93
+
94
+ * Make Float distinguish between `float4` and `float8` in PostgreSQL.
95
+
96
+ Fixes #52742
97
+
98
+ *Ryota Kitazawa*, *Takayuki Nagatomi*
99
+
100
+
1
101
  ## Rails 8.0.0.beta1 (September 26, 2024) ##
2
102
 
3
103
  * Allow `drop_table` to accept an array of table names.
@@ -15,9 +115,9 @@
15
115
 
16
116
  *Ariel Rzezak*
17
117
 
18
- * When running `db:migrate` on a fresh database, load the database schema before running migrations.
118
+ * When running `db:migrate` on a fresh database, load the databases schemas before running migrations.
19
119
 
20
- *Andrew Novoselac*
120
+ *Andrew Novoselac*, *Marek Kasztelnik*
21
121
 
22
122
  * Fix an issue where `.left_outer_joins` used with multiple associations that have
23
123
  the same child association but different parents does not join all parents.
@@ -43,6 +43,7 @@ module ActiveRecord
43
43
  def exec_queries
44
44
  super do |record|
45
45
  @association.set_inverse_instance_from_queries(record)
46
+ @association.set_strict_loading(record)
46
47
  yield record if block_given?
47
48
  end
48
49
  end
@@ -120,6 +120,14 @@ module ActiveRecord
120
120
  @association_scope = nil
121
121
  end
122
122
 
123
+ def set_strict_loading(record)
124
+ if owner.strict_loading_n_plus_one_only? && reflection.macro == :has_many
125
+ record.strict_loading!
126
+ else
127
+ record.strict_loading!(false, mode: owner.strict_loading_mode)
128
+ end
129
+ end
130
+
123
131
  # Set the inverse association, if possible
124
132
  def set_inverse_instance(record)
125
133
  if inverse = inverse_association_for(record)
@@ -260,11 +268,7 @@ module ActiveRecord
260
268
  klass.with_connection do |c|
261
269
  sc.execute(binds, c, async: async) do |record|
262
270
  set_inverse_instance(record)
263
- if owner.strict_loading_n_plus_one_only? && reflection.macro == :has_many
264
- record.strict_loading!
265
- else
266
- record.strict_loading!(false, mode: owner.strict_loading_mode)
267
- end
271
+ set_strict_loading(record)
268
272
  end
269
273
  end
270
274
  end
@@ -93,7 +93,13 @@ module ActiveRecord
93
93
  @through_scope = scope
94
94
  record = super
95
95
 
96
- inverse = source_reflection.inverse_of
96
+ inverse =
97
+ if source_reflection.polymorphic?
98
+ source_reflection.polymorphic_inverse_of(record.class)
99
+ else
100
+ source_reflection.inverse_of
101
+ end
102
+
97
103
  if inverse
98
104
  if inverse.collection?
99
105
  record.send(inverse.name) << build_through_record(record)
@@ -559,7 +559,7 @@ module ActiveRecord
559
559
  # @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
560
560
  # @group.avatars.delete(@group.avatars.last) # so would this
561
561
  #
562
- # == Setting Inverses
562
+ # === Setting Inverses
563
563
  #
564
564
  # If you are using a #belongs_to on the join model, it is a good idea to set the
565
565
  # <tt>:inverse_of</tt> option on the #belongs_to, which will mean that the following example
@@ -1221,8 +1221,11 @@ module ActiveRecord
1221
1221
  # If you are going to modify the association (rather than just read from it), then it is
1222
1222
  # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1223
1223
  # join model. This allows associated records to be built which will automatically create
1224
- # the appropriate join model records when they are saved. (See the 'Association Join Models'
1225
- # and 'Setting Inverses' sections above.)
1224
+ # the appropriate join model records when they are saved. See
1225
+ # {Association Join Models}[rdoc-ref:Associations::ClassMethods@Association+Join+Models]
1226
+ # and {Setting Inverses}[rdoc-ref:Associations::ClassMethods@Setting+Inverses] for
1227
+ # more detail.
1228
+ #
1226
1229
  # [+:disable_joins+]
1227
1230
  # Specifies whether joins should be skipped for an association. If set to true, two or more queries
1228
1231
  # will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
@@ -1251,7 +1254,8 @@ module ActiveRecord
1251
1254
  # [+:inverse_of+]
1252
1255
  # Specifies the name of the #belongs_to association on the associated object
1253
1256
  # that is the inverse of this #has_many association.
1254
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1257
+ # See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
1258
+ # for more detail.
1255
1259
  # [+:extend+]
1256
1260
  # Specifies a module or array of modules that will be extended into the association object returned.
1257
1261
  # Useful for defining methods on associations, especially when they should be shared between multiple
@@ -1300,10 +1304,12 @@ module ActiveRecord
1300
1304
  Reflection.add_reflection self, name, reflection
1301
1305
  end
1302
1306
 
1303
- # Specifies a one-to-one association with another class. This method should only be used
1304
- # if the other class contains the foreign key. If the current class contains the foreign key,
1305
- # then you should use #belongs_to instead. See also ActiveRecord::Associations::ClassMethods's overview
1306
- # on when to use #has_one and when to use #belongs_to.
1307
+ # Specifies a one-to-one association with another class. This method
1308
+ # should only be used if the other class contains the foreign key. If
1309
+ # the current class contains the foreign key, then you should use
1310
+ # #belongs_to instead. See {Is it a belongs_to or has_one
1311
+ # association?}[rdoc-ref:Associations::ClassMethods@Is+it+a+-23belongs_to+or+-23has_one+association-3F]
1312
+ # for more detail on when to use #has_one and when to use #belongs_to.
1307
1313
  #
1308
1314
  # The following methods for retrieval and query of a single associated object will be added:
1309
1315
  #
@@ -1418,8 +1424,10 @@ module ActiveRecord
1418
1424
  # If you are going to modify the association (rather than just read from it), then it is
1419
1425
  # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1420
1426
  # join model. This allows associated records to be built which will automatically create
1421
- # the appropriate join model records when they are saved. (See the 'Association Join Models'
1422
- # and 'Setting Inverses' sections above.)
1427
+ # the appropriate join model records when they are saved. See
1428
+ # {Association Join Models}[rdoc-ref:Associations::ClassMethods@Association+Join+Models]
1429
+ # and {Setting Inverses}[rdoc-ref:Associations::ClassMethods@Setting+Inverses] for
1430
+ # more detail.
1423
1431
  # [+:disable_joins+]
1424
1432
  # Specifies whether joins should be skipped for an association. If set to true, two or more queries
1425
1433
  # will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
@@ -1457,7 +1465,8 @@ module ActiveRecord
1457
1465
  # [+:inverse_of+]
1458
1466
  # Specifies the name of the #belongs_to association on the associated object
1459
1467
  # that is the inverse of this #has_one association.
1460
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1468
+ # See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
1469
+ # for more detail.
1461
1470
  # [+:required+]
1462
1471
  # When set to +true+, the association will also have its presence validated.
1463
1472
  # This will validate the association itself, not the id. You can use
@@ -1491,10 +1500,12 @@ module ActiveRecord
1491
1500
  Reflection.add_reflection self, name, reflection
1492
1501
  end
1493
1502
 
1494
- # Specifies a one-to-one association with another class. This method should only be used
1495
- # if this class contains the foreign key. If the other class contains the foreign key,
1496
- # then you should use #has_one instead. See also ActiveRecord::Associations::ClassMethods's overview
1497
- # on when to use #has_one and when to use #belongs_to.
1503
+ # Specifies a one-to-one association with another class. This method
1504
+ # should only be used if this class contains the foreign key. If the
1505
+ # other class contains the foreign key, then you should use #has_one
1506
+ # instead. See {Is it a belongs_to or has_one
1507
+ # association?}[rdoc-ref:Associations::ClassMethods@Is+it+a+-23belongs_to+or+-23has_one+association-3F]
1508
+ # for more detail on when to use #has_one and when to use #belongs_to.
1498
1509
  #
1499
1510
  # Methods will be added for retrieval and query for a single associated object, for which
1500
1511
  # this object holds an id:
@@ -1636,7 +1647,8 @@ module ActiveRecord
1636
1647
  # [+:inverse_of+]
1637
1648
  # Specifies the name of the #has_one or #has_many association on the associated
1638
1649
  # object that is the inverse of this #belongs_to association.
1639
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1650
+ # See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
1651
+ # for more detail.
1640
1652
  # [+:optional+]
1641
1653
  # When set to +true+, the association will not have its presence validated.
1642
1654
  # [+:required+]
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
-
5
3
  module ActiveRecord
6
4
  module AttributeMethods
7
5
  # = Active Record Attribute Methods Primary Key
@@ -89,10 +87,9 @@ module ActiveRecord
89
87
  @composite_primary_key
90
88
  end
91
89
 
92
- # Returns a quoted version of the primary key name, used to construct
93
- # SQL statements.
90
+ # Returns a quoted version of the primary key name.
94
91
  def quoted_primary_key
95
- @quoted_primary_key ||= adapter_class.quote_column_name(primary_key)
92
+ adapter_class.quote_column_name(primary_key)
96
93
  end
97
94
 
98
95
  def reset_primary_key # :nodoc:
@@ -138,7 +135,6 @@ module ActiveRecord
138
135
  elsif value
139
136
  -value.to_s
140
137
  end
141
- @quoted_primary_key = nil
142
138
  @attributes_builder = nil
143
139
  end
144
140
 
@@ -148,7 +144,6 @@ module ActiveRecord
148
144
  base.class_eval do
149
145
  @primary_key = PRIMARY_KEY_NOT_SET
150
146
  @composite_primary_key = false
151
- @quoted_primary_key = nil
152
147
  @attributes_builder = nil
153
148
  end
154
149
  end
@@ -28,7 +28,7 @@ module ActiveRecord
28
28
  elsif value.respond_to?(:infinite?) && value.infinite?
29
29
  value
30
30
  else
31
- map_avoiding_infinite_recursion(super) { |v| cast(v) }
31
+ map(super) { |v| cast(v) }
32
32
  end
33
33
  end
34
34
 
@@ -45,23 +45,13 @@ module ActiveRecord
45
45
  elsif value.respond_to?(:infinite?) && value.infinite?
46
46
  value
47
47
  else
48
- map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
48
+ map(value) { |v| convert_time_to_time_zone(v) }
49
49
  end
50
50
  end
51
51
 
52
52
  def set_time_zone_without_conversion(value)
53
53
  ::Time.zone.local_to_utc(value).try(:in_time_zone) if value
54
54
  end
55
-
56
- def map_avoiding_infinite_recursion(value)
57
- map(value) do |v|
58
- if value.equal?(v)
59
- nil
60
- else
61
- yield(v)
62
- end
63
- end
64
- end
65
55
  end
66
56
 
67
57
  extend ActiveSupport::Concern
@@ -418,7 +418,7 @@ module ActiveRecord
418
418
 
419
419
  def destroy # :nodoc:
420
420
  @_destroy_callback_already_called ||= false
421
- return if @_destroy_callback_already_called
421
+ return true if @_destroy_callback_already_called
422
422
  @_destroy_callback_already_called = true
423
423
  _run_destroy_callbacks { super }
424
424
  rescue RecordNotDestroyed => e
@@ -183,6 +183,31 @@ module ActiveRecord
183
183
  end
184
184
  end
185
185
 
186
+ module ExecutorHooks # :nodoc:
187
+ class << self
188
+ def run
189
+ # noop
190
+ end
191
+
192
+ def complete(_)
193
+ ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
194
+ if (connection = pool.active_connection?)
195
+ transaction = connection.current_transaction
196
+ if transaction.closed? || !transaction.joinable?
197
+ pool.release_connection
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ class << self
206
+ def install_executor_hooks(executor = ActiveSupport::Executor)
207
+ executor.register_hook(ExecutorHooks)
208
+ end
209
+ end
210
+
186
211
  include MonitorMixin
187
212
  prepend QueryCache::ConnectionPoolConfiguration
188
213
  include ConnectionAdapters::AbstractPool
@@ -291,14 +316,6 @@ module ActiveRecord
291
316
  connection_lease.sticky.nil?
292
317
  end
293
318
 
294
- def connection
295
- ActiveRecord.deprecator.warn(<<~MSG)
296
- ActiveRecord::ConnectionAdapters::ConnectionPool#connection is deprecated
297
- and will be removed in Rails 8.0. Use #lease_connection instead.
298
- MSG
299
- lease_connection
300
- end
301
-
302
319
  def pin_connection!(lock_thread) # :nodoc:
303
320
  @pinned_connection ||= (connection_lease&.connection || checkout)
304
321
  @pinned_connections_depth += 1
@@ -332,6 +349,7 @@ module ActiveRecord
332
349
  end
333
350
 
334
351
  if @pinned_connection.nil?
352
+ connection.steal!
335
353
  connection.lock_thread = nil
336
354
  checkin(connection)
337
355
  end
@@ -28,6 +28,7 @@ module ActiveRecord
28
28
  sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
29
29
  sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
30
30
  sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
31
+ sql << o.constraint_drops.map { |con| visit_DropConstraint con }.join(" ")
31
32
  end
32
33
 
33
34
  def visit_ColumnDefinition(o)
@@ -96,9 +97,11 @@ module ActiveRecord
96
97
  "ADD #{accept(o)}"
97
98
  end
98
99
 
99
- def visit_DropForeignKey(name)
100
+ def visit_DropConstraint(name)
100
101
  "DROP CONSTRAINT #{quote_column_name(name)}"
101
102
  end
103
+ alias :visit_DropForeignKey :visit_DropConstraint
104
+ alias :visit_DropCheckConstraint :visit_DropConstraint
102
105
 
103
106
  def visit_CreateIndexDefinition(o)
104
107
  index = o.index
@@ -127,10 +130,6 @@ module ActiveRecord
127
130
  "ADD #{accept(o)}"
128
131
  end
129
132
 
130
- def visit_DropCheckConstraint(name)
131
- "DROP CONSTRAINT #{quote_column_name(name)}"
132
- end
133
-
134
133
  def quoted_columns(o)
135
134
  String === o.columns ? o.columns : quoted_columns_for_index(o.columns, o.column_options)
136
135
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module ActiveRecord
5
4
  module ConnectionAdapters # :nodoc:
6
5
  # Abstract representation of an index definition on a table. Instances of
@@ -622,6 +621,7 @@ module ActiveRecord
622
621
  attr_reader :adds
623
622
  attr_reader :foreign_key_adds, :foreign_key_drops
624
623
  attr_reader :check_constraint_adds, :check_constraint_drops
624
+ attr_reader :constraint_drops
625
625
 
626
626
  def initialize(td)
627
627
  @td = td
@@ -630,6 +630,7 @@ module ActiveRecord
630
630
  @foreign_key_drops = []
631
631
  @check_constraint_adds = []
632
632
  @check_constraint_drops = []
633
+ @constraint_drops = []
633
634
  end
634
635
 
635
636
  def name; @td.name; end
@@ -650,6 +651,10 @@ module ActiveRecord
650
651
  @check_constraint_drops << constraint_name
651
652
  end
652
653
 
654
+ def drop_constraint(constraint_name)
655
+ @constraint_drops << constraint_name
656
+ end
657
+
653
658
  def add_column(name, type, **options)
654
659
  name = name.to_s
655
660
  type = type.to_sym
@@ -693,7 +693,7 @@ module ActiveRecord
693
693
  #
694
694
  # If the options provided include an +if_exists+ key, it will be used to check if the
695
695
  # column does not exist. This will silently ignore the migration rather than raising
696
- # if the column was already used.
696
+ # if the column was already removed.
697
697
  #
698
698
  # remove_column(:suppliers, :qualification, if_exists: true)
699
699
  def remove_column(table_name, column_name, type = nil, **options)
@@ -1334,7 +1334,6 @@ module ActiveRecord
1334
1334
  execute schema_creation.accept(at)
1335
1335
  end
1336
1336
 
1337
-
1338
1337
  # Checks to see if a check constraint exists on a table for a given check constraint definition.
1339
1338
  #
1340
1339
  # check_constraint_exists?(:products, name: "price_check")
@@ -1346,6 +1345,13 @@ module ActiveRecord
1346
1345
  check_constraint_for(table_name, **options).present?
1347
1346
  end
1348
1347
 
1348
+ def remove_constraint(table_name, constraint_name) # :nodoc:
1349
+ at = create_alter_table(table_name)
1350
+ at.drop_constraint(constraint_name)
1351
+
1352
+ execute schema_creation.accept(at)
1353
+ end
1354
+
1349
1355
  def dump_schema_information # :nodoc:
1350
1356
  versions = pool.schema_migration.versions
1351
1357
  insert_versions_sql(versions) if versions.any?
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
3
  require "active_record/connection_adapters/sql_type_metadata"
5
4
  require "active_record/connection_adapters/abstract/schema_dumper"
6
5
  require "active_record/connection_adapters/abstract/schema_creation"
@@ -98,7 +98,7 @@ module ActiveRecord
98
98
  end
99
99
 
100
100
  def supports_index_sort_order?
101
- !mariadb? && database_version >= "8.0.1"
101
+ mariadb? ? database_version >= "10.8.1" : database_version >= "8.0.1"
102
102
  end
103
103
 
104
104
  def supports_expression_index?
@@ -628,7 +628,7 @@ module ActiveRecord
628
628
  end
629
629
 
630
630
  def build_insert_sql(insert) # :nodoc:
631
- no_op_column = quote_column_name(insert.keys.first)
631
+ no_op_column = quote_column_name(insert.keys.first) if insert.keys.first
632
632
 
633
633
  # MySQL 8.0.19 replaces `VALUES(<expression>)` clauses with row and column alias names, see https://dev.mysql.com/worklog/task/?id=6312 .
634
634
  # then MySQL 8.0.20 deprecates the `VALUES(<expression>)` see https://dev.mysql.com/worklog/task/?id=13325 .
@@ -637,7 +637,9 @@ module ActiveRecord
637
637
  sql = +"INSERT #{insert.into} #{insert.values_list} AS #{values_alias}"
638
638
 
639
639
  if insert.skip_duplicates?
640
- sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{values_alias}.#{no_op_column}"
640
+ if no_op_column
641
+ sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{values_alias}.#{no_op_column}"
642
+ end
641
643
  elsif insert.update_duplicates?
642
644
  if insert.raw_update_sql?
643
645
  sql = +"INSERT #{insert.into} #{insert.values_list} ON DUPLICATE KEY UPDATE #{insert.raw_update_sql}"
@@ -651,7 +653,9 @@ module ActiveRecord
651
653
  sql = +"INSERT #{insert.into} #{insert.values_list}"
652
654
 
653
655
  if insert.skip_duplicates?
654
- sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{no_op_column}"
656
+ if no_op_column
657
+ sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{no_op_column}"
658
+ end
655
659
  elsif insert.update_duplicates?
656
660
  sql << " ON DUPLICATE KEY UPDATE "
657
661
  if insert.raw_update_sql?
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  end
66
66
 
67
67
  def map(value, &block)
68
- value.map { |v| subtype.map(v, &block) }
68
+ value.is_a?(::Array) ? value.map(&block) : subtype.map(value, &block)
69
69
  end
70
70
 
71
71
  def changed_in_place?(raw_old_value, new_value)
@@ -45,12 +45,10 @@ Rails needs superuser privileges to disable referential integrity.
45
45
  BEGIN
46
46
  FOR r IN (
47
47
  SELECT FORMAT(
48
- 'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I'' AND connamespace::regnamespace = ''%I''::regnamespace; ALTER TABLE %I.%I VALIDATE CONSTRAINT %I;',
48
+ 'UPDATE pg_catalog.pg_constraint SET convalidated=false WHERE conname = ''%1$I'' AND connamespace::regnamespace = ''%2$I''::regnamespace; ALTER TABLE %2$I.%3$I VALIDATE CONSTRAINT %1$I;',
49
49
  constraint_name,
50
50
  table_schema,
51
- table_schema,
52
- table_name,
53
- constraint_name
51
+ table_name
54
52
  ) AS constraint_check
55
53
  FROM information_schema.table_constraints WHERE constraint_type = 'FOREIGN KEY'
56
54
  )
@@ -11,9 +11,7 @@ module ActiveRecord
11
11
  sql = super
12
12
  sql << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
13
13
  sql << o.exclusion_constraint_adds.map { |con| visit_AddExclusionConstraint con }.join(" ")
14
- sql << o.exclusion_constraint_drops.map { |con| visit_DropExclusionConstraint con }.join(" ")
15
14
  sql << o.unique_constraint_adds.map { |con| visit_AddUniqueConstraint con }.join(" ")
16
- sql << o.unique_constraint_drops.map { |con| visit_DropUniqueConstraint con }.join(" ")
17
15
  end
18
16
 
19
17
  def visit_AddForeignKey(o)
@@ -54,6 +52,7 @@ module ActiveRecord
54
52
  sql = ["CONSTRAINT"]
55
53
  sql << quote_column_name(o.name)
56
54
  sql << "UNIQUE"
55
+ sql << "NULLS NOT DISTINCT" if supports_nulls_not_distinct? && o.nulls_not_distinct
57
56
 
58
57
  if o.using_index
59
58
  sql << "USING INDEX #{quote_column_name(o.using_index)}"
@@ -72,18 +71,10 @@ module ActiveRecord
72
71
  "ADD #{accept(o)}"
73
72
  end
74
73
 
75
- def visit_DropExclusionConstraint(name)
76
- "DROP CONSTRAINT #{quote_column_name(name)}"
77
- end
78
-
79
74
  def visit_AddUniqueConstraint(o)
80
75
  "ADD #{accept(o)}"
81
76
  end
82
77
 
83
- def visit_DropUniqueConstraint(name)
84
- "DROP CONSTRAINT #{quote_column_name(name)}"
85
- end
86
-
87
78
  def visit_ChangeColumnDefinition(o)
88
79
  column = o.column
89
80
  column.sql_type = type_to_sql(column.type, **column.options)