activerecord 8.0.0.beta1 → 8.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +102 -2
- data/lib/active_record/association_relation.rb +1 -0
- data/lib/active_record/associations/association.rb +9 -5
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations.rb +28 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +6 -12
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +11 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +12 -10
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +0 -2
- data/lib/active_record/connection_adapters.rb +0 -56
- data/lib/active_record/core.rb +43 -14
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/database_configurations/hash_config.rb +8 -0
- data/lib/active_record/enum.rb +9 -22
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +5 -11
- data/lib/active_record/marshalling.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +5 -5
- data/lib/active_record/migration.rb +0 -5
- data/lib/active_record/model_schema.rb +2 -3
- data/lib/active_record/query_cache.rb +0 -4
- data/lib/active_record/query_logs.rb +5 -11
- data/lib/active_record/querying.rb +2 -2
- data/lib/active_record/railtie.rb +2 -25
- data/lib/active_record/railties/databases.rake +2 -17
- data/lib/active_record/reflection.rb +14 -19
- data/lib/active_record/relation/calculations.rb +24 -28
- data/lib/active_record/relation/predicate_builder.rb +8 -0
- data/lib/active_record/relation/query_methods.rb +76 -38
- data/lib/active_record/relation.rb +8 -1
- data/lib/active_record/result.rb +10 -9
- data/lib/active_record/table_metadata.rb +1 -3
- data/lib/active_record/tasks/database_tasks.rb +26 -34
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record.rb +0 -45
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/sqlite.rb +25 -0
- metadata +9 -10
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b6b5ce7951d63889da24f22f9635d27371d6fc733e400d1510cd0ffe27f669e
|
4
|
+
data.tar.gz: 68f851f76e82b3969bc3a7125b3700ce3623ed7cf1717064f26202b4a5c062cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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.
|
@@ -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
|
-
|
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 =
|
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
|
-
#
|
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.
|
1225
|
-
#
|
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
|
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
|
1304
|
-
# if the other class contains the foreign key. If
|
1305
|
-
#
|
1306
|
-
#
|
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.
|
1422
|
-
#
|
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
|
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
|
1495
|
-
# if this class contains the foreign key. If the
|
1496
|
-
# then you should use #has_one
|
1497
|
-
#
|
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
|
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
|
93
|
-
# SQL statements.
|
90
|
+
# Returns a quoted version of the primary key name.
|
94
91
|
def quoted_primary_key
|
95
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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?
|
@@ -98,7 +98,7 @@ module ActiveRecord
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def supports_index_sort_order?
|
101
|
-
|
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
|
-
|
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
|
-
|
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?
|
@@ -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
|
-
|
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)
|