activerecord 7.0.4.3 → 7.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -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 +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3039efb205667bcd9fc218b22042ee4a8f36b735f62fedf208a56b70bb3bd5c
|
4
|
+
data.tar.gz: df54f94c2480c583f2236f31de29f55525ee8f281fea93b30690f57f775d758b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a412b99cef7bb68b569f14be355f715f888f0072f33436d40ffe8e4c90c088539d0fd1d26d43e508d5e6a2089ad7a73874f1aef7094bc7dc5287bccca753496b
|
7
|
+
data.tar.gz: 4b6008f67510a941efad31e7cddc4f6af2a7149da4a68cb248ce5481631c674216204d0a0028686c36a8f61f4366b1b2c096c5a6fd8ea61d29884bc57822a0fe
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,100 @@
|
|
1
|
+
## Rails 7.0.5 (May 24, 2023) ##
|
2
|
+
|
3
|
+
* Type cast `#attribute_changed?` `:from` and `:to` options.
|
4
|
+
|
5
|
+
*Andrew Novoselac*
|
6
|
+
|
7
|
+
* Fix `index_exists?` when column is an array.
|
8
|
+
|
9
|
+
*Eileen M. Uchitelle*
|
10
|
+
|
11
|
+
* Handle `Date` objects for PostgreSQL `timestamptz` columns.
|
12
|
+
|
13
|
+
*Alex Ghiculescu*
|
14
|
+
|
15
|
+
* Fix collation for changing column to non-string.
|
16
|
+
|
17
|
+
*Hartley McGuire*
|
18
|
+
|
19
|
+
* Map through subtype in `PostgreSQL::OID::Array`.
|
20
|
+
|
21
|
+
*Jonathan Hefner*
|
22
|
+
|
23
|
+
* Store correct environment in `internal_metadata` when run rails `db:prepare`.
|
24
|
+
|
25
|
+
*fatkodima*
|
26
|
+
|
27
|
+
* Make sure `ActiveRecord::Relation#sum` works with objects that implement `#coerce` without deprecation.
|
28
|
+
|
29
|
+
*Alex Ghiculescu*
|
30
|
+
|
31
|
+
* Fix retrieving foreign keys referencing tables named like keywords in PostgreSQL and MySQL.
|
32
|
+
|
33
|
+
*fatkodima*
|
34
|
+
|
35
|
+
* Support UUIDs in Disable Joins.
|
36
|
+
|
37
|
+
*Samuel Cochran*
|
38
|
+
|
39
|
+
* Fix Active Record's explain for queries starting with comments.
|
40
|
+
|
41
|
+
*fatkodima*
|
42
|
+
|
43
|
+
* Fix incorrectly preloading through association records when middle association has been loaded.
|
44
|
+
|
45
|
+
*Joshua Young*
|
46
|
+
|
47
|
+
* Fix where.missing and where.associated for parent/child associations.
|
48
|
+
|
49
|
+
*fatkodima*
|
50
|
+
|
51
|
+
* Fix Enumerable#in_order_of to preserve duplicates.
|
52
|
+
|
53
|
+
*fatkodima*
|
54
|
+
|
55
|
+
* Fix autoincrement on primary key for mysql.
|
56
|
+
|
57
|
+
*Eileen M. Uchitelle*
|
58
|
+
|
59
|
+
* Restore ability to redefine column in `create_table` for Rails 5.2 migrations.
|
60
|
+
|
61
|
+
*fatkodima*
|
62
|
+
|
63
|
+
* Fix schema cache dumping of virtual columns.
|
64
|
+
|
65
|
+
*fatkodima*
|
66
|
+
|
67
|
+
* Fix Active Record grouped calculations on joined tables on column present in both tables.
|
68
|
+
|
69
|
+
*fatkodima*
|
70
|
+
|
71
|
+
* Fix mutation detection for serialized attributes backed by binary columns.
|
72
|
+
|
73
|
+
*Jean Boussier*
|
74
|
+
|
75
|
+
* Fix a bug where using groups and counts with long table names would return incorrect results.
|
76
|
+
|
77
|
+
*Shota Toguchi*, *Yusaku Ono*
|
78
|
+
|
79
|
+
* Use connection from `#with_raw_connection` in `#quote_string`.
|
80
|
+
|
81
|
+
Prior to this change, virtual datetime columns did not have the same
|
82
|
+
default precision as regular datetime columns, resulting in the following
|
83
|
+
being erroneously equivalent:
|
84
|
+
|
85
|
+
t.virtual :name, type: datetime, as: "expression"
|
86
|
+
t.virtual :name, type: datetime, precision: nil, as: "expression"
|
87
|
+
|
88
|
+
This change fixes the default precision lookup, so virtual and regular
|
89
|
+
datetime column default precisions match.
|
90
|
+
|
91
|
+
*Sam Bostock*
|
92
|
+
|
93
|
+
* Fix a case where the query cache can return wrong values. See #46044
|
94
|
+
|
95
|
+
*Aaron Patterson*
|
96
|
+
|
97
|
+
|
1
98
|
## Rails 7.0.4.3 (March 13, 2023) ##
|
2
99
|
|
3
100
|
* No changes.
|
@@ -17,7 +114,7 @@
|
|
17
114
|
carefully crafted input.
|
18
115
|
|
19
116
|
This commit makes the sanitization more robust by replacing any
|
20
|
-
|
117
|
+
occurrences of "/*" or "*/" with "/ *" or "* /". It also performs a
|
21
118
|
first pass to remove one surrounding comment to avoid compatibility
|
22
119
|
issues for users relying on the existing removal.
|
23
120
|
|
@@ -142,21 +239,21 @@
|
|
142
239
|
|
143
240
|
This adds two new configuration options The configuration options are as
|
144
241
|
follows:
|
145
|
-
|
146
|
-
* `config.
|
147
|
-
|
242
|
+
|
243
|
+
* `config.active_record.use_yaml_unsafe_load`
|
244
|
+
|
148
245
|
When set to true, this configuration option tells Rails to use the old
|
149
246
|
"unsafe" YAML loading strategy, maintaining the existing behavior but leaving
|
150
247
|
the possible escalation vulnerability in place. Setting this option to true
|
151
248
|
is *not* recommended, but can aid in upgrading.
|
152
|
-
|
249
|
+
|
153
250
|
* `config.active_record.yaml_column_permitted_classes`
|
154
|
-
|
251
|
+
|
155
252
|
The "safe YAML" loading method does not allow all classes to be deserialized
|
156
253
|
by default. This option allows you to specify classes deemed "safe" in your
|
157
254
|
application. For example, if your application uses Symbol and Time in
|
158
255
|
serialized data, you can add Symbol and Time to the allowed list as follows:
|
159
|
-
|
256
|
+
|
160
257
|
```
|
161
258
|
config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]
|
162
259
|
```
|
@@ -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
|
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: 2023-
|
11
|
+
date: 2023-05-24 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
|
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
|
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
|
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
|
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.5/activerecord/CHANGELOG.md
|
438
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.5/
|
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/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.4.
|
460
|
-
signing_key:
|
459
|
+
rubygems_version: 3.4.10
|
460
|
+
signing_key:
|
461
461
|
specification_version: 4
|
462
462
|
summary: Object-relational mapper framework (part of Rails).
|
463
463
|
test_files: []
|