activerecord 8.1.0 → 8.1.3
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 +138 -0
- data/lib/active_record/associations/join_dependency.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/base.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +41 -36
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -2
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/enum.rb +2 -2
- data/lib/active_record/future_result.rb +2 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/insert_all.rb +2 -2
- data/lib/active_record/migration/command_recorder.rb +1 -1
- data/lib/active_record/railtie.rb +1 -1
- data/lib/active_record/relation/batches.rb +2 -2
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/where_clause.rb +1 -1
- data/lib/active_record/relation.rb +4 -2
- data/lib/active_record/runtime_registry.rb +1 -0
- data/lib/active_record/schema_dumper.rb +2 -2
- data/lib/active_record/type/json.rb +1 -3
- data/lib/active_record/type/serialized.rb +5 -0
- data/lib/active_record.rb +1 -1
- data/lib/arel/predications.rb +1 -3
- metadata +9 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf11d5e6abc99265d39fb3f4b3b0d87f1e2bbdf6099a478306ba3d04ac2a760a
|
|
4
|
+
data.tar.gz: 4d47ba93fb7a68eb7cbadf3a001bb676b71b87a06b00504907717059c39190b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bcbbfd82d1032400a7f3dfa0784bd5d506107d50d0ada3e1fefd26de665959e1f86cb2aa5f4e7cfbb24e69101e3b71542abd1ecffaa53963823ae47fa4e26475
|
|
7
|
+
data.tar.gz: ce6acb68c3c821dfda84556f5089effcf401cff05b8d819297430b77d51699bf096bc2ed69f78161f9750bd45bbe3ffaa2b591b08d6676dd437e8a9fc06952d4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,141 @@
|
|
|
1
|
+
## Rails 8.1.3 (March 24, 2026) ##
|
|
2
|
+
|
|
3
|
+
* Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
|
|
4
|
+
|
|
5
|
+
*Gabriel Sobrinho*
|
|
6
|
+
|
|
7
|
+
* Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
|
|
8
|
+
|
|
9
|
+
*Hans Schnedlitz*
|
|
10
|
+
|
|
11
|
+
* Restore previous instrumenter after `execute_or_skip`
|
|
12
|
+
|
|
13
|
+
`FutureResult#execute_or_skip` replaces the thread's instrumenter with an
|
|
14
|
+
`EventBuffer` to collect events published during async query execution.
|
|
15
|
+
If the global async executor is saturated and the `caller_runs` fallback
|
|
16
|
+
executes the task on the calling thread, we need to make sure the previous
|
|
17
|
+
instrumenter is restored or the stale `EventBuffer` would stay in place and
|
|
18
|
+
permanently swallow all subsequent `sql.active_record` notifications on
|
|
19
|
+
that thread.
|
|
20
|
+
|
|
21
|
+
*Rosa Gutierrez*
|
|
22
|
+
|
|
23
|
+
* Bump the minimum PostgreSQL version to 9.5, due to usage of `array_position` function.
|
|
24
|
+
|
|
25
|
+
*Ivan Kuchin*
|
|
26
|
+
|
|
27
|
+
* Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
|
|
28
|
+
|
|
29
|
+
*Hammad Khan*
|
|
30
|
+
|
|
31
|
+
* Fix support for table names containing hyphens.
|
|
32
|
+
|
|
33
|
+
*Evgeniy Demin*
|
|
34
|
+
|
|
35
|
+
* Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
|
|
36
|
+
|
|
37
|
+
`Column#==` and `Column#hash` now account for `virtual?` so that the
|
|
38
|
+
`Deduplicable` registry does not treat a generated column and a regular
|
|
39
|
+
column with the same name and type as identical. Previously, if a
|
|
40
|
+
generated column was registered first, a regular column on a different
|
|
41
|
+
table could be deduplicated to the generated instance, silently
|
|
42
|
+
excluding it from INSERT/UPDATE statements.
|
|
43
|
+
|
|
44
|
+
*Jay Huber*
|
|
45
|
+
|
|
46
|
+
* Fix PostgreSQL schema dumping to handle schema-qualified table names in foreign_key references that span different schemas.
|
|
47
|
+
|
|
48
|
+
# before
|
|
49
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs" # emits correctly because they're in the same schema (hst)
|
|
50
|
+
add_foreign_key "hst.event_log_attributes", "hst.usr.user_profiles", column: "created_by_id" # emits hst.user.* when user.* is expected
|
|
51
|
+
|
|
52
|
+
# after
|
|
53
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs"
|
|
54
|
+
add_foreign_key "hst.event_log_attributes", "usr.user_profiles", column: "created_by_id"
|
|
55
|
+
|
|
56
|
+
*Chiperific*
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Rails 8.1.2.1 (March 23, 2026) ##
|
|
60
|
+
|
|
61
|
+
* No changes.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
65
|
+
|
|
66
|
+
* Fix counting cached queries in `ActiveRecord::RuntimeRegistry`.
|
|
67
|
+
|
|
68
|
+
*fatkodima*
|
|
69
|
+
|
|
70
|
+
* Fix merging relations with arel equality predicates with null relations.
|
|
71
|
+
|
|
72
|
+
*fatkodima*
|
|
73
|
+
|
|
74
|
+
* Fix SQLite3 schema dump for non-autoincrement integer primary keys.
|
|
75
|
+
|
|
76
|
+
Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
|
|
77
|
+
primary key.
|
|
78
|
+
|
|
79
|
+
*Chris Hasiński*
|
|
80
|
+
|
|
81
|
+
* Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
|
|
82
|
+
|
|
83
|
+
The `schema_search_path` configured in `database.yml` is now correctly
|
|
84
|
+
reapplied instead of falling back to PostgreSQL defaults.
|
|
85
|
+
|
|
86
|
+
*Tobias Egli*
|
|
87
|
+
|
|
88
|
+
* Restore the ability of enum to be foats.
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
enum :rating, { low: 0.0, medium: 0.5, high: 1.0 },
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
In Rails 8.1.0, enum values are eagerly validated, and floats weren't expected.
|
|
95
|
+
|
|
96
|
+
*Said Kaldybaev*
|
|
97
|
+
|
|
98
|
+
* Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
|
|
99
|
+
|
|
100
|
+
*zzak*, *Stjepan Hadjic*
|
|
101
|
+
|
|
102
|
+
* Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
|
|
103
|
+
|
|
104
|
+
This was the case until Rails 7.2, but starting from 8.0 it
|
|
105
|
+
started mistakenly returning the model class.
|
|
106
|
+
|
|
107
|
+
*Jean Boussier*
|
|
108
|
+
|
|
109
|
+
* Improve PostgreSQLAdapter resilience to Timeout.timeout.
|
|
110
|
+
|
|
111
|
+
Better handle asynchronous exceptions being thrown inside
|
|
112
|
+
the `reconnect!` method.
|
|
113
|
+
|
|
114
|
+
This may fixes some deep errors such as:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
undefined method `key?' for nil:NilClass (NoMethodError)
|
|
118
|
+
if !type_map.key?(oid)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
*Jean Boussier*
|
|
122
|
+
|
|
123
|
+
* Fix structured events for Active Record was not being emitted.
|
|
124
|
+
|
|
125
|
+
*Yuji Yaginuma*
|
|
126
|
+
|
|
127
|
+
* Fix `eager_load` when loading `has_many` assocations with composite primary keys.
|
|
128
|
+
|
|
129
|
+
This would result in some records being loaded multiple times.
|
|
130
|
+
|
|
131
|
+
*Martin-Alexander*
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
135
|
+
|
|
136
|
+
* No changes.
|
|
137
|
+
|
|
138
|
+
|
|
1
139
|
## Rails 8.1.0 (October 22, 2025) ##
|
|
2
140
|
|
|
3
141
|
* Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
|
|
@@ -103,7 +103,7 @@ module ActiveRecord
|
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
def instantiate(result_set, strict_loading_value, &block)
|
|
106
|
-
primary_key = aliases.column_alias(join_root,
|
|
106
|
+
primary_key = Array(join_root.primary_key).map { |column| aliases.column_alias(join_root, column) }
|
|
107
107
|
|
|
108
108
|
seen = Hash.new { |i, parent|
|
|
109
109
|
i[parent] = Hash.new { |j, child_class|
|
|
@@ -141,7 +141,7 @@ module ActiveRecord
|
|
|
141
141
|
|
|
142
142
|
message_bus.instrument("instantiation.active_record", payload) do
|
|
143
143
|
result_set.each { |row_hash|
|
|
144
|
-
parent_key = primary_key ? row_hash
|
|
144
|
+
parent_key = primary_key.empty? ? row_hash : row_hash.values_at(*primary_key)
|
|
145
145
|
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, column_types, &block)
|
|
146
146
|
construct(parent, join_root, row_hash, seen, model_cache, strict_loading_value)
|
|
147
147
|
}
|
|
@@ -38,7 +38,13 @@ module ActiveRecord
|
|
|
38
38
|
attr_reader :loaders
|
|
39
39
|
|
|
40
40
|
def group_and_load_similar(loaders)
|
|
41
|
-
loaders.grep_v(ThroughAssociation)
|
|
41
|
+
non_through = loaders.grep_v(ThroughAssociation)
|
|
42
|
+
|
|
43
|
+
grouped = non_through.group_by do |loader|
|
|
44
|
+
[loader.loader_query, loader.klass]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
grouped.each do |(query, _klass), similar_loaders|
|
|
42
48
|
query.load_records_in_batch(similar_loaders)
|
|
43
49
|
end
|
|
44
50
|
end
|
|
@@ -1030,9 +1030,9 @@ module ActiveRecord
|
|
|
1030
1030
|
# associated records themselves, you can always do something along the lines of
|
|
1031
1031
|
# <tt>person.tasks.each(&:destroy)</tt>.
|
|
1032
1032
|
#
|
|
1033
|
-
# == Deprecated Associations
|
|
1033
|
+
# == Deprecated \Associations
|
|
1034
1034
|
#
|
|
1035
|
-
# Associations can be marked as deprecated by passing <tt>deprecated: true</tt>:
|
|
1035
|
+
# \Associations can be marked as deprecated by passing <tt>deprecated: true</tt>:
|
|
1036
1036
|
#
|
|
1037
1037
|
# has_many :posts, deprecated: true
|
|
1038
1038
|
#
|
data/lib/active_record/base.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "active_support/descendants_tracker"
|
|
|
6
6
|
require "active_support/time"
|
|
7
7
|
require "active_support/core_ext/class/subclasses"
|
|
8
8
|
require "active_record/log_subscriber"
|
|
9
|
+
require "active_record/structured_event_subscriber"
|
|
9
10
|
require "active_record/relation/delegation"
|
|
10
11
|
require "active_record/attributes"
|
|
11
12
|
require "active_record/type_caster"
|
|
@@ -129,7 +129,7 @@ module ActiveRecord
|
|
|
129
129
|
class ConnectionPool
|
|
130
130
|
# Prior to 3.3.5, WeakKeyMap had a use after free bug
|
|
131
131
|
# https://bugs.ruby-lang.org/issues/20688
|
|
132
|
-
if ObjectSpace.const_defined?(:WeakKeyMap) && RUBY_VERSION >= "3.3.5"
|
|
132
|
+
if ObjectSpace.const_defined?(:WeakKeyMap) && Gem::Version.new(RUBY_VERSION) >= "3.3.5"
|
|
133
133
|
WeakThreadKeyMap = ObjectSpace::WeakKeyMap
|
|
134
134
|
else
|
|
135
135
|
class WeakThreadKeyMap # :nodoc:
|
|
@@ -526,7 +526,7 @@ module ActiveRecord
|
|
|
526
526
|
end
|
|
527
527
|
conn.disconnect!
|
|
528
528
|
end
|
|
529
|
-
@connections = []
|
|
529
|
+
@connections = @pinned_connection ? [@pinned_connection] : []
|
|
530
530
|
@leases.clear
|
|
531
531
|
@available.clear
|
|
532
532
|
|
|
@@ -753,7 +753,7 @@ module ActiveRecord
|
|
|
753
753
|
end
|
|
754
754
|
|
|
755
755
|
def extract_table_ref_from_insert_sql(sql)
|
|
756
|
-
if sql =~ /into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
|
|
756
|
+
if sql =~ /into\s("[-A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
|
|
757
757
|
$1.delete('"').strip
|
|
758
758
|
end
|
|
759
759
|
end
|
|
@@ -1604,11 +1604,11 @@ module ActiveRecord
|
|
|
1604
1604
|
non_combinable_operations = []
|
|
1605
1605
|
|
|
1606
1606
|
operations.each do |command, args|
|
|
1607
|
-
|
|
1607
|
+
args.shift # remove table_name
|
|
1608
1608
|
method = :"#{command}_for_alter"
|
|
1609
1609
|
|
|
1610
1610
|
if respond_to?(method, true)
|
|
1611
|
-
sqls, procs = Array(send(method,
|
|
1611
|
+
sqls, procs = Array(send(method, table_name, *args)).partition { |v| v.is_a?(String) }
|
|
1612
1612
|
sql_fragments.concat(sqls)
|
|
1613
1613
|
non_combinable_operations.concat(procs)
|
|
1614
1614
|
else
|
|
@@ -1616,7 +1616,7 @@ module ActiveRecord
|
|
|
1616
1616
|
non_combinable_operations.each(&:call)
|
|
1617
1617
|
sql_fragments = []
|
|
1618
1618
|
non_combinable_operations = []
|
|
1619
|
-
send(command,
|
|
1619
|
+
send(command, table_name, *args)
|
|
1620
1620
|
end
|
|
1621
1621
|
end
|
|
1622
1622
|
|
|
@@ -126,7 +126,7 @@ module ActiveRecord
|
|
|
126
126
|
|
|
127
127
|
# Opens a database console session.
|
|
128
128
|
def self.dbconsole(config, options = {})
|
|
129
|
-
raise NotImplementedError.new("#{self
|
|
129
|
+
raise NotImplementedError.new("#{self} should define `dbconsole` that accepts a db config and options to implement connecting to the db console")
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_options = nil, deprecated_config = nil) # :nodoc:
|
|
@@ -713,37 +713,36 @@ module ActiveRecord
|
|
|
713
713
|
deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
|
|
714
714
|
|
|
715
715
|
@lock.synchronize do
|
|
716
|
-
|
|
716
|
+
attempt_configure_connection do
|
|
717
|
+
@allow_preconnect = false
|
|
717
718
|
|
|
718
|
-
|
|
719
|
+
reconnect
|
|
719
720
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
721
|
+
enable_lazy_transactions!
|
|
722
|
+
@raw_connection_dirty = false
|
|
723
|
+
@last_activity = @connected_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
724
|
+
@verified = true
|
|
725
|
+
@allow_preconnect = true
|
|
726
|
+
|
|
727
|
+
reset_transaction(restore: restore_transactions) do
|
|
728
|
+
clear_cache!(new_connection: true)
|
|
729
|
+
configure_connection
|
|
730
|
+
end
|
|
731
|
+
rescue => original_exception
|
|
732
|
+
translated_exception = translate_exception_class(original_exception, nil, nil)
|
|
733
|
+
retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
733
734
|
|
|
734
|
-
|
|
735
|
-
|
|
735
|
+
if !retry_deadline_exceeded && retries_available > 0
|
|
736
|
+
retries_available -= 1
|
|
736
737
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
738
|
+
if retryable_connection_error?(translated_exception)
|
|
739
|
+
backoff(connection_retries - retries_available)
|
|
740
|
+
retry
|
|
741
|
+
end
|
|
740
742
|
end
|
|
741
|
-
end
|
|
742
|
-
|
|
743
|
-
@last_activity = nil
|
|
744
|
-
@verified = false
|
|
745
743
|
|
|
746
|
-
|
|
744
|
+
raise translated_exception
|
|
745
|
+
end
|
|
747
746
|
end
|
|
748
747
|
end
|
|
749
748
|
|
|
@@ -755,6 +754,8 @@ module ActiveRecord
|
|
|
755
754
|
reset_transaction
|
|
756
755
|
@raw_connection_dirty = false
|
|
757
756
|
@connected_since = nil
|
|
757
|
+
@last_activity = nil
|
|
758
|
+
@verified = false
|
|
758
759
|
end
|
|
759
760
|
end
|
|
760
761
|
|
|
@@ -777,9 +778,11 @@ module ActiveRecord
|
|
|
777
778
|
# should call super immediately after resetting the connection (and while
|
|
778
779
|
# still holding @lock).
|
|
779
780
|
def reset!
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
781
|
+
attempt_configure_connection do
|
|
782
|
+
clear_cache!(new_connection: true)
|
|
783
|
+
reset_transaction
|
|
784
|
+
configure_connection
|
|
785
|
+
end
|
|
783
786
|
end
|
|
784
787
|
|
|
785
788
|
# Removes the connection from the pool and disconnect it.
|
|
@@ -813,12 +816,14 @@ module ActiveRecord
|
|
|
813
816
|
unless active?
|
|
814
817
|
@lock.synchronize do
|
|
815
818
|
if @unconfigured_connection
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
819
|
+
attempt_configure_connection do
|
|
820
|
+
@raw_connection = @unconfigured_connection
|
|
821
|
+
@unconfigured_connection = nil
|
|
822
|
+
configure_connection
|
|
823
|
+
@last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
824
|
+
@verified = true
|
|
825
|
+
@allow_preconnect = true
|
|
826
|
+
end
|
|
822
827
|
return
|
|
823
828
|
end
|
|
824
829
|
|
|
@@ -1282,7 +1287,7 @@ module ActiveRecord
|
|
|
1282
1287
|
end
|
|
1283
1288
|
|
|
1284
1289
|
def attempt_configure_connection
|
|
1285
|
-
|
|
1290
|
+
yield
|
|
1286
1291
|
rescue Exception # Need to handle things such as Timeout::ExitException
|
|
1287
1292
|
disconnect!
|
|
1288
1293
|
raise
|
|
@@ -69,7 +69,8 @@ module ActiveRecord
|
|
|
69
69
|
other.is_a?(Column) &&
|
|
70
70
|
super &&
|
|
71
71
|
identity? == other.identity? &&
|
|
72
|
-
serial? == other.serial?
|
|
72
|
+
serial? == other.serial? &&
|
|
73
|
+
virtual? == other.virtual?
|
|
73
74
|
end
|
|
74
75
|
alias :eql? :==
|
|
75
76
|
|
|
@@ -77,7 +78,8 @@ module ActiveRecord
|
|
|
77
78
|
Column.hash ^
|
|
78
79
|
super.hash ^
|
|
79
80
|
identity?.hash ^
|
|
80
|
-
serial?.hash
|
|
81
|
+
serial?.hash ^
|
|
82
|
+
virtual?.hash
|
|
81
83
|
end
|
|
82
84
|
end
|
|
83
85
|
end
|
|
@@ -395,6 +395,11 @@ module ActiveRecord
|
|
|
395
395
|
end
|
|
396
396
|
end
|
|
397
397
|
|
|
398
|
+
def clear_cache!(new_connection: false)
|
|
399
|
+
super
|
|
400
|
+
@schema_search_path = nil if new_connection
|
|
401
|
+
end
|
|
402
|
+
|
|
398
403
|
# Disconnects from the database if already connected. Otherwise, this
|
|
399
404
|
# method does nothing.
|
|
400
405
|
def disconnect!
|
|
@@ -677,8 +682,8 @@ module ActiveRecord
|
|
|
677
682
|
end
|
|
678
683
|
|
|
679
684
|
def check_version # :nodoc:
|
|
680
|
-
if database_version <
|
|
681
|
-
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.
|
|
685
|
+
if database_version < 9_05_00 # < 9.5
|
|
686
|
+
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.5."
|
|
682
687
|
end
|
|
683
688
|
end
|
|
684
689
|
|
|
@@ -1009,6 +1014,8 @@ module ActiveRecord
|
|
|
1009
1014
|
add_pg_encoders
|
|
1010
1015
|
add_pg_decoders
|
|
1011
1016
|
|
|
1017
|
+
schema_search_path # populate cache
|
|
1018
|
+
|
|
1012
1019
|
reload_type_map
|
|
1013
1020
|
end
|
|
1014
1021
|
|
|
@@ -46,7 +46,9 @@ module ActiveRecord
|
|
|
46
46
|
def ==(other)
|
|
47
47
|
other.is_a?(Column) &&
|
|
48
48
|
super &&
|
|
49
|
-
auto_increment? == other.auto_increment?
|
|
49
|
+
auto_increment? == other.auto_increment? &&
|
|
50
|
+
rowid == other.rowid &&
|
|
51
|
+
generated_type == other.generated_type
|
|
50
52
|
end
|
|
51
53
|
alias :eql? :==
|
|
52
54
|
|
|
@@ -54,8 +56,12 @@ module ActiveRecord
|
|
|
54
56
|
Column.hash ^
|
|
55
57
|
super.hash ^
|
|
56
58
|
auto_increment?.hash ^
|
|
57
|
-
rowid.hash
|
|
59
|
+
rowid.hash ^
|
|
60
|
+
virtual?.hash
|
|
58
61
|
end
|
|
62
|
+
|
|
63
|
+
protected
|
|
64
|
+
attr_reader :generated_type
|
|
59
65
|
end
|
|
60
66
|
end
|
|
61
67
|
end
|
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
|
6
6
|
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
|
7
7
|
private
|
|
8
8
|
def virtual_tables(stream)
|
|
9
|
-
virtual_tables = @connection.virtual_tables
|
|
9
|
+
virtual_tables = @connection.virtual_tables.reject { |name, _| ignored?(name) }
|
|
10
10
|
if virtual_tables.any?
|
|
11
11
|
stream.puts
|
|
12
12
|
stream.puts " # Virtual tables defined in this database."
|
|
@@ -19,11 +19,23 @@ module ActiveRecord
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def default_primary_key?(column)
|
|
22
|
-
schema_type(column) == :integer
|
|
22
|
+
schema_type(column) == :integer && primary_key_has_autoincrement?
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def explicit_primary_key_default?(column)
|
|
26
|
-
column.bigint?
|
|
26
|
+
column.bigint? || (column.type == :integer && !primary_key_has_autoincrement?)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def primary_key_has_autoincrement?
|
|
30
|
+
return false unless table_name
|
|
31
|
+
|
|
32
|
+
table_sql = @connection.query_value(<<~SQL, "SCHEMA")
|
|
33
|
+
SELECT sql FROM sqlite_master WHERE name = #{@connection.quote(table_name)} AND type = 'table'
|
|
34
|
+
UNION ALL
|
|
35
|
+
SELECT sql FROM sqlite_temp_master WHERE name = #{@connection.quote(table_name)} AND type = 'table'
|
|
36
|
+
SQL
|
|
37
|
+
|
|
38
|
+
table_sql.to_s.match?(/\bAUTOINCREMENT\b/i)
|
|
27
39
|
end
|
|
28
40
|
|
|
29
41
|
def prepare_column_options(column)
|
|
@@ -319,7 +319,7 @@ module ActiveRecord
|
|
|
319
319
|
exec_query "DROP INDEX #{quote_column_name(index_name)}"
|
|
320
320
|
end
|
|
321
321
|
|
|
322
|
-
VIRTUAL_TABLE_REGEX = /USING\s+(\w+)\s*\((
|
|
322
|
+
VIRTUAL_TABLE_REGEX = /USING\s+(\w+)\s*\((.*)\)/i
|
|
323
323
|
|
|
324
324
|
# Returns a list of defined virtual tables
|
|
325
325
|
def virtual_tables
|
data/lib/active_record/enum.rb
CHANGED
|
@@ -349,10 +349,10 @@ module ActiveRecord
|
|
|
349
349
|
|
|
350
350
|
values.each_value do |value|
|
|
351
351
|
case value
|
|
352
|
-
when String, Integer, true, false, nil
|
|
352
|
+
when String, Integer, Float, true, false, nil
|
|
353
353
|
# noop
|
|
354
354
|
else
|
|
355
|
-
raise ArgumentError, "Enum values #{values} must be only booleans, integers, symbols or strings, got: #{value.class}"
|
|
355
|
+
raise ArgumentError, "Enum values #{values} must be only booleans, integers, floats, symbols or strings, got: #{value.class}"
|
|
356
356
|
end
|
|
357
357
|
end
|
|
358
358
|
|
|
@@ -105,6 +105,7 @@ module ActiveRecord
|
|
|
105
105
|
|
|
106
106
|
@pool.with_connection do |connection|
|
|
107
107
|
return unless @mutex.try_lock
|
|
108
|
+
previous_instrumenter = ActiveSupport::IsolatedExecutionState[:active_record_instrumenter]
|
|
108
109
|
begin
|
|
109
110
|
if pending?
|
|
110
111
|
@event_buffer = EventBuffer.new(self, @instrumenter)
|
|
@@ -113,6 +114,7 @@ module ActiveRecord
|
|
|
113
114
|
execute_query(connection, async: true)
|
|
114
115
|
end
|
|
115
116
|
ensure
|
|
117
|
+
ActiveSupport::IsolatedExecutionState[:active_record_instrumenter] = previous_instrumenter
|
|
116
118
|
@mutex.unlock
|
|
117
119
|
end
|
|
118
120
|
end
|
|
@@ -39,7 +39,7 @@ module ActiveRecord
|
|
|
39
39
|
@returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
|
|
40
40
|
@returning = false if @returning == []
|
|
41
41
|
|
|
42
|
-
@unique_by = find_unique_index_for(@unique_by)
|
|
42
|
+
@unique_by = find_unique_index_for(@unique_by) if @on_duplicate != :raise
|
|
43
43
|
|
|
44
44
|
configure_on_duplicate_update_logic
|
|
45
45
|
ensure_valid_options_for_connection!
|
|
@@ -48,7 +48,7 @@ module ActiveRecord
|
|
|
48
48
|
def execute
|
|
49
49
|
return ActiveRecord::Result.empty if inserts.empty?
|
|
50
50
|
|
|
51
|
-
message = +"#{model} "
|
|
51
|
+
message = +"#{model.name} "
|
|
52
52
|
message << "Bulk " if inserts.many?
|
|
53
53
|
message << (on_duplicate == :update ? "Upsert" : "Insert")
|
|
54
54
|
connection.exec_insert_all to_sql, message
|
|
@@ -142,7 +142,7 @@ module ActiveRecord
|
|
|
142
142
|
recorder.reverting = @reverting
|
|
143
143
|
yield recorder.delegate.update_table_definition(table_name, recorder)
|
|
144
144
|
commands = recorder.commands
|
|
145
|
-
@commands << [:change_table, [table_name], -> t { bulk_change_table(
|
|
145
|
+
@commands << [:change_table, [table_name], -> t { bulk_change_table(t.name, commands.reverse) }]
|
|
146
146
|
else
|
|
147
147
|
yield delegate.update_table_definition(table_name, self)
|
|
148
148
|
end
|
|
@@ -441,8 +441,8 @@ module ActiveRecord
|
|
|
441
441
|
yielded_relation.load_records(records)
|
|
442
442
|
elsif (empty_scope && use_ranges != false) || use_ranges
|
|
443
443
|
# Efficiently peak at the last value for the next batch using offset and limit.
|
|
444
|
-
values_size = batch_limit
|
|
445
|
-
values_last = batch_relation.offset(
|
|
444
|
+
values_size = remaining ? [batch_limit, remaining].min : batch_limit
|
|
445
|
+
values_last = batch_relation.offset(values_size - 1).pick(*cursor)
|
|
446
446
|
|
|
447
447
|
# If the last value is not found using offset, there is at most one more batch of size < batch_limit.
|
|
448
448
|
# Retry by getting the whole list of remaining values so that we have the exact size and last value.
|
|
@@ -31,7 +31,9 @@ module ActiveRecord
|
|
|
31
31
|
values_predicate
|
|
32
32
|
else
|
|
33
33
|
array_predicates = ranges.map! { |range| predicate_builder.build(attribute, range) }
|
|
34
|
-
|
|
34
|
+
values_predicate.or(
|
|
35
|
+
Arel::Nodes::Grouping.new Arel::Nodes::Or.new(array_predicates)
|
|
36
|
+
)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
|
|
@@ -182,7 +182,7 @@ module ActiveRecord
|
|
|
182
182
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
183
183
|
|
|
184
184
|
predicates.reject do |node|
|
|
185
|
-
if !non_attrs.empty? && node
|
|
185
|
+
if !non_attrs.empty? && equality_node?(node) && node.left.is_a?(Arel::Predications)
|
|
186
186
|
non_attrs.include?(node.left)
|
|
187
187
|
end || Arel.fetch_attribute(node) do |attr|
|
|
188
188
|
attrs.include?(attr) || columns.include?(attr.name.to_s)
|
|
@@ -869,7 +869,9 @@ module ActiveRecord
|
|
|
869
869
|
# Active Record's schema_cache.
|
|
870
870
|
#
|
|
871
871
|
# [:on_duplicate]
|
|
872
|
-
# Configure the
|
|
872
|
+
# Configure the behavior that will be used in case of conflict. Use `:skip`
|
|
873
|
+
# to ignore any conflicts or provide a safe SQL fragment wrapped with
|
|
874
|
+
# `Arel.sql`.
|
|
873
875
|
#
|
|
874
876
|
# NOTE: If you use this option you must provide all the columns you want to update
|
|
875
877
|
# by yourself.
|
|
@@ -1020,7 +1022,7 @@ module ActiveRecord
|
|
|
1020
1022
|
#
|
|
1021
1023
|
# Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
|
|
1022
1024
|
#
|
|
1023
|
-
#
|
|
1025
|
+
# This call deletes the affected posts all at once with a single DELETE statement.
|
|
1024
1026
|
# If you need to destroy dependent associations or call your <tt>before_*</tt> or
|
|
1025
1027
|
# +after_destroy+ callbacks, use the #destroy_all method instead.
|
|
1026
1028
|
#
|
|
@@ -232,8 +232,8 @@ module ActiveRecord
|
|
|
232
232
|
def indexes(table, stream)
|
|
233
233
|
if (indexes = @connection.indexes(table)).any?
|
|
234
234
|
add_index_statements = indexes.map do |index|
|
|
235
|
-
table_name = remove_prefix_and_suffix(index.table)
|
|
236
|
-
" add_index #{([relation_name(table_name)] + index_parts(index)).join(', ')}"
|
|
235
|
+
table_name = remove_prefix_and_suffix(index.table)
|
|
236
|
+
" add_index #{([relation_name(table_name).inspect] + index_parts(index)).join(', ')}"
|
|
237
237
|
end
|
|
238
238
|
|
|
239
239
|
stream.puts add_index_statements.sort.join("\n")
|
|
@@ -25,10 +25,8 @@ module ActiveRecord
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
JSON_ENCODER = ActiveSupport::JSON::Encoding.json_encoder.new(escape: false)
|
|
29
|
-
|
|
30
28
|
def serialize(value)
|
|
31
|
-
|
|
29
|
+
ActiveSupport::JSON::Encoding.encode_without_escape(value) unless value.nil?
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
def changed_in_place?(raw_old_value, new_value)
|
|
@@ -65,6 +65,11 @@ module ActiveRecord
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
private
|
|
68
|
+
# Prevent Ruby 4.0 "delegator does not forward private method" warning.
|
|
69
|
+
# Kernel#inspect calls instance_variables_to_inspect which, without this,
|
|
70
|
+
# triggers Delegator#respond_to_missing? for a private method.
|
|
71
|
+
define_method(:instance_variables_to_inspect, Kernel.instance_method(:instance_variables))
|
|
72
|
+
|
|
68
73
|
def default_value?(value)
|
|
69
74
|
value == coder.load(nil)
|
|
70
75
|
end
|
data/lib/active_record.rb
CHANGED
|
@@ -358,7 +358,7 @@ module ActiveRecord
|
|
|
358
358
|
self.run_after_transaction_callbacks_in_order_defined = false
|
|
359
359
|
|
|
360
360
|
singleton_class.attr_accessor :raise_on_missing_required_finder_order_columns
|
|
361
|
-
self.
|
|
361
|
+
self.raise_on_missing_required_finder_order_columns = false
|
|
362
362
|
|
|
363
363
|
singleton_class.attr_accessor :application_record_class
|
|
364
364
|
self.application_record_class = nil
|
data/lib/arel/predications.rb
CHANGED
|
@@ -231,9 +231,7 @@ module Arel # :nodoc: all
|
|
|
231
231
|
private
|
|
232
232
|
def grouping_any(method_id, others, *extras)
|
|
233
233
|
nodes = others.map { |expr| send(method_id, expr, *extras) }
|
|
234
|
-
Nodes::Grouping.new nodes
|
|
235
|
-
Nodes::Or.new([memo, node])
|
|
236
|
-
}
|
|
234
|
+
Nodes::Grouping.new Nodes::Or.new(nodes)
|
|
237
235
|
end
|
|
238
236
|
|
|
239
237
|
def grouping_all(method_id, others, *extras)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.1.
|
|
4
|
+
version: 8.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 8.1.
|
|
18
|
+
version: 8.1.3
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 8.1.
|
|
25
|
+
version: 8.1.3
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: activemodel
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 8.1.
|
|
32
|
+
version: 8.1.3
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 8.1.
|
|
39
|
+
version: 8.1.3
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: timeout
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -478,10 +478,10 @@ licenses:
|
|
|
478
478
|
- MIT
|
|
479
479
|
metadata:
|
|
480
480
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
|
481
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.1.
|
|
482
|
-
documentation_uri: https://api.rubyonrails.org/v8.1.
|
|
481
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.1.3/activerecord/CHANGELOG.md
|
|
482
|
+
documentation_uri: https://api.rubyonrails.org/v8.1.3/
|
|
483
483
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
|
484
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.1.
|
|
484
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.3/activerecord
|
|
485
485
|
rubygems_mfa_required: 'true'
|
|
486
486
|
rdoc_options:
|
|
487
487
|
- "--main"
|
|
@@ -499,7 +499,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
499
499
|
- !ruby/object:Gem::Version
|
|
500
500
|
version: '0'
|
|
501
501
|
requirements: []
|
|
502
|
-
rubygems_version:
|
|
502
|
+
rubygems_version: 4.0.6
|
|
503
503
|
specification_version: 4
|
|
504
504
|
summary: Object-relational mapper framework (part of Rails).
|
|
505
505
|
test_files: []
|