activerecord 7.0.0 → 7.0.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +175 -0
- data/MIT-LICENSE +1 -1
- data/lib/active_record/associations.rb +29 -8
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -4
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +8 -3
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +28 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/encryption/configurable.rb +2 -2
- data/lib/active_record/encryption/extended_deterministic_queries.rb +28 -28
- data/lib/active_record/fixtures.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/integration.rb +2 -2
- data/lib/active_record/migration/compatibility.rb +24 -2
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/railtie.rb +2 -2
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation/calculations.rb +3 -2
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +19 -5
- data/lib/active_record/relation.rb +16 -1
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +15 -16
- data/lib/active_record/tasks/database_tasks.rb +6 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record.rb +1 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c33dacf42d19439217c8ca1869c9760c3aae71ca9b4b2155fa58729c802e4ba
|
4
|
+
data.tar.gz: c4444cddcab6a46fd9c38b9c03f58ce785d44fbb564a3985676bcec8ad99e98c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e8ada99b5f4ab64565ed58f6526aa1ffb40605e0769ccc344f896fc934cd1519841e8fea9e753cfd4d3d7f96490dc7a668c101c0d4ef178bb23e6c8d5e6d884
|
7
|
+
data.tar.gz: 771f2198ae227ffb4f5ae9e47e1d3ccf6201f4b9b40c79a03ea662d46d426f8c7d13855c7017c5f99b5748fafb1c07026fa965e1a87b1f1d2271ff4a3901c40e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,176 @@
|
|
1
|
+
## Rails 7.0.2.2 (February 11, 2022) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 7.0.2.1 (February 11, 2022) ##
|
7
|
+
|
8
|
+
* No changes.
|
9
|
+
|
10
|
+
|
11
|
+
## Rails 7.0.2 (February 08, 2022) ##
|
12
|
+
|
13
|
+
* Fix `PG.connect` keyword arguments deprecation warning on ruby 2.7.
|
14
|
+
|
15
|
+
*Nikita Vasilevsky*
|
16
|
+
|
17
|
+
* Fix the ability to exclude encryption params from being autofiltered.
|
18
|
+
|
19
|
+
*Mark Gangl*
|
20
|
+
|
21
|
+
* Dump the precision for datetime columns following the new defaults.
|
22
|
+
|
23
|
+
*Rafael Mendonça França*
|
24
|
+
|
25
|
+
* Make sure encrypted attributes are not being filtered twice.
|
26
|
+
|
27
|
+
*Nikita Vasilevsky*
|
28
|
+
|
29
|
+
* Dump the database schema containing the current Rails version.
|
30
|
+
|
31
|
+
Since https://github.com/rails/rails/pull/42297, Rails now generate datetime columns
|
32
|
+
with a default precision of 6. This means that users upgrading to Rails 7.0 from 6.1,
|
33
|
+
when loading the database schema, would get the new precision value, which would not match
|
34
|
+
the production schema.
|
35
|
+
|
36
|
+
To avoid this the schema dumper will generate the new format which will include the Rails
|
37
|
+
version and will look like this:
|
38
|
+
|
39
|
+
```
|
40
|
+
ActiveRecord::Schema[7.0].define
|
41
|
+
```
|
42
|
+
|
43
|
+
When upgrading from Rails 6.1 to Rails 7.0, you can run the `rails app:update` task that will
|
44
|
+
set the current schema version to 6.1.
|
45
|
+
|
46
|
+
*Rafael Mendonça França*
|
47
|
+
|
48
|
+
* Fix parsing expression for PostgreSQL generated column.
|
49
|
+
|
50
|
+
*fatkodima*
|
51
|
+
|
52
|
+
* Fix `Mysql2::Error: Commands out of sync; you can't run this command now`
|
53
|
+
when bulk-inserting fixtures that exceed `max_allowed_packet` configuration.
|
54
|
+
|
55
|
+
*Nikita Vasilevsky*
|
56
|
+
|
57
|
+
* Fix error when saving an association with a relation named `record`.
|
58
|
+
|
59
|
+
*Dorian Marié*
|
60
|
+
|
61
|
+
* Fix `MySQL::SchemaDumper` behavior about datetime precision value.
|
62
|
+
|
63
|
+
*y0t4*
|
64
|
+
|
65
|
+
* Improve associated with no reflection error.
|
66
|
+
|
67
|
+
*Nikolai*
|
68
|
+
|
69
|
+
* Fix PG.connect keyword arguments deprecation warning on ruby 2.7.
|
70
|
+
|
71
|
+
Fixes #44307.
|
72
|
+
|
73
|
+
*Nikita Vasilevsky*
|
74
|
+
|
75
|
+
* Fix passing options to `check_constraint` from `change_table`.
|
76
|
+
|
77
|
+
*Frederick Cheung*
|
78
|
+
|
79
|
+
|
80
|
+
## Rails 7.0.1 (January 06, 2022) ##
|
81
|
+
|
82
|
+
|
83
|
+
* Change `QueryMethods#in_order_of` to drop records not listed in values.
|
84
|
+
|
85
|
+
`in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
|
86
|
+
|
87
|
+
*Kevin Newton*
|
88
|
+
|
89
|
+
* Allow named expression indexes to be revertible.
|
90
|
+
|
91
|
+
Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
|
95
|
+
```
|
96
|
+
|
97
|
+
Fixes #43331.
|
98
|
+
|
99
|
+
*Oliver Günther*
|
100
|
+
|
101
|
+
* Better error messages when association name is invalid in the argument of `ActiveRecord::QueryMethods::WhereChain#missing`.
|
102
|
+
|
103
|
+
*ykpythemind*
|
104
|
+
|
105
|
+
* Fix ordered migrations for single db in multi db environment.
|
106
|
+
|
107
|
+
*Himanshu*
|
108
|
+
|
109
|
+
* Extract `on update CURRENT_TIMESTAMP` for mysql2 adapter.
|
110
|
+
|
111
|
+
*Kazuhiro Masuda*
|
112
|
+
|
113
|
+
* Fix incorrect argument in PostgreSQL structure dump tasks.
|
114
|
+
|
115
|
+
Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.
|
116
|
+
|
117
|
+
*Alex Dent*
|
118
|
+
|
119
|
+
* Fix schema dumping column default SQL values for sqlite3.
|
120
|
+
|
121
|
+
*fatkodima*
|
122
|
+
|
123
|
+
* Correctly parse complex check constraint expressions for PostgreSQL.
|
124
|
+
|
125
|
+
*fatkodima*
|
126
|
+
|
127
|
+
* Fix `timestamptz` attributes on PostgreSQL handle blank inputs.
|
128
|
+
|
129
|
+
*Alex Ghiculescu*
|
130
|
+
|
131
|
+
* Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
|
132
|
+
|
133
|
+
Reference/belongs_to in migrations with version 6.0 were creating columns as
|
134
|
+
bigint instead of integer for the SQLite Adapter.
|
135
|
+
|
136
|
+
*Marcelo Lauxen*
|
137
|
+
|
138
|
+
* Fix joining through a polymorphic association.
|
139
|
+
|
140
|
+
*Alexandre Ruban*
|
141
|
+
|
142
|
+
* Fix `QueryMethods#in_order_of` to handle empty order list.
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
Post.in_order_of(:id, []).to_a
|
146
|
+
```
|
147
|
+
|
148
|
+
Also more explicitly set the column as secondary order, so that any other
|
149
|
+
value is still ordered.
|
150
|
+
|
151
|
+
*Jean Boussier*
|
152
|
+
|
153
|
+
* Fix `rails dbconsole` for 3-tier config.
|
154
|
+
|
155
|
+
*Eileen M. Uchitelle*
|
156
|
+
|
157
|
+
* Fix quoting of column aliases generated by calculation methods.
|
158
|
+
|
159
|
+
Since the alias is derived from the table name, we can't assume the result
|
160
|
+
is a valid identifier.
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
class Test < ActiveRecord::Base
|
164
|
+
self.table_name = '1abc'
|
165
|
+
end
|
166
|
+
Test.group(:id).count
|
167
|
+
# syntax error at or near "1" (ActiveRecord::StatementInvalid)
|
168
|
+
# LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
|
169
|
+
```
|
170
|
+
|
171
|
+
*Jean Boussier*
|
172
|
+
|
173
|
+
|
1
174
|
## Rails 7.0.0 (December 15, 2021) ##
|
2
175
|
|
3
176
|
* Better handle SQL queries with invalid encoding.
|
@@ -20,6 +193,7 @@
|
|
20
193
|
|
21
194
|
*Eileen M. Uchitelle*
|
22
195
|
|
196
|
+
|
23
197
|
## Rails 7.0.0.rc3 (December 14, 2021) ##
|
24
198
|
|
25
199
|
* No changes.
|
@@ -29,6 +203,7 @@
|
|
29
203
|
|
30
204
|
* No changes.
|
31
205
|
|
206
|
+
|
32
207
|
## Rails 7.0.0.rc1 (December 06, 2021) ##
|
33
208
|
|
34
209
|
* Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
|
data/MIT-LICENSE
CHANGED
@@ -290,6 +290,7 @@ module ActiveRecord
|
|
290
290
|
def self.eager_load!
|
291
291
|
super
|
292
292
|
Preloader.eager_load!
|
293
|
+
JoinDependency.eager_load!
|
293
294
|
end
|
294
295
|
|
295
296
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
@@ -594,19 +595,27 @@ module ActiveRecord
|
|
594
595
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
595
596
|
# object from an association collection.
|
596
597
|
#
|
597
|
-
# class
|
598
|
-
#
|
598
|
+
# class Firm < ActiveRecord::Base
|
599
|
+
# has_many :clients,
|
600
|
+
# dependent: :destroy,
|
601
|
+
# after_add: :congratulate_client,
|
602
|
+
# after_remove: :log_after_remove
|
599
603
|
#
|
600
|
-
# def
|
601
|
-
# ...
|
604
|
+
# def congratulate_client(record)
|
605
|
+
# # ...
|
606
|
+
# end
|
607
|
+
#
|
608
|
+
# def log_after_remove(record)
|
609
|
+
# # ...
|
602
610
|
# end
|
603
|
-
# end
|
604
611
|
#
|
605
612
|
# It's possible to stack callbacks by passing them as an array. Example:
|
606
613
|
#
|
607
|
-
# class
|
608
|
-
#
|
609
|
-
#
|
614
|
+
# class Firm < ActiveRecord::Base
|
615
|
+
# has_many :clients,
|
616
|
+
# dependent: :destroy,
|
617
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
618
|
+
# after_remove: :log_after_remove
|
610
619
|
# end
|
611
620
|
#
|
612
621
|
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
|
@@ -617,6 +626,18 @@ module ActiveRecord
|
|
617
626
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
618
627
|
# will not be removed from the collection.
|
619
628
|
#
|
629
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
630
|
+
#
|
631
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
632
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
633
|
+
# * <tt>firm.clients.destroy_all</tt>
|
634
|
+
#
|
635
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
636
|
+
#
|
637
|
+
# * <tt>firm.clients.delete(client)</tt>
|
638
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
639
|
+
# * <tt>firm.clients.delete_all</tt>
|
640
|
+
#
|
620
641
|
# == Association extensions
|
621
642
|
#
|
622
643
|
# The proxy objects that control the access to associations can be extended through anonymous
|
@@ -413,7 +413,7 @@ module ActiveRecord
|
|
413
413
|
inspected_value = if value.is_a?(String) && value.length > 50
|
414
414
|
"#{value[0, 50]}...".inspect
|
415
415
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
416
|
-
%("#{value.
|
416
|
+
%("#{value.to_fs(:inspect)}")
|
417
417
|
else
|
418
418
|
value.inspect
|
419
419
|
end
|
@@ -446,7 +446,7 @@ module ActiveRecord
|
|
446
446
|
elsif autosave != false
|
447
447
|
key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
|
448
448
|
|
449
|
-
if (autosave && record.changed_for_autosave?) ||
|
449
|
+
if (autosave && record.changed_for_autosave?) || _record_changed?(reflection, record, key)
|
450
450
|
unless reflection.through_reflection
|
451
451
|
record[reflection.foreign_key] = key
|
452
452
|
association.set_inverse_instance(record)
|
@@ -461,7 +461,7 @@ module ActiveRecord
|
|
461
461
|
end
|
462
462
|
|
463
463
|
# If the record is new or it has changed, returns true.
|
464
|
-
def
|
464
|
+
def _record_changed?(reflection, record, key)
|
465
465
|
record.new_record? ||
|
466
466
|
association_foreign_key_changed?(reflection, record, key) ||
|
467
467
|
record.will_save_change_to_attribute?(reflection.foreign_key)
|
@@ -810,8 +810,8 @@ module ActiveRecord
|
|
810
810
|
# t.check_constraint("price > 0", name: "price_check")
|
811
811
|
#
|
812
812
|
# See {connection.add_check_constraint}[rdoc-ref:SchemaStatements#add_check_constraint]
|
813
|
-
def check_constraint(*args)
|
814
|
-
@base.add_check_constraint(name, *args)
|
813
|
+
def check_constraint(*args, **options)
|
814
|
+
@base.add_check_constraint(name, *args, **options)
|
815
815
|
end
|
816
816
|
|
817
817
|
# Removes the given check constraint from the table.
|
@@ -819,8 +819,8 @@ module ActiveRecord
|
|
819
819
|
# t.remove_check_constraint(name: "price_check")
|
820
820
|
#
|
821
821
|
# See {connection.remove_check_constraint}[rdoc-ref:SchemaStatements#remove_check_constraint]
|
822
|
-
def remove_check_constraint(*args)
|
823
|
-
@base.remove_check_constraint(name, *args)
|
822
|
+
def remove_check_constraint(*args, **options)
|
823
|
+
@base.remove_check_constraint(name, *args, **options)
|
824
824
|
end
|
825
825
|
end
|
826
826
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters # :nodoc:
|
5
5
|
class SchemaDumper < SchemaDumper # :nodoc:
|
6
|
+
DEFAULT_DATETIME_PRECISION = 6 # :nodoc:
|
7
|
+
|
6
8
|
def self.create(connection, options)
|
7
9
|
new(connection, options)
|
8
10
|
end
|
@@ -63,7 +65,18 @@ module ActiveRecord
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def schema_precision(column)
|
66
|
-
column.
|
68
|
+
if column.type == :datetime
|
69
|
+
case column.precision
|
70
|
+
when nil
|
71
|
+
"nil"
|
72
|
+
when DEFAULT_DATETIME_PRECISION
|
73
|
+
nil
|
74
|
+
else
|
75
|
+
column.precision.inspect
|
76
|
+
end
|
77
|
+
elsif column.precision
|
78
|
+
column.precision.inspect
|
79
|
+
end
|
67
80
|
end
|
68
81
|
|
69
82
|
def schema_scale(column)
|
@@ -1438,7 +1438,7 @@ module ActiveRecord
|
|
1438
1438
|
|
1439
1439
|
checks = []
|
1440
1440
|
|
1441
|
-
if !options.key?(:name) &&
|
1441
|
+
if !options.key?(:name) && expression_column_name?(column_name)
|
1442
1442
|
options[:name] = index_name(table_name, column_name)
|
1443
1443
|
column_names = []
|
1444
1444
|
else
|
@@ -1447,7 +1447,7 @@ module ActiveRecord
|
|
1447
1447
|
|
1448
1448
|
checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
|
1449
1449
|
|
1450
|
-
if column_names.present?
|
1450
|
+
if column_names.present? && !(options.key?(:name) && expression_column_name?(column_names))
|
1451
1451
|
checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
|
1452
1452
|
end
|
1453
1453
|
|
@@ -1515,7 +1515,7 @@ module ActiveRecord
|
|
1515
1515
|
end
|
1516
1516
|
|
1517
1517
|
def index_column_names(column_names)
|
1518
|
-
if
|
1518
|
+
if expression_column_name?(column_names)
|
1519
1519
|
column_names
|
1520
1520
|
else
|
1521
1521
|
Array(column_names)
|
@@ -1523,13 +1523,18 @@ module ActiveRecord
|
|
1523
1523
|
end
|
1524
1524
|
|
1525
1525
|
def index_name_options(column_names)
|
1526
|
-
if
|
1526
|
+
if expression_column_name?(column_names)
|
1527
1527
|
column_names = column_names.scan(/\w+/).join("_")
|
1528
1528
|
end
|
1529
1529
|
|
1530
1530
|
{ column: column_names }
|
1531
1531
|
end
|
1532
1532
|
|
1533
|
+
# Try to identify whether the given column name is an expression
|
1534
|
+
def expression_column_name?(column_name)
|
1535
|
+
column_name.is_a?(String) && /\W/.match?(column_name)
|
1536
|
+
end
|
1537
|
+
|
1533
1538
|
def strip_table_name_prefix_and_suffix(table_name)
|
1534
1539
|
prefix = Base.table_name_prefix
|
1535
1540
|
suffix = Base.table_name_suffix
|
@@ -197,7 +197,7 @@ module ActiveRecord
|
|
197
197
|
|
198
198
|
# Executes the SQL statement in the context of this connection.
|
199
199
|
def execute(sql, name = nil, async: false)
|
200
|
-
raw_execute(sql, name, async)
|
200
|
+
raw_execute(sql, name, async: async)
|
201
201
|
end
|
202
202
|
|
203
203
|
# Mysql2Adapter doesn't have to free a result after using it, but we use this method
|
@@ -100,8 +100,8 @@ module ActiveRecord
|
|
100
100
|
statements = statements.map { |sql| transform_query(sql) }
|
101
101
|
combine_multi_statements(statements).each do |statement|
|
102
102
|
raw_execute(statement, name)
|
103
|
+
@connection.abandon_results!
|
103
104
|
end
|
104
|
-
@connection.abandon_results!
|
105
105
|
end
|
106
106
|
|
107
107
|
def default_insert_value(column)
|
@@ -53,7 +53,13 @@ module ActiveRecord
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def schema_precision(column)
|
56
|
-
|
56
|
+
if /\Atime(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
|
57
|
+
nil
|
58
|
+
elsif column.type == :datetime
|
59
|
+
column.precision == 0 ? "nil" : super
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
57
63
|
end
|
58
64
|
|
59
65
|
def schema_collation(column)
|
@@ -163,6 +163,7 @@ module ActiveRecord
|
|
163
163
|
default, default_function = field[:Default], nil
|
164
164
|
|
165
165
|
if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
|
166
|
+
default = "#{default} ON UPDATE #{default}" if /on update CURRENT_TIMESTAMP/i.match?(field[:Extra])
|
166
167
|
default, default_function = nil, default
|
167
168
|
elsif type_metadata.extra == "DEFAULT_GENERATED"
|
168
169
|
default = +"(#{default})" unless default.start_with?("(")
|
@@ -525,7 +525,7 @@ module ActiveRecord
|
|
525
525
|
scope = quoted_scope(table_name)
|
526
526
|
|
527
527
|
check_info = exec_query(<<-SQL, "SCHEMA")
|
528
|
-
SELECT conname, pg_get_constraintdef(c.oid) AS constraintdef, c.convalidated AS valid
|
528
|
+
SELECT conname, pg_get_constraintdef(c.oid, true) AS constraintdef, c.convalidated AS valid
|
529
529
|
FROM pg_constraint c
|
530
530
|
JOIN pg_class t ON c.conrelid = t.oid
|
531
531
|
WHERE c.contype = 'c'
|
@@ -537,7 +537,7 @@ module ActiveRecord
|
|
537
537
|
name: row["conname"],
|
538
538
|
validate: row["valid"]
|
539
539
|
}
|
540
|
-
expression = row["constraintdef"][/CHECK \(
|
540
|
+
expression = row["constraintdef"][/CHECK \((.+)\)/m, 1]
|
541
541
|
|
542
542
|
CheckConstraintDefinition.new(table_name, expression, options)
|
543
543
|
end
|
@@ -663,7 +663,12 @@ module ActiveRecord
|
|
663
663
|
column_name, type, default, notnull, oid, fmod, collation, comment, attgenerated = field
|
664
664
|
type_metadata = fetch_type_metadata(column_name, type, oid.to_i, fmod.to_i)
|
665
665
|
default_value = extract_value_from_default(default)
|
666
|
-
|
666
|
+
|
667
|
+
if attgenerated.present?
|
668
|
+
default_function = default
|
669
|
+
else
|
670
|
+
default_function = extract_default_function(default_value, default)
|
671
|
+
end
|
667
672
|
|
668
673
|
if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
|
669
674
|
serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
|
@@ -75,7 +75,7 @@ module ActiveRecord
|
|
75
75
|
|
76
76
|
class << self
|
77
77
|
def new_client(conn_params)
|
78
|
-
PG.connect(conn_params)
|
78
|
+
PG.connect(**conn_params)
|
79
79
|
rescue ::PG::Error => error
|
80
80
|
if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
|
81
81
|
raise ActiveRecord::NoDatabaseError.db_error(conn_params[:dbname])
|
@@ -281,7 +281,7 @@ module ActiveRecord
|
|
281
281
|
def initialize(connection, logger, connection_parameters, config)
|
282
282
|
super(connection, logger, config)
|
283
283
|
|
284
|
-
@connection_parameters = connection_parameters
|
284
|
+
@connection_parameters = connection_parameters || {}
|
285
285
|
|
286
286
|
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
287
287
|
@local_tz = nil
|
@@ -45,6 +45,19 @@ module ActiveRecord
|
|
45
45
|
0
|
46
46
|
end
|
47
47
|
|
48
|
+
def quote_default_expression(value, column) # :nodoc:
|
49
|
+
if value.is_a?(Proc)
|
50
|
+
value = value.call
|
51
|
+
if value.match?(/\A\w+\(.*\)\z/)
|
52
|
+
"(#{value})"
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
48
61
|
def type_cast(value) # :nodoc:
|
49
62
|
case value
|
50
63
|
when BigDecimal
|
@@ -127,20 +127,20 @@ module ActiveRecord
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def new_column_from_field(table_name, field)
|
130
|
-
default =
|
131
|
-
case field["dflt_value"]
|
132
|
-
when /^null$/i
|
133
|
-
nil
|
134
|
-
when /^'(.*)'$/m
|
135
|
-
$1.gsub("''", "'")
|
136
|
-
when /^"(.*)"$/m
|
137
|
-
$1.gsub('""', '"')
|
138
|
-
else
|
139
|
-
field["dflt_value"]
|
140
|
-
end
|
130
|
+
default = field["dflt_value"]
|
141
131
|
|
142
132
|
type_metadata = fetch_type_metadata(field["type"])
|
143
|
-
|
133
|
+
default_value = extract_value_from_default(default)
|
134
|
+
default_function = extract_default_function(default_value, default)
|
135
|
+
|
136
|
+
Column.new(
|
137
|
+
field["name"],
|
138
|
+
default_value,
|
139
|
+
type_metadata,
|
140
|
+
field["notnull"].to_i == 0,
|
141
|
+
default_function,
|
142
|
+
collation: field["collation"]
|
143
|
+
)
|
144
144
|
end
|
145
145
|
|
146
146
|
def data_source_sql(name = nil, type: nil)
|
@@ -389,6 +389,34 @@ module ActiveRecord
|
|
389
389
|
end
|
390
390
|
alias column_definitions table_structure
|
391
391
|
|
392
|
+
def extract_value_from_default(default)
|
393
|
+
case default
|
394
|
+
when /^null$/i
|
395
|
+
nil
|
396
|
+
# Quoted types
|
397
|
+
when /^'(.*)'$/m
|
398
|
+
$1.gsub("''", "'")
|
399
|
+
# Quoted types
|
400
|
+
when /^"(.*)"$/m
|
401
|
+
$1.gsub('""', '"')
|
402
|
+
# Numeric types
|
403
|
+
when /\A-?\d+(\.\d*)?\z/
|
404
|
+
$&
|
405
|
+
else
|
406
|
+
# Anything else is blank or some function
|
407
|
+
# and we can't know the value of that, so return nil.
|
408
|
+
nil
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def extract_default_function(default_value, default)
|
413
|
+
default if has_default_function?(default_value, default)
|
414
|
+
end
|
415
|
+
|
416
|
+
def has_default_function?(default_value, default)
|
417
|
+
!default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
418
|
+
end
|
419
|
+
|
392
420
|
# See: https://www.sqlite.org/lang_altertable.html
|
393
421
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
394
422
|
def invalid_alter_table_type?(type, options)
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
38
38
|
# the returned list. Most of the time we're only iterating over the write
|
39
39
|
# connection (i.e. migrations don't need to run for the write and read connection).
|
40
40
|
# Defaults to +false+.
|
41
|
-
# * <tt>include_hidden:</
|
41
|
+
# * <tt>include_hidden:</tt> Determines whether to include replicas and configurations
|
42
42
|
# hidden by +database_tasks: false+ in the returned list. Most of the time we're only
|
43
43
|
# iterating over the primary connections (i.e. migrations don't need to run for the
|
44
44
|
# write and read connection). Defaults to +false+.
|
@@ -50,9 +50,9 @@ module ActiveRecord
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def install_auto_filtered_parameters_hook(application) # :nodoc:
|
54
54
|
ActiveRecord::Encryption.on_encrypted_attribute_declared do |klass, encrypted_attribute_name|
|
55
|
-
application.config.filter_parameters << encrypted_attribute_name unless ActiveRecord::Encryption.config.excluded_from_filter_parameters.include?(
|
55
|
+
application.config.filter_parameters << encrypted_attribute_name unless ActiveRecord::Encryption.config.excluded_from_filter_parameters.include?(encrypted_attribute_name)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -1,35 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Automatically expand encrypted arguments to support querying both encrypted and unencrypted data
|
4
|
-
#
|
5
|
-
# Active Record Encryption supports querying the db using deterministic attributes. For example:
|
6
|
-
#
|
7
|
-
# Contact.find_by(email_address: "jorge@hey.com")
|
8
|
-
#
|
9
|
-
# The value "jorge@hey.com" will get encrypted automatically to perform the query. But there is
|
10
|
-
# a problem while the data is being encrypted. This won't work. During that time, you need these
|
11
|
-
# queries to be:
|
12
|
-
#
|
13
|
-
# Contact.find_by(email_address: [ "jorge@hey.com", "<encrypted jorge@hey.com>" ])
|
14
|
-
#
|
15
|
-
# This patches ActiveRecord to support this automatically. It addresses both:
|
16
|
-
#
|
17
|
-
# * ActiveRecord::Base: Used in +Contact.find_by_email_address(...)+
|
18
|
-
# * ActiveRecord::Relation: Used in +Contact.internal.find_by_email_address(...)+
|
19
|
-
#
|
20
|
-
# +ActiveRecord::Base+ relies on +ActiveRecord::Relation+ (+ActiveRecord::QueryMethods+) but it does
|
21
|
-
# some prepared statements caching. That's why we need to intercept +ActiveRecord::Base+ as soon
|
22
|
-
# as it's invoked (so that the proper prepared statement is cached).
|
23
|
-
#
|
24
|
-
# When modifying this file run performance tests in +test/performance/extended_deterministic_queries_performance_test.rb+ to
|
25
|
-
# make sure performance overhead is acceptable.
|
26
|
-
#
|
27
|
-
# We will extend this to support previous "encryption context" versions in future iterations
|
28
|
-
#
|
29
|
-
# @TODO Experimental. Support for every kind of query is pending
|
30
|
-
# @TODO It should not patch anything if not needed (no previous schemes or no support for previous encryption schemes)
|
31
3
|
module ActiveRecord
|
32
4
|
module Encryption
|
5
|
+
# Automatically expand encrypted arguments to support querying both encrypted and unencrypted data
|
6
|
+
#
|
7
|
+
# Active Record Encryption supports querying the db using deterministic attributes. For example:
|
8
|
+
#
|
9
|
+
# Contact.find_by(email_address: "jorge@hey.com")
|
10
|
+
#
|
11
|
+
# The value "jorge@hey.com" will get encrypted automatically to perform the query. But there is
|
12
|
+
# a problem while the data is being encrypted. This won't work. During that time, you need these
|
13
|
+
# queries to be:
|
14
|
+
#
|
15
|
+
# Contact.find_by(email_address: [ "jorge@hey.com", "<encrypted jorge@hey.com>" ])
|
16
|
+
#
|
17
|
+
# This patches ActiveRecord to support this automatically. It addresses both:
|
18
|
+
#
|
19
|
+
# * ActiveRecord::Base: Used in +Contact.find_by_email_address(...)+
|
20
|
+
# * ActiveRecord::Relation: Used in +Contact.internal.find_by_email_address(...)+
|
21
|
+
#
|
22
|
+
# +ActiveRecord::Base+ relies on +ActiveRecord::Relation+ (+ActiveRecord::QueryMethods+) but it does
|
23
|
+
# some prepared statements caching. That's why we need to intercept +ActiveRecord::Base+ as soon
|
24
|
+
# as it's invoked (so that the proper prepared statement is cached).
|
25
|
+
#
|
26
|
+
# When modifying this file run performance tests in +test/performance/extended_deterministic_queries_performance_test.rb+ to
|
27
|
+
# make sure performance overhead is acceptable.
|
28
|
+
#
|
29
|
+
# We will extend this to support previous "encryption context" versions in future iterations
|
30
|
+
#
|
31
|
+
# @TODO Experimental. Support for every kind of query is pending
|
32
|
+
# @TODO It should not patch anything if not needed (no previous schemes or no support for previous encryption schemes)
|
33
33
|
module ExtendedDeterministicQueries
|
34
34
|
def self.install_support
|
35
35
|
ActiveRecord::Relation.prepend(RelationQueries)
|
@@ -79,7 +79,7 @@ module ActiveRecord
|
|
79
79
|
timestamp = max_updated_column_timestamp
|
80
80
|
|
81
81
|
if timestamp
|
82
|
-
timestamp = timestamp.utc.
|
82
|
+
timestamp = timestamp.utc.to_fs(cache_timestamp_format)
|
83
83
|
"#{model_name.cache_key}/#{id}-#{timestamp}"
|
84
84
|
else
|
85
85
|
"#{model_name.cache_key}/#{id}"
|
@@ -103,7 +103,7 @@ module ActiveRecord
|
|
103
103
|
raw_timestamp_to_cache_version(timestamp)
|
104
104
|
|
105
105
|
elsif timestamp = updated_at
|
106
|
-
timestamp.utc.
|
106
|
+
timestamp.utc.to_fs(cache_timestamp_format)
|
107
107
|
end
|
108
108
|
elsif self.class.has_attribute?("updated_at")
|
109
109
|
raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
|
@@ -92,6 +92,22 @@ module ActiveRecord
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
+
module SQLite3
|
96
|
+
module TableDefinition
|
97
|
+
def references(*args, **options)
|
98
|
+
args.each do |ref_name|
|
99
|
+
ReferenceDefinition.new(ref_name, type: :integer, **options).add_to(self)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
alias :belongs_to :references
|
103
|
+
|
104
|
+
def column(name, type, index: nil, **options)
|
105
|
+
options[:precision] ||= nil
|
106
|
+
super
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
95
111
|
module TableDefinition
|
96
112
|
def references(*args, **options)
|
97
113
|
args.each do |ref_name|
|
@@ -131,8 +147,13 @@ module ActiveRecord
|
|
131
147
|
end
|
132
148
|
|
133
149
|
def add_reference(table_name, ref_name, **options)
|
134
|
-
|
135
|
-
.
|
150
|
+
if connection.adapter_name == "SQLite"
|
151
|
+
reference_definition = ReferenceDefinition.new(ref_name, type: :integer, **options)
|
152
|
+
else
|
153
|
+
reference_definition = ReferenceDefinition.new(ref_name, **options)
|
154
|
+
end
|
155
|
+
|
156
|
+
reference_definition.add_to(connection.update_table_definition(table_name, self))
|
136
157
|
end
|
137
158
|
alias :add_belongs_to :add_reference
|
138
159
|
|
@@ -140,6 +161,7 @@ module ActiveRecord
|
|
140
161
|
def compatible_table_definition(t)
|
141
162
|
class << t
|
142
163
|
prepend TableDefinition
|
164
|
+
prepend SQLite3::TableDefinition
|
143
165
|
end
|
144
166
|
t
|
145
167
|
end
|
@@ -1001,7 +1001,7 @@ module ActiveRecord
|
|
1001
1001
|
# Determines the version number of the next migration.
|
1002
1002
|
def next_migration_number(number)
|
1003
1003
|
if ActiveRecord.timestamped_migrations
|
1004
|
-
[Time.now.utc.strftime("%Y%m%d%H%M%S")
|
1004
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
1005
1005
|
else
|
1006
1006
|
SchemaMigration.normalize_migration_number(number)
|
1007
1007
|
end
|
@@ -360,9 +360,9 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
360
360
|
end
|
361
361
|
|
362
362
|
# Filtered params
|
363
|
-
ActiveSupport.on_load(:action_controller) do
|
363
|
+
ActiveSupport.on_load(:action_controller, run_once: true) do
|
364
364
|
if ActiveRecord::Encryption.config.add_to_filter_parameters
|
365
|
-
ActiveRecord::Encryption.
|
365
|
+
ActiveRecord::Encryption.install_auto_filtered_parameters_hook(app)
|
366
366
|
end
|
367
367
|
end
|
368
368
|
end
|
@@ -1031,7 +1031,7 @@ module ActiveRecord
|
|
1031
1031
|
end
|
1032
1032
|
|
1033
1033
|
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
1034
|
-
scopes = @previous_reflection.join_scopes(table, predicate_builder, record) + super
|
1034
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
1035
1035
|
scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
|
1036
1036
|
end
|
1037
1037
|
|
@@ -155,7 +155,7 @@ module ActiveRecord
|
|
155
155
|
end
|
156
156
|
|
157
157
|
# Use #pluck as a shortcut to select one or more attributes without
|
158
|
-
# loading
|
158
|
+
# loading an entire record object per row.
|
159
159
|
#
|
160
160
|
# Person.pluck(:name)
|
161
161
|
#
|
@@ -345,12 +345,13 @@ module ActiveRecord
|
|
345
345
|
column = aggregate_column(column_name)
|
346
346
|
column_alias = column_alias_for("#{operation} #{column_name.to_s.downcase}")
|
347
347
|
select_value = operation_over_aggregate_column(column, operation, distinct)
|
348
|
-
select_value.as(column_alias)
|
348
|
+
select_value.as(connection.quote_column_name(column_alias))
|
349
349
|
|
350
350
|
select_values = [select_value]
|
351
351
|
select_values += self.select_values unless having_clause.empty?
|
352
352
|
|
353
353
|
select_values.concat group_columns.map { |aliaz, field|
|
354
|
+
aliaz = connection.quote_column_name(aliaz)
|
354
355
|
if field.respond_to?(:as)
|
355
356
|
field.as(aliaz)
|
356
357
|
else
|
@@ -87,7 +87,7 @@ module ActiveRecord
|
|
87
87
|
|
88
88
|
delegate :to_xml, :encode_with, :length, :each, :join,
|
89
89
|
:[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
|
90
|
-
:to_sentence, :to_formatted_s, :as_json,
|
90
|
+
:to_sentence, :to_fs, :to_formatted_s, :as_json,
|
91
91
|
:shuffle, :split, :slice, :index, :rindex, to: :records
|
92
92
|
|
93
93
|
delegate :primary_key, :connection, to: :klass
|
@@ -68,7 +68,7 @@ module ActiveRecord
|
|
68
68
|
# # WHERE "authors"."id" IS NOT NULL AND "comments"."id" IS NOT NULL
|
69
69
|
def associated(*associations)
|
70
70
|
associations.each do |association|
|
71
|
-
reflection =
|
71
|
+
reflection = scope_association_reflection(association)
|
72
72
|
@scope.joins!(association)
|
73
73
|
self.not(reflection.table_name => { reflection.association_primary_key => nil })
|
74
74
|
end
|
@@ -96,13 +96,22 @@ module ActiveRecord
|
|
96
96
|
# # WHERE "authors"."id" IS NULL AND "comments"."id" IS NULL
|
97
97
|
def missing(*associations)
|
98
98
|
associations.each do |association|
|
99
|
-
reflection =
|
99
|
+
reflection = scope_association_reflection(association)
|
100
100
|
@scope.left_outer_joins!(association)
|
101
101
|
@scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
|
102
102
|
end
|
103
103
|
|
104
104
|
@scope
|
105
105
|
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def scope_association_reflection(association)
|
109
|
+
reflection = @scope.klass._reflect_on_association(association)
|
110
|
+
unless reflection
|
111
|
+
raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{@scope.name}`.")
|
112
|
+
end
|
113
|
+
reflection
|
114
|
+
end
|
106
115
|
end
|
107
116
|
|
108
117
|
FROZEN_EMPTY_ARRAY = [].freeze
|
@@ -424,18 +433,23 @@ module ActiveRecord
|
|
424
433
|
# adapter this will either use a CASE statement or a built-in function.
|
425
434
|
#
|
426
435
|
# User.in_order_of(:id, [1, 5, 3])
|
427
|
-
# # SELECT "users".* FROM "users"
|
436
|
+
# # SELECT "users".* FROM "users"
|
437
|
+
# # ORDER BY FIELD("users"."id", 1, 5, 3)
|
438
|
+
# # WHERE "users"."id" IN (1, 5, 3)
|
428
439
|
#
|
429
440
|
def in_order_of(column, values)
|
430
441
|
klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
|
442
|
+
return spawn.none! if values.empty?
|
431
443
|
|
432
444
|
references = column_references([column])
|
433
445
|
self.references_values |= references unless references.empty?
|
434
446
|
|
435
447
|
values = values.map { |value| type_caster.type_cast_for_database(column, value) }
|
436
|
-
|
448
|
+
arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
|
437
449
|
|
438
|
-
spawn
|
450
|
+
spawn
|
451
|
+
.order!(connection.field_ordered_value(arel_column, values))
|
452
|
+
.where!(arel_column.in(values))
|
439
453
|
end
|
440
454
|
|
441
455
|
# Replaces any existing order defined on the relation with the specified order.
|
@@ -388,7 +388,7 @@ module ActiveRecord
|
|
388
388
|
end
|
389
389
|
|
390
390
|
if timestamp
|
391
|
-
"#{size}-#{timestamp.utc.
|
391
|
+
"#{size}-#{timestamp.utc.to_fs(cache_timestamp_format)}"
|
392
392
|
else
|
393
393
|
"#{size}"
|
394
394
|
end
|
@@ -646,6 +646,21 @@ module ActiveRecord
|
|
646
646
|
# Schedule the query to be performed from a background thread pool.
|
647
647
|
#
|
648
648
|
# Post.where(published: true).load_async # => #<ActiveRecord::Relation>
|
649
|
+
#
|
650
|
+
# When the +Relation+ is iterated, if the background query wasn't executed yet,
|
651
|
+
# it will be performed by the foreground thread.
|
652
|
+
#
|
653
|
+
# Note that {config.active_record.async_query_executor}[https://guides.rubyonrails.org/configuring.html#config-active-record-async-query-executor] must be configured
|
654
|
+
# for queries to actually be executed concurrently. Otherwise it defaults to
|
655
|
+
# executing them in the foreground.
|
656
|
+
#
|
657
|
+
# +load_async+ will also fallback to executing in the foreground in the test environment when transactional
|
658
|
+
# fixtures are enabled.
|
659
|
+
#
|
660
|
+
# If the query was actually executed in the background, the Active Record logs will show
|
661
|
+
# it by prefixing the log line with <tt>ASYNC</tt>:
|
662
|
+
#
|
663
|
+
# ASYNC Post Load (0.0ms) (db time 2ms) SELECT "posts".* FROM "posts" LIMIT 100
|
649
664
|
def load_async
|
650
665
|
return load if !connection.async_enabled?
|
651
666
|
|
data/lib/active_record/schema.rb
CHANGED
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
#
|
11
11
|
# Usage:
|
12
12
|
#
|
13
|
-
# ActiveRecord::Schema.define do
|
13
|
+
# ActiveRecord::Schema[7.0].define do
|
14
14
|
# create_table :authors do |t|
|
15
15
|
# t.string :name, null: false
|
16
16
|
# end
|
@@ -30,32 +30,47 @@ module ActiveRecord
|
|
30
30
|
# ActiveRecord::Schema is only supported by database adapters that also
|
31
31
|
# support migrations, the two features being very similar.
|
32
32
|
class Schema < Migration::Current
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
module Definition
|
34
|
+
extend ActiveSupport::Concern
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
# Eval the given block. All methods available to the current connection
|
38
|
+
# adapter are available within the block, so you can easily use the
|
39
|
+
# database definition DSL to build up your schema (
|
40
|
+
# {create_table}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table],
|
41
|
+
# {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index], etc.).
|
42
|
+
#
|
43
|
+
# The +info+ hash is optional, and if given is used to define metadata
|
44
|
+
# about the current schema (currently, only the schema's version):
|
45
|
+
#
|
46
|
+
# ActiveRecord::Schema[7.0].define(version: 2038_01_19_000001) do
|
47
|
+
# ...
|
48
|
+
# end
|
49
|
+
def define(info = {}, &block)
|
50
|
+
new.define(info, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define(info, &block) # :nodoc:
|
55
|
+
instance_eval(&block)
|
48
56
|
|
49
|
-
|
50
|
-
|
57
|
+
if info[:version].present?
|
58
|
+
connection.schema_migration.create_table
|
59
|
+
connection.assume_migrated_upto_version(info[:version])
|
60
|
+
end
|
51
61
|
|
52
|
-
|
53
|
-
connection.
|
54
|
-
connection.assume_migrated_upto_version(info[:version])
|
62
|
+
ActiveRecord::InternalMetadata.create_table
|
63
|
+
ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
|
55
64
|
end
|
65
|
+
end
|
66
|
+
|
67
|
+
include Definition
|
56
68
|
|
57
|
-
|
58
|
-
|
69
|
+
def self.[](version)
|
70
|
+
@class_for_version ||= {}
|
71
|
+
@class_for_version[version] ||= Class.new(Migration::Compatibility.find(version)) do
|
72
|
+
include Definition
|
73
|
+
end
|
59
74
|
end
|
60
75
|
end
|
61
76
|
end
|
@@ -74,22 +74,21 @@ module ActiveRecord
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def header(stream)
|
77
|
-
stream.puts
|
78
|
-
# This file is auto-generated from the current state of the database. Instead
|
79
|
-
# of editing this file, please use the migrations feature of Active Record to
|
80
|
-
# incrementally modify your database, and then regenerate this schema definition.
|
81
|
-
#
|
82
|
-
# This file is the source Rails uses to define your schema when running `bin/rails
|
83
|
-
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
84
|
-
# be faster and is potentially less error prone than running all of your
|
85
|
-
# migrations from scratch. Old migrations may fail to apply correctly if those
|
86
|
-
# migrations use external dependencies or application code.
|
87
|
-
#
|
88
|
-
# It's strongly recommended that you check this file into your version control system.
|
89
|
-
|
90
|
-
ActiveRecord::Schema.define(#{define_params}) do
|
91
|
-
|
92
|
-
HEADER
|
77
|
+
stream.puts <<~HEADER
|
78
|
+
# This file is auto-generated from the current state of the database. Instead
|
79
|
+
# of editing this file, please use the migrations feature of Active Record to
|
80
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
81
|
+
#
|
82
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
83
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
84
|
+
# be faster and is potentially less error prone than running all of your
|
85
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
86
|
+
# migrations use external dependencies or application code.
|
87
|
+
#
|
88
|
+
# It's strongly recommended that you check this file into your version control system.
|
89
|
+
|
90
|
+
ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
|
91
|
+
HEADER
|
93
92
|
end
|
94
93
|
|
95
94
|
def trailer(stream)
|
@@ -257,8 +257,12 @@ module ActiveRecord
|
|
257
257
|
scope = ENV["SCOPE"]
|
258
258
|
verbose_was, Migration.verbose = Migration.verbose, verbose?
|
259
259
|
|
260
|
-
Base.connection.migration_context.migrate(target_version
|
261
|
-
|
260
|
+
Base.connection.migration_context.migrate(target_version) do |migration|
|
261
|
+
if version.blank?
|
262
|
+
scope.blank? || scope == migration.scope
|
263
|
+
else
|
264
|
+
migration.version == version
|
265
|
+
end
|
262
266
|
end.tap do |migrations_ran|
|
263
267
|
Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
|
264
268
|
end
|
@@ -58,7 +58,7 @@ module ActiveRecord
|
|
58
58
|
end
|
59
59
|
|
60
60
|
args = ["--schema-only", "--no-privileges", "--no-owner"]
|
61
|
-
args << "--no-
|
61
|
+
args << "--no-comments" if connection.database_version >= 110_000
|
62
62
|
args.concat(["--file", filename])
|
63
63
|
|
64
64
|
args.concat(Array(extra_flags)) if extra_flags
|
data/lib/active_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2022 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 7.0.
|
19
|
+
version: 7.0.2.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 7.0.
|
26
|
+
version: 7.0.2.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 7.0.
|
33
|
+
version: 7.0.2.2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 7.0.
|
40
|
+
version: 7.0.2.2
|
41
41
|
description: Databases on Rails. Build a persistent domain model by mapping database
|
42
42
|
tables to Ruby classes. Strong conventions for associations, validations, aggregations,
|
43
43
|
migrations, and testing come baked-in.
|
@@ -434,12 +434,12 @@ licenses:
|
|
434
434
|
- MIT
|
435
435
|
metadata:
|
436
436
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
437
|
-
changelog_uri: https://github.com/rails/rails/blob/v7.0.
|
438
|
-
documentation_uri: https://api.rubyonrails.org/v7.0.
|
437
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.0.2.2/activerecord/CHANGELOG.md
|
438
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.2.2/
|
439
439
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
440
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.0.
|
440
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.0.2.2/activerecord
|
441
441
|
rubygems_mfa_required: 'true'
|
442
|
-
post_install_message:
|
442
|
+
post_install_message:
|
443
443
|
rdoc_options:
|
444
444
|
- "--main"
|
445
445
|
- README.rdoc
|
@@ -456,8 +456,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
456
456
|
- !ruby/object:Gem::Version
|
457
457
|
version: '0'
|
458
458
|
requirements: []
|
459
|
-
rubygems_version: 3.2.
|
460
|
-
signing_key:
|
459
|
+
rubygems_version: 3.2.22
|
460
|
+
signing_key:
|
461
461
|
specification_version: 4
|
462
462
|
summary: Object-relational mapper framework (part of Rails).
|
463
463
|
test_files: []
|