activerecord 7.0.4.3 → 7.0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +109 -7
- data/lib/active_record/associations/has_one_association.rb +4 -0
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/singular_association.rb +7 -5
- data/lib/active_record/associations.rb +15 -6
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -4
- data/lib/active_record/attribute_methods.rb +5 -7
- data/lib/active_record/callbacks.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +20 -16
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +4 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -3
- data/lib/active_record/connection_adapters/mysql/quoting.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -5
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/middleware/database_selector.rb +3 -3
- data/lib/active_record/migration/command_recorder.rb +1 -2
- data/lib/active_record/migration/compatibility.rb +7 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/relation/calculations.rb +50 -23
- data/lib/active_record/relation/predicate_builder.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +3 -3
- data/lib/active_record/schema_dumper.rb +4 -0
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/type/serialized.rb +4 -4
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/filter.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 572cf430aba8f89db10099754543391f35585ddf6e696f0f07b4b4de3a8705d4
|
4
|
+
data.tar.gz: caf69799eae3b7059d405b08f1d7e0b2e09d9f794cdf0ff47ac92614da04a640
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 232404c2cf6cf6a785e32b8aac5be7c45db0e4de54c2b9aa7cf56a8b44ea87725a1b3a044ba9c3f79b3a73cc57300ac0ef9139762d769bc6bc7e71e1274c3765
|
7
|
+
data.tar.gz: 3193ff9f69dddcf8233a2ea00aef1eabaaf58525fbb4653e10ac570e3f52f917f90b2aec649926c506c8bacc81454e9c2f6ed9a7554accfd3d4fd71bb5a40177
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,105 @@
|
|
1
|
+
## Rails 7.0.5.1 (June 26, 2023) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 7.0.5 (May 24, 2023) ##
|
7
|
+
|
8
|
+
* Type cast `#attribute_changed?` `:from` and `:to` options.
|
9
|
+
|
10
|
+
*Andrew Novoselac*
|
11
|
+
|
12
|
+
* Fix `index_exists?` when column is an array.
|
13
|
+
|
14
|
+
*Eileen M. Uchitelle*
|
15
|
+
|
16
|
+
* Handle `Date` objects for PostgreSQL `timestamptz` columns.
|
17
|
+
|
18
|
+
*Alex Ghiculescu*
|
19
|
+
|
20
|
+
* Fix collation for changing column to non-string.
|
21
|
+
|
22
|
+
*Hartley McGuire*
|
23
|
+
|
24
|
+
* Map through subtype in `PostgreSQL::OID::Array`.
|
25
|
+
|
26
|
+
*Jonathan Hefner*
|
27
|
+
|
28
|
+
* Store correct environment in `internal_metadata` when run rails `db:prepare`.
|
29
|
+
|
30
|
+
*fatkodima*
|
31
|
+
|
32
|
+
* Make sure `ActiveRecord::Relation#sum` works with objects that implement `#coerce` without deprecation.
|
33
|
+
|
34
|
+
*Alex Ghiculescu*
|
35
|
+
|
36
|
+
* Fix retrieving foreign keys referencing tables named like keywords in PostgreSQL and MySQL.
|
37
|
+
|
38
|
+
*fatkodima*
|
39
|
+
|
40
|
+
* Support UUIDs in Disable Joins.
|
41
|
+
|
42
|
+
*Samuel Cochran*
|
43
|
+
|
44
|
+
* Fix Active Record's explain for queries starting with comments.
|
45
|
+
|
46
|
+
*fatkodima*
|
47
|
+
|
48
|
+
* Fix incorrectly preloading through association records when middle association has been loaded.
|
49
|
+
|
50
|
+
*Joshua Young*
|
51
|
+
|
52
|
+
* Fix where.missing and where.associated for parent/child associations.
|
53
|
+
|
54
|
+
*fatkodima*
|
55
|
+
|
56
|
+
* Fix Enumerable#in_order_of to preserve duplicates.
|
57
|
+
|
58
|
+
*fatkodima*
|
59
|
+
|
60
|
+
* Fix autoincrement on primary key for mysql.
|
61
|
+
|
62
|
+
*Eileen M. Uchitelle*
|
63
|
+
|
64
|
+
* Restore ability to redefine column in `create_table` for Rails 5.2 migrations.
|
65
|
+
|
66
|
+
*fatkodima*
|
67
|
+
|
68
|
+
* Fix schema cache dumping of virtual columns.
|
69
|
+
|
70
|
+
*fatkodima*
|
71
|
+
|
72
|
+
* Fix Active Record grouped calculations on joined tables on column present in both tables.
|
73
|
+
|
74
|
+
*fatkodima*
|
75
|
+
|
76
|
+
* Fix mutation detection for serialized attributes backed by binary columns.
|
77
|
+
|
78
|
+
*Jean Boussier*
|
79
|
+
|
80
|
+
* Fix a bug where using groups and counts with long table names would return incorrect results.
|
81
|
+
|
82
|
+
*Shota Toguchi*, *Yusaku Ono*
|
83
|
+
|
84
|
+
* Use connection from `#with_raw_connection` in `#quote_string`.
|
85
|
+
|
86
|
+
Prior to this change, virtual datetime columns did not have the same
|
87
|
+
default precision as regular datetime columns, resulting in the following
|
88
|
+
being erroneously equivalent:
|
89
|
+
|
90
|
+
t.virtual :name, type: datetime, as: "expression"
|
91
|
+
t.virtual :name, type: datetime, precision: nil, as: "expression"
|
92
|
+
|
93
|
+
This change fixes the default precision lookup, so virtual and regular
|
94
|
+
datetime column default precisions match.
|
95
|
+
|
96
|
+
*Sam Bostock*
|
97
|
+
|
98
|
+
* Fix a case where the query cache can return wrong values. See #46044
|
99
|
+
|
100
|
+
*Aaron Patterson*
|
101
|
+
|
102
|
+
|
1
103
|
## Rails 7.0.4.3 (March 13, 2023) ##
|
2
104
|
|
3
105
|
* No changes.
|
@@ -17,7 +119,7 @@
|
|
17
119
|
carefully crafted input.
|
18
120
|
|
19
121
|
This commit makes the sanitization more robust by replacing any
|
20
|
-
|
122
|
+
occurrences of "/*" or "*/" with "/ *" or "* /". It also performs a
|
21
123
|
first pass to remove one surrounding comment to avoid compatibility
|
22
124
|
issues for users relying on the existing removal.
|
23
125
|
|
@@ -142,21 +244,21 @@
|
|
142
244
|
|
143
245
|
This adds two new configuration options The configuration options are as
|
144
246
|
follows:
|
145
|
-
|
146
|
-
* `config.
|
147
|
-
|
247
|
+
|
248
|
+
* `config.active_record.use_yaml_unsafe_load`
|
249
|
+
|
148
250
|
When set to true, this configuration option tells Rails to use the old
|
149
251
|
"unsafe" YAML loading strategy, maintaining the existing behavior but leaving
|
150
252
|
the possible escalation vulnerability in place. Setting this option to true
|
151
253
|
is *not* recommended, but can aid in upgrading.
|
152
|
-
|
254
|
+
|
153
255
|
* `config.active_record.yaml_column_permitted_classes`
|
154
|
-
|
256
|
+
|
155
257
|
The "safe YAML" loading method does not allow all classes to be deserialized
|
156
258
|
by default. This option allows you to specify classes deemed "safe" in your
|
157
259
|
application. For example, if your application uses Symbol and Time in
|
158
260
|
serialized data, you can add Symbol and Time to the allowed list as follows:
|
159
|
-
|
261
|
+
|
160
262
|
```
|
161
263
|
config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]
|
162
264
|
```
|
@@ -54,11 +54,13 @@ module ActiveRecord
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def _create_record(attributes, raise_error = false, &block)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
reflection.klass.transaction do
|
58
|
+
record = build(attributes, &block)
|
59
|
+
saved = record.save
|
60
|
+
replace_keys(record, force: true)
|
61
|
+
raise RecordInvalid.new(record) if !saved && raise_error
|
62
|
+
record
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
@@ -586,8 +586,11 @@ module ActiveRecord
|
|
586
586
|
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
587
587
|
# end
|
588
588
|
#
|
589
|
-
# Note: Joining
|
590
|
-
#
|
589
|
+
# Note: Joining or eager loading such associations is not possible because
|
590
|
+
# those operations happen before instance creation. Such associations
|
591
|
+
# _can_ be preloaded, but doing so will perform N+1 queries because there
|
592
|
+
# will be a different scope for each record (similar to preloading
|
593
|
+
# polymorphic scopes).
|
591
594
|
#
|
592
595
|
# == Association callbacks
|
593
596
|
#
|
@@ -1600,6 +1603,12 @@ module ActiveRecord
|
|
1600
1603
|
#
|
1601
1604
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1602
1605
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1606
|
+
# [:touch]
|
1607
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1608
|
+
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1609
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1610
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1611
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1603
1612
|
# [:inverse_of]
|
1604
1613
|
# Specifies the name of the #belongs_to association on the associated object
|
1605
1614
|
# that is the inverse of this #has_one association.
|
@@ -1747,11 +1756,11 @@ module ActiveRecord
|
|
1747
1756
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1748
1757
|
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1749
1758
|
# [:touch]
|
1750
|
-
# If true, the associated object will be touched (the updated_at/
|
1759
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1751
1760
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1752
|
-
# will be updated with the current time in addition to the updated_at/
|
1753
|
-
# Please note that
|
1754
|
-
# +after_commit
|
1761
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1762
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1763
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1755
1764
|
# [:inverse_of]
|
1756
1765
|
# Specifies the name of the #has_one or #has_many association on the associated
|
1757
1766
|
# object that is the inverse of this #belongs_to association.
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
23
23
|
|
24
24
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after
|
25
25
|
# it has been typecast (for example, "2004-12-12" in a date column is cast
|
26
|
-
# to a date object, like Date.new(2004, 12, 12)).
|
26
|
+
# to a date object, like <tt>Date.new(2004, 12, 12)</tt>).
|
27
27
|
def read_attribute(attr_name, &block)
|
28
28
|
name = attr_name.to_s
|
29
29
|
name = self.class.attribute_aliases[name] || name
|
@@ -19,8 +19,6 @@ module ActiveRecord
|
|
19
19
|
|
20
20
|
if value.is_a?(Hash)
|
21
21
|
set_time_zone_without_conversion(super)
|
22
|
-
elsif value.is_a?(Range)
|
23
|
-
Range.new(user_input_in_time_zone(value.begin), user_input_in_time_zone(value.end), value.exclude_end?)
|
24
22
|
elsif value.respond_to?(:in_time_zone)
|
25
23
|
begin
|
26
24
|
super(user_input_in_time_zone(value)) || super
|
@@ -42,8 +40,6 @@ module ActiveRecord
|
|
42
40
|
value.in_time_zone
|
43
41
|
elsif value.respond_to?(:infinite?) && value.infinite?
|
44
42
|
value
|
45
|
-
elsif value.is_a?(Range)
|
46
|
-
Range.new(convert_time_to_time_zone(value.begin), convert_time_to_time_zone(value.end), value.exclude_end?)
|
47
43
|
else
|
48
44
|
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
49
45
|
end
|
@@ -310,8 +310,8 @@ module ActiveRecord
|
|
310
310
|
end
|
311
311
|
|
312
312
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
313
|
-
# "2004-12-12" in a date column is cast to a date object, like Date.new(2004, 12, 12)). It raises
|
314
|
-
#
|
313
|
+
# "2004-12-12" in a date column is cast to a date object, like <tt>Date.new(2004, 12, 12)</tt>). It raises
|
314
|
+
# ActiveModel::MissingAttributeError if the identified attribute is missing.
|
315
315
|
#
|
316
316
|
# Note: +:id+ is always present.
|
317
317
|
#
|
@@ -331,7 +331,6 @@ module ActiveRecord
|
|
331
331
|
end
|
332
332
|
|
333
333
|
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
334
|
-
# (Alias for the protected #write_attribute method).
|
335
334
|
#
|
336
335
|
# class Person < ActiveRecord::Base
|
337
336
|
# end
|
@@ -360,10 +359,9 @@ module ActiveRecord
|
|
360
359
|
# end
|
361
360
|
#
|
362
361
|
# private
|
363
|
-
#
|
364
|
-
#
|
365
|
-
#
|
366
|
-
# end
|
362
|
+
# def print_accessed_fields
|
363
|
+
# p @posts.first.accessed_fields
|
364
|
+
# end
|
367
365
|
# end
|
368
366
|
#
|
369
367
|
# Which allows you to quickly change your code to:
|
@@ -224,14 +224,13 @@ module ActiveRecord
|
|
224
224
|
# after_save :do_something_else
|
225
225
|
#
|
226
226
|
# private
|
227
|
+
# def log_children
|
228
|
+
# # Child processing
|
229
|
+
# end
|
227
230
|
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
# def do_something_else
|
233
|
-
# # Something else
|
234
|
-
# end
|
231
|
+
# def do_something_else
|
232
|
+
# # Something else
|
233
|
+
# end
|
235
234
|
# end
|
236
235
|
#
|
237
236
|
# In this case the +log_children+ is executed before +do_something_else+.
|
@@ -249,14 +248,13 @@ module ActiveRecord
|
|
249
248
|
# after_commit :do_something_else
|
250
249
|
#
|
251
250
|
# private
|
251
|
+
# def log_children
|
252
|
+
# # Child processing
|
253
|
+
# end
|
252
254
|
#
|
253
|
-
#
|
254
|
-
#
|
255
|
-
#
|
256
|
-
#
|
257
|
-
# def do_something_else
|
258
|
-
# # Something else
|
259
|
-
# end
|
255
|
+
# def do_something_else
|
256
|
+
# # Something else
|
257
|
+
# end
|
260
258
|
# end
|
261
259
|
#
|
262
260
|
# In this case the +do_something_else+ is executed before +log_children+.
|
@@ -411,20 +411,7 @@ module ActiveRecord
|
|
411
411
|
name = name.to_s
|
412
412
|
type = type.to_sym if type
|
413
413
|
|
414
|
-
|
415
|
-
if @columns_hash[name].primary_key?
|
416
|
-
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
417
|
-
else
|
418
|
-
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
if @conn.supports_datetime_with_precision?
|
423
|
-
if type == :datetime && !options.key?(:precision)
|
424
|
-
options[:precision] = 6
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
414
|
+
raise_on_duplicate_column(name)
|
428
415
|
@columns_hash[name] = new_column_definition(name, type, **options)
|
429
416
|
|
430
417
|
if index
|
@@ -491,6 +478,13 @@ module ActiveRecord
|
|
491
478
|
type = integer_like_primary_key_type(type, options)
|
492
479
|
end
|
493
480
|
type = aliased_types(type.to_s, type)
|
481
|
+
|
482
|
+
if @conn.supports_datetime_with_precision?
|
483
|
+
if type == :datetime && !options.key?(:precision)
|
484
|
+
options[:precision] = 6
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
494
488
|
options[:primary_key] ||= type == :primary_key
|
495
489
|
options[:null] = false if options[:primary_key]
|
496
490
|
create_column_definition(name, type, options)
|
@@ -525,6 +519,16 @@ module ActiveRecord
|
|
525
519
|
def integer_like_primary_key_type(type, options)
|
526
520
|
type
|
527
521
|
end
|
522
|
+
|
523
|
+
def raise_on_duplicate_column(name)
|
524
|
+
if @columns_hash[name]
|
525
|
+
if @columns_hash[name].primary_key?
|
526
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
527
|
+
else
|
528
|
+
raise ArgumentError, "you can't define an already defined column '#{name}'."
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
528
532
|
end
|
529
533
|
|
530
534
|
class AlterTable # :nodoc:
|
@@ -661,8 +665,8 @@ module ActiveRecord
|
|
661
665
|
# end
|
662
666
|
#
|
663
667
|
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
|
664
|
-
def index_exists?(column_name, options
|
665
|
-
@base.index_exists?(name, column_name, options)
|
668
|
+
def index_exists?(column_name, **options)
|
669
|
+
@base.index_exists?(name, column_name, **options)
|
666
670
|
end
|
667
671
|
|
668
672
|
# Renames the given index on the table.
|
@@ -593,6 +593,10 @@ module ActiveRecord
|
|
593
593
|
#
|
594
594
|
# This is useful for when you need to call a proprietary method such as
|
595
595
|
# PostgreSQL's lo_* methods.
|
596
|
+
#
|
597
|
+
# Active Record cannot track if the database is getting modified using
|
598
|
+
# this client. If that is the case, generally you'll want to invalidate
|
599
|
+
# the query cache using +ActiveRecord::Base.clear_query_cache+.
|
596
600
|
def raw_connection
|
597
601
|
disable_lazy_transactions!
|
598
602
|
@connection
|
@@ -403,7 +403,7 @@ module ActiveRecord
|
|
403
403
|
|
404
404
|
fk_info.map do |row|
|
405
405
|
options = {
|
406
|
-
column: row["column"],
|
406
|
+
column: unquote_identifier(row["column"]),
|
407
407
|
name: row["name"],
|
408
408
|
primary_key: row["primary_key"]
|
409
409
|
}
|
@@ -411,7 +411,7 @@ module ActiveRecord
|
|
411
411
|
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
412
412
|
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
413
413
|
|
414
|
-
ForeignKeyDefinition.new(table_name, row["to_table"], options)
|
414
|
+
ForeignKeyDefinition.new(table_name, unquote_identifier(row["to_table"]), options)
|
415
415
|
end
|
416
416
|
end
|
417
417
|
|
@@ -619,6 +619,10 @@ module ActiveRecord
|
|
619
619
|
end
|
620
620
|
|
621
621
|
private
|
622
|
+
def text_type?(type)
|
623
|
+
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
|
624
|
+
end
|
625
|
+
|
622
626
|
def type_map
|
623
627
|
emulate_booleans ? TYPE_MAP_WITH_BOOLEAN : TYPE_MAP
|
624
628
|
end
|
@@ -712,7 +716,7 @@ module ActiveRecord
|
|
712
716
|
end
|
713
717
|
|
714
718
|
unless options.key?(:collation)
|
715
|
-
options[:collation] = column.collation
|
719
|
+
options[:collation] = column.collation if text_type?(type)
|
716
720
|
end
|
717
721
|
|
718
722
|
unless options.key?(:auto_increment)
|
@@ -51,6 +51,14 @@ module ActiveRecord
|
|
51
51
|
"x'#{value.hex}'"
|
52
52
|
end
|
53
53
|
|
54
|
+
def unquote_identifier(identifier)
|
55
|
+
if identifier && identifier.start_with?("`")
|
56
|
+
identifier[1..-2]
|
57
|
+
else
|
58
|
+
identifier
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
54
62
|
# Override +type_cast+ we pass to mysql2 Date and Time objects instead
|
55
63
|
# of Strings since mysql2 is able to handle those classes more efficiently.
|
56
64
|
def type_cast(value) # :nodoc:
|
@@ -57,11 +57,7 @@ module ActiveRecord
|
|
57
57
|
fields.each_with_index do |fname, i|
|
58
58
|
ftype = result.ftype i
|
59
59
|
fmod = result.fmod i
|
60
|
-
|
61
|
-
when Type::Integer, Type::Float, OID::Decimal, Type::String, Type::DateTime, Type::Boolean
|
62
|
-
# skip if a column has already been type casted by pg decoders
|
63
|
-
else types[fname] = type
|
64
|
-
end
|
60
|
+
types[fname] = get_oid_type(ftype, fmod, fname)
|
65
61
|
end
|
66
62
|
build_result(columns: fields, rows: result.values, column_types: types)
|
67
63
|
end
|
@@ -13,7 +13,7 @@ module ActiveRecord
|
|
13
13
|
return if value.blank?
|
14
14
|
|
15
15
|
time = super
|
16
|
-
return time
|
16
|
+
return time unless time.acts_like?(:time)
|
17
17
|
|
18
18
|
# While in UTC mode, the PG gem may not return times back in "UTC" even if they were provided to Postgres in UTC.
|
19
19
|
# We prefer times always in UTC, so here we convert back.
|
@@ -498,7 +498,7 @@ module ActiveRecord
|
|
498
498
|
|
499
499
|
fk_info.map do |row|
|
500
500
|
options = {
|
501
|
-
column: row["column"],
|
501
|
+
column: Utils.unquote_identifier(row["column"]),
|
502
502
|
name: row["name"],
|
503
503
|
primary_key: row["primary_key"]
|
504
504
|
}
|
@@ -508,8 +508,9 @@ module ActiveRecord
|
|
508
508
|
options[:deferrable] = extract_foreign_key_deferrable(row["deferrable"], row["deferred"])
|
509
509
|
|
510
510
|
options[:validate] = row["valid"]
|
511
|
+
to_table = Utils.unquote_identifier(row["to_table"])
|
511
512
|
|
512
|
-
ForeignKeyDefinition.new(table_name,
|
513
|
+
ForeignKeyDefinition.new(table_name, to_table, options)
|
513
514
|
end
|
514
515
|
end
|
515
516
|
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
attr_reader :schema, :identifier
|
13
13
|
|
14
14
|
def initialize(schema, identifier)
|
15
|
-
@schema, @identifier =
|
15
|
+
@schema, @identifier = Utils.unquote_identifier(schema), Utils.unquote_identifier(identifier)
|
16
16
|
end
|
17
17
|
|
18
18
|
def to_s
|
@@ -40,15 +40,6 @@ module ActiveRecord
|
|
40
40
|
def parts
|
41
41
|
@parts ||= [@schema, @identifier].compact
|
42
42
|
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def unquote(part)
|
46
|
-
if part && part.start_with?('"')
|
47
|
-
part[1..-2]
|
48
|
-
else
|
49
|
-
part
|
50
|
-
end
|
51
|
-
end
|
52
43
|
end
|
53
44
|
|
54
45
|
module Utils # :nodoc:
|
@@ -74,6 +65,14 @@ module ActiveRecord
|
|
74
65
|
end
|
75
66
|
PostgreSQL::Name.new(schema, table)
|
76
67
|
end
|
68
|
+
|
69
|
+
def unquote_identifier(identifier)
|
70
|
+
if identifier && identifier.start_with?('"')
|
71
|
+
identifier[1..-2]
|
72
|
+
else
|
73
|
+
identifier
|
74
|
+
end
|
75
|
+
end
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
@@ -977,7 +977,7 @@ module ActiveRecord
|
|
977
977
|
PG::TextDecoder::TimestampUtc :
|
978
978
|
PG::TextDecoder::TimestampWithoutTimeZone
|
979
979
|
|
980
|
-
@timestamp_decoder = decoder_class.new(
|
980
|
+
@timestamp_decoder = decoder_class.new(**@timestamp_decoder.to_h)
|
981
981
|
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
982
982
|
|
983
983
|
@default_timezone = ActiveRecord.default_timezone
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
# On the other hand, we want to monitor the performance of our real database
|
22
22
|
# queries, not the performance of the access to the query cache.
|
23
23
|
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
24
|
-
EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
|
24
|
+
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
25
25
|
def ignore_payload?(payload)
|
26
26
|
payload[:exception] ||
|
27
27
|
payload[:cached] ||
|
@@ -43,9 +43,9 @@ module ActiveRecord
|
|
43
43
|
# config.active_record.database_resolver = MyResolver
|
44
44
|
# config.active_record.database_resolver_context = MyResolver::MySession
|
45
45
|
#
|
46
|
-
# Note: If you are using
|
47
|
-
#
|
48
|
-
#
|
46
|
+
# Note: If you are using <tt>rails new my_app --minimal</tt> you will need
|
47
|
+
# to call <tt>require "active_support/core_ext/integer/time"</tt> to load
|
48
|
+
# the core extension in order to use +2.seconds+
|
49
49
|
class DatabaseSelector
|
50
50
|
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
51
51
|
@app = app
|
@@ -12,7 +12,6 @@ module ActiveRecord
|
|
12
12
|
# * add_index
|
13
13
|
# * add_reference
|
14
14
|
# * add_timestamps
|
15
|
-
# * change_column
|
16
15
|
# * change_column_default (must supply a +:from+ and +:to+ option)
|
17
16
|
# * change_column_null
|
18
17
|
# * change_column_comment (must supply a +:from+ and +:to+ option)
|
@@ -24,7 +23,7 @@ module ActiveRecord
|
|
24
23
|
# * drop_table (must supply a block)
|
25
24
|
# * enable_extension
|
26
25
|
# * remove_column (must supply a type)
|
27
|
-
# * remove_columns (must
|
26
|
+
# * remove_columns (must supply a +:type+ option)
|
28
27
|
# * remove_foreign_key (must supply a second table)
|
29
28
|
# * remove_check_constraint
|
30
29
|
# * remove_index
|
@@ -1338,7 +1338,7 @@ module ActiveRecord
|
|
1338
1338
|
# Stores the current environment in the database.
|
1339
1339
|
def record_environment
|
1340
1340
|
return if down?
|
1341
|
-
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.
|
1341
|
+
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.pool.db_config.env_name
|
1342
1342
|
end
|
1343
1343
|
|
1344
1344
|
def ran?(migration)
|
@@ -4,6 +4,47 @@ require "active_support/core_ext/enumerable"
|
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Calculations
|
7
|
+
class ColumnAliasTracker # :nodoc:
|
8
|
+
def initialize(connection)
|
9
|
+
@connection = connection
|
10
|
+
@aliases = Hash.new(0)
|
11
|
+
end
|
12
|
+
|
13
|
+
def alias_for(field)
|
14
|
+
aliased_name = column_alias_for(field)
|
15
|
+
|
16
|
+
if @aliases[aliased_name] == 0
|
17
|
+
@aliases[aliased_name] = 1
|
18
|
+
aliased_name
|
19
|
+
else
|
20
|
+
# Update the count
|
21
|
+
count = @aliases[aliased_name] += 1
|
22
|
+
"#{truncate(aliased_name)}_#{count}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
# Converts the given field to the value that the database adapter returns as
|
28
|
+
# a usable column name:
|
29
|
+
#
|
30
|
+
# column_alias_for("users.id") # => "users_id"
|
31
|
+
# column_alias_for("sum(id)") # => "sum_id"
|
32
|
+
# column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
|
33
|
+
# column_alias_for("count(*)") # => "count_all"
|
34
|
+
def column_alias_for(field)
|
35
|
+
column_alias = +field
|
36
|
+
column_alias.gsub!(/\*/, "all")
|
37
|
+
column_alias.gsub!(/\W+/, " ")
|
38
|
+
column_alias.strip!
|
39
|
+
column_alias.gsub!(/ +/, "_")
|
40
|
+
@connection.table_alias_for(column_alias)
|
41
|
+
end
|
42
|
+
|
43
|
+
def truncate(name)
|
44
|
+
name.slice(0, @connection.table_alias_length - 2)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
7
48
|
# Count the records.
|
8
49
|
#
|
9
50
|
# Person.count
|
@@ -86,7 +127,7 @@ module ActiveRecord
|
|
86
127
|
def sum(identity_or_column = nil, &block)
|
87
128
|
if block_given?
|
88
129
|
values = map(&block)
|
89
|
-
if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [])
|
130
|
+
if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [] || values.first.respond_to?(:coerce))
|
90
131
|
identity_or_column = 0
|
91
132
|
end
|
92
133
|
|
@@ -336,14 +377,16 @@ module ActiveRecord
|
|
336
377
|
end
|
337
378
|
group_fields = arel_columns(group_fields)
|
338
379
|
|
380
|
+
column_alias_tracker = ColumnAliasTracker.new(connection)
|
381
|
+
|
339
382
|
group_aliases = group_fields.map { |field|
|
340
383
|
field = connection.visitor.compile(field) if Arel.arel_node?(field)
|
341
|
-
|
384
|
+
column_alias_tracker.alias_for(field.to_s.downcase)
|
342
385
|
}
|
343
386
|
group_columns = group_aliases.zip(group_fields)
|
344
387
|
|
345
388
|
column = aggregate_column(column_name)
|
346
|
-
column_alias =
|
389
|
+
column_alias = column_alias_tracker.alias_for("#{operation} #{column_name.to_s.downcase}")
|
347
390
|
select_value = operation_over_aggregate_column(column, operation, distinct)
|
348
391
|
select_value.as(connection.quote_column_name(column_alias))
|
349
392
|
|
@@ -372,9 +415,10 @@ module ActiveRecord
|
|
372
415
|
end
|
373
416
|
|
374
417
|
key_types = group_columns.each_with_object({}) do |(aliaz, col_name), types|
|
375
|
-
types[aliaz] =
|
376
|
-
|
377
|
-
|
418
|
+
types[aliaz] = col_name.try(:type_caster) ||
|
419
|
+
type_for(col_name) do
|
420
|
+
calculated_data.column_types.fetch(aliaz, Type.default_value)
|
421
|
+
end
|
378
422
|
end
|
379
423
|
|
380
424
|
hash_rows = calculated_data.cast_values(key_types).map! do |row|
|
@@ -398,23 +442,6 @@ module ActiveRecord
|
|
398
442
|
end
|
399
443
|
end
|
400
444
|
|
401
|
-
# Converts the given field to the value that the database adapter returns as
|
402
|
-
# a usable column name:
|
403
|
-
#
|
404
|
-
# column_alias_for("users.id") # => "users_id"
|
405
|
-
# column_alias_for("sum(id)") # => "sum_id"
|
406
|
-
# column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
|
407
|
-
# column_alias_for("count(*)") # => "count_all"
|
408
|
-
def column_alias_for(field)
|
409
|
-
column_alias = +field
|
410
|
-
column_alias.gsub!(/\*/, "all")
|
411
|
-
column_alias.gsub!(/\W+/, " ")
|
412
|
-
column_alias.strip!
|
413
|
-
column_alias.gsub!(/ +/, "_")
|
414
|
-
|
415
|
-
connection.table_alias_for(column_alias)
|
416
|
-
end
|
417
|
-
|
418
445
|
def type_for(field, &block)
|
419
446
|
field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split(".").last
|
420
447
|
@klass.type_for_attribute(field_name, &block)
|
@@ -65,7 +65,8 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def build_bind_attribute(column_name, value)
|
68
|
-
|
68
|
+
type = table.type(column_name)
|
69
|
+
Relation::QueryAttribute.new(column_name, type.immutable_value(value), type)
|
69
70
|
end
|
70
71
|
|
71
72
|
def resolve_arel_attribute(table_name, column_name, &block)
|
@@ -77,7 +77,7 @@ module ActiveRecord
|
|
77
77
|
associations.each do |association|
|
78
78
|
reflection = scope_association_reflection(association)
|
79
79
|
@scope.joins!(association)
|
80
|
-
self.not(
|
80
|
+
self.not(association => { reflection.association_primary_key => nil })
|
81
81
|
end
|
82
82
|
|
83
83
|
@scope
|
@@ -105,7 +105,7 @@ module ActiveRecord
|
|
105
105
|
associations.each do |association|
|
106
106
|
reflection = scope_association_reflection(association)
|
107
107
|
@scope.left_outer_joins!(association)
|
108
|
-
@scope.where!(
|
108
|
+
@scope.where!(association => { reflection.association_primary_key => nil })
|
109
109
|
end
|
110
110
|
|
111
111
|
@scope
|
@@ -289,7 +289,7 @@ module ActiveRecord
|
|
289
289
|
# You can also use one or more strings, which will be used unchanged as SELECT fields.
|
290
290
|
#
|
291
291
|
# Model.select('field AS field_one', 'other_field AS field_two')
|
292
|
-
# # => [#<Model id: nil,
|
292
|
+
# # => [#<Model id: nil, field_one: "value", field_two: "value">]
|
293
293
|
#
|
294
294
|
# If an alias was specified, it will be accessible from the resulting objects:
|
295
295
|
#
|
@@ -292,6 +292,10 @@ module ActiveRecord
|
|
292
292
|
end
|
293
293
|
|
294
294
|
def remove_prefix_and_suffix(table)
|
295
|
+
# This method appears at the top when profiling active_record test cases run.
|
296
|
+
# Avoid costly calculation when there are no prefix and suffix.
|
297
|
+
return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
|
298
|
+
|
295
299
|
prefix = Regexp.escape(@options[:table_name_prefix].to_s)
|
296
300
|
suffix = Regexp.escape(@options[:table_name_suffix].to_s)
|
297
301
|
table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
|
data/lib/active_record/store.rb
CHANGED
@@ -70,7 +70,7 @@ module ActiveRecord
|
|
70
70
|
#
|
71
71
|
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
|
72
72
|
#
|
73
|
-
# User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
|
73
|
+
# User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
|
74
74
|
#
|
75
75
|
# == Overwriting default accessors
|
76
76
|
#
|
@@ -63,11 +63,11 @@ module ActiveRecord
|
|
63
63
|
def encoded(value)
|
64
64
|
return if default_value?(value)
|
65
65
|
payload = coder.dump(value)
|
66
|
-
if payload && binary?
|
67
|
-
|
68
|
-
|
66
|
+
if payload && @subtype.binary?
|
67
|
+
ActiveModel::Type::Binary::Data.new(payload)
|
68
|
+
else
|
69
|
+
payload
|
69
70
|
end
|
70
|
-
payload
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
data/lib/arel/nodes/filter.rb
CHANGED
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.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-26 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.5.1
|
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.5.1
|
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.5.1
|
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.5.1
|
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,10 +434,10 @@ 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.5.1/activerecord/CHANGELOG.md
|
438
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.5.1/
|
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.5.1/activerecord
|
441
441
|
rubygems_mfa_required: 'true'
|
442
442
|
post_install_message:
|
443
443
|
rdoc_options:
|
@@ -456,7 +456,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
456
456
|
- !ruby/object:Gem::Version
|
457
457
|
version: '0'
|
458
458
|
requirements: []
|
459
|
-
rubygems_version: 3.
|
459
|
+
rubygems_version: 3.3.3
|
460
460
|
signing_key:
|
461
461
|
specification_version: 4
|
462
462
|
summary: Object-relational mapper framework (part of Rails).
|