activerecord 7.1.5.1 → 7.2.0.beta1
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 +515 -2445
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +9 -8
- data/lib/active_record/associations/belongs_to_association.rb +14 -7
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +6 -4
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +29 -28
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +33 -16
- data/lib/active_record/attribute_assignment.rb +1 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +4 -16
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -10
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +60 -71
- data/lib/active_record/attributes.rb +55 -42
- data/lib/active_record/autosave_association.rb +13 -32
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +248 -65
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +159 -74
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/transaction.rb +60 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +18 -46
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +32 -6
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +11 -5
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +5 -23
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -13
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -21
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +107 -75
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +12 -6
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +53 -37
- data/lib/active_record/counter_cache.rb +18 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +15 -4
- data/lib/active_record/database_configurations/hash_config.rb +38 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +24 -0
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +2 -2
- data/lib/active_record/encryption/encrypted_attribute_type.rb +22 -2
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption.rb +0 -2
- data/lib/active_record/enum.rb +10 -1
- data/lib/active_record/errors.rb +16 -11
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +8 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +7 -6
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +5 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +28 -68
- data/lib/active_record/nested_attributes.rb +13 -16
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +30 -352
- data/lib/active_record/query_cache.rb +18 -6
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +50 -62
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +41 -44
- data/lib/active_record/reflection.rb +90 -35
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +94 -61
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +196 -57
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +496 -72
- data/lib/active_record/result.rb +31 -44
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/signed_id.rb +11 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -70
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +81 -91
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +1 -1
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +68 -0
- data/lib/active_record/transactions.rb +43 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +14 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +149 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +29 -16
- data/lib/arel.rb +7 -3
- metadata +20 -15
@@ -110,6 +110,12 @@ module ActiveRecord
|
|
110
110
|
# assert_raise(StandardError) { web_sites(:reddit) }
|
111
111
|
# end
|
112
112
|
#
|
113
|
+
# If the model names conflicts with a +TestCase+ methods, you can use the generic +fixture+ accessor
|
114
|
+
#
|
115
|
+
# test "generic find" do
|
116
|
+
# assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
|
117
|
+
# end
|
118
|
+
#
|
113
119
|
# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
|
114
120
|
# following tests:
|
115
121
|
#
|
@@ -492,8 +498,8 @@ module ActiveRecord
|
|
492
498
|
# # app/models/book_orders.rb
|
493
499
|
# class BookOrder < ApplicationRecord
|
494
500
|
# self.primary_key = [:shop_id, :id]
|
495
|
-
# belongs_to :order,
|
496
|
-
# belongs_to :book,
|
501
|
+
# belongs_to :order, foreign_key: [:shop_id, :order_id]
|
502
|
+
# belongs_to :book, foreign_key: [:author_id, :book_id]
|
497
503
|
# end
|
498
504
|
#
|
499
505
|
# <code></code>
|
@@ -553,24 +559,24 @@ module ActiveRecord
|
|
553
559
|
@@all_cached_fixtures.clear
|
554
560
|
end
|
555
561
|
|
556
|
-
def
|
557
|
-
@@all_cached_fixtures[
|
562
|
+
def cache_for_connection_pool(connection_pool)
|
563
|
+
@@all_cached_fixtures[connection_pool]
|
558
564
|
end
|
559
565
|
|
560
|
-
def fixture_is_cached?(
|
561
|
-
|
566
|
+
def fixture_is_cached?(connection_pool, table_name)
|
567
|
+
cache_for_connection_pool(connection_pool)[table_name]
|
562
568
|
end
|
563
569
|
|
564
|
-
def cached_fixtures(
|
570
|
+
def cached_fixtures(connection_pool, keys_to_fetch = nil)
|
565
571
|
if keys_to_fetch
|
566
|
-
|
572
|
+
cache_for_connection_pool(connection_pool).values_at(*keys_to_fetch)
|
567
573
|
else
|
568
|
-
|
574
|
+
cache_for_connection_pool(connection_pool).values
|
569
575
|
end
|
570
576
|
end
|
571
577
|
|
572
|
-
def cache_fixtures(
|
573
|
-
|
578
|
+
def cache_fixtures(connection_pool, fixtures_map)
|
579
|
+
cache_for_connection_pool(connection_pool).update(fixtures_map)
|
574
580
|
end
|
575
581
|
|
576
582
|
def instantiate_fixtures(object, fixture_set, load_instances = true)
|
@@ -588,15 +594,13 @@ module ActiveRecord
|
|
588
594
|
end
|
589
595
|
end
|
590
596
|
|
591
|
-
def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base
|
597
|
+
def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
|
592
598
|
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
593
599
|
class_names.stringify_keys!
|
594
600
|
|
595
|
-
|
596
|
-
connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
|
597
|
-
|
601
|
+
connection_pool = config.connection_pool
|
598
602
|
fixture_files_to_read = fixture_set_names.reject do |fs_name|
|
599
|
-
fixture_is_cached?(
|
603
|
+
fixture_is_cached?(connection_pool, fs_name)
|
600
604
|
end
|
601
605
|
|
602
606
|
if fixture_files_to_read.any?
|
@@ -604,11 +608,11 @@ module ActiveRecord
|
|
604
608
|
Array(fixtures_directories),
|
605
609
|
fixture_files_to_read,
|
606
610
|
class_names,
|
607
|
-
|
611
|
+
connection_pool,
|
608
612
|
)
|
609
|
-
cache_fixtures(
|
613
|
+
cache_fixtures(connection_pool, fixtures_map)
|
610
614
|
end
|
611
|
-
cached_fixtures(
|
615
|
+
cached_fixtures(connection_pool, fixture_set_names)
|
612
616
|
end
|
613
617
|
|
614
618
|
# Returns a consistent, platform-independent identifier for +label+.
|
@@ -641,7 +645,7 @@ module ActiveRecord
|
|
641
645
|
end
|
642
646
|
|
643
647
|
private
|
644
|
-
def read_and_insert(fixtures_directories, fixture_files, class_names,
|
648
|
+
def read_and_insert(fixtures_directories, fixture_files, class_names, connection_pool) # :nodoc:
|
645
649
|
fixtures_map = {}
|
646
650
|
directory_glob = "{#{fixtures_directories.join(",")}}"
|
647
651
|
fixture_sets = fixture_files.map do |fixture_set_name|
|
@@ -655,21 +659,21 @@ module ActiveRecord
|
|
655
659
|
end
|
656
660
|
update_all_loaded_fixtures(fixtures_map)
|
657
661
|
|
658
|
-
insert(fixture_sets,
|
662
|
+
insert(fixture_sets, connection_pool)
|
659
663
|
|
660
664
|
fixtures_map
|
661
665
|
end
|
662
666
|
|
663
|
-
def insert(fixture_sets,
|
664
|
-
|
667
|
+
def insert(fixture_sets, connection_pool) # :nodoc:
|
668
|
+
fixture_sets_by_pool = fixture_sets.group_by do |fixture_set|
|
665
669
|
if fixture_set.model_class
|
666
|
-
fixture_set.model_class.
|
670
|
+
fixture_set.model_class.connection_pool
|
667
671
|
else
|
668
|
-
|
672
|
+
connection_pool
|
669
673
|
end
|
670
674
|
end
|
671
675
|
|
672
|
-
|
676
|
+
fixture_sets_by_pool.each do |pool, set|
|
673
677
|
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
674
678
|
|
675
679
|
set.each do |fixture_set|
|
@@ -678,13 +682,15 @@ module ActiveRecord
|
|
678
682
|
end
|
679
683
|
end
|
680
684
|
|
681
|
-
|
685
|
+
pool.with_connection do |conn|
|
686
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
682
687
|
|
683
|
-
|
688
|
+
check_all_foreign_keys_valid!(conn)
|
684
689
|
|
685
|
-
|
686
|
-
|
687
|
-
|
690
|
+
# Cap primary key sequences to max(pk).
|
691
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
692
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
693
|
+
end
|
688
694
|
end
|
689
695
|
end
|
690
696
|
end
|
@@ -32,8 +32,11 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
def instrument(name, payload = {}, &block)
|
34
34
|
event = @instrumenter.new_event(name, payload)
|
35
|
-
|
36
|
-
|
35
|
+
begin
|
36
|
+
event.record(&block)
|
37
|
+
ensure
|
38
|
+
@events << event
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def flush
|
@@ -57,7 +60,6 @@ module ActiveRecord
|
|
57
60
|
end
|
58
61
|
|
59
62
|
delegate :empty?, :to_a, to: :result
|
60
|
-
delegate_missing_to :result
|
61
63
|
|
62
64
|
attr_reader :lock_wait
|
63
65
|
|
@@ -140,7 +142,9 @@ module ActiveRecord
|
|
140
142
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
141
143
|
@mutex.synchronize do
|
142
144
|
if pending?
|
143
|
-
|
145
|
+
@pool.with_connection do |connection|
|
146
|
+
execute_query(connection)
|
147
|
+
end
|
144
148
|
else
|
145
149
|
@lock_wait = (Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - start)
|
146
150
|
end
|
@@ -165,7 +165,7 @@ module ActiveRecord
|
|
165
165
|
|
166
166
|
# Returns whether this class is an abstract class or not.
|
167
167
|
def abstract_class?
|
168
|
-
|
168
|
+
@abstract_class == true
|
169
169
|
end
|
170
170
|
|
171
171
|
# Sets the application record class for Active Record
|
@@ -202,7 +202,9 @@ module ActiveRecord
|
|
202
202
|
"The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
|
203
203
|
"This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
|
204
204
|
"Please rename this column if you didn't intend it to be used for storing the inheritance class " \
|
205
|
-
"or overwrite #{name}.inheritance_column to use another column for that information."
|
205
|
+
"or overwrite #{name}.inheritance_column to use another column for that information. " \
|
206
|
+
"If you wish to disable single-table inheritance for #{name} set " \
|
207
|
+
"#{name}.inheritance_column to nil"
|
206
208
|
end
|
207
209
|
|
208
210
|
# Returns the value to be stored in the polymorphic type column for Polymorphic Associations.
|
@@ -7,8 +7,17 @@ module ActiveRecord
|
|
7
7
|
attr_reader :model, :connection, :inserts, :keys
|
8
8
|
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
class << self
|
11
|
+
def execute(relation, ...)
|
12
|
+
relation.model.with_connection do |c|
|
13
|
+
new(relation, c, ...).execute
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
|
19
|
+
@relation = relation
|
20
|
+
@model, @connection, @inserts = relation.model, connection, inserts.map(&:stringify_keys)
|
12
21
|
@on_duplicate, @update_only, @returning, @unique_by = on_duplicate, update_only, returning, unique_by
|
13
22
|
@record_timestamps = record_timestamps.nil? ? model.record_timestamps : record_timestamps
|
14
23
|
|
@@ -23,10 +32,8 @@ module ActiveRecord
|
|
23
32
|
@keys = @inserts.first.keys
|
24
33
|
end
|
25
34
|
|
26
|
-
|
27
|
-
|
28
|
-
@keys |= @scope_attributes.keys
|
29
|
-
end
|
35
|
+
@scope_attributes = relation.scope_for_create.except(@model.inheritance_column)
|
36
|
+
@keys |= @scope_attributes.keys
|
30
37
|
@keys = @keys.to_set
|
31
38
|
|
32
39
|
@returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
|
@@ -52,10 +59,9 @@ module ActiveRecord
|
|
52
59
|
end
|
53
60
|
|
54
61
|
def primary_keys
|
55
|
-
Array(
|
62
|
+
Array(@model.schema_cache.primary_keys(model.table_name))
|
56
63
|
end
|
57
64
|
|
58
|
-
|
59
65
|
def skip_duplicates?
|
60
66
|
on_duplicate == :skip
|
61
67
|
end
|
@@ -67,7 +73,7 @@ module ActiveRecord
|
|
67
73
|
def map_key_with_value
|
68
74
|
inserts.map do |attributes|
|
69
75
|
attributes = attributes.stringify_keys
|
70
|
-
attributes.merge!(scope_attributes)
|
76
|
+
attributes.merge!(@scope_attributes)
|
71
77
|
attributes.reverse_merge!(timestamps_for_create) if record_timestamps?
|
72
78
|
|
73
79
|
verify_attributes(attributes)
|
@@ -92,8 +98,6 @@ module ActiveRecord
|
|
92
98
|
end
|
93
99
|
|
94
100
|
private
|
95
|
-
attr_reader :scope_attributes
|
96
|
-
|
97
101
|
def has_attribute_aliases?(attributes)
|
98
102
|
attributes.keys.any? { |attribute| model.attribute_alias?(attribute) }
|
99
103
|
end
|
@@ -163,10 +167,9 @@ module ActiveRecord
|
|
163
167
|
end
|
164
168
|
|
165
169
|
def unique_indexes
|
166
|
-
|
170
|
+
@model.schema_cache.indexes(model.table_name).select(&:unique)
|
167
171
|
end
|
168
172
|
|
169
|
-
|
170
173
|
def ensure_valid_options_for_connection!
|
171
174
|
if returning && !connection.supports_insert_returning?
|
172
175
|
raise ArgumentError, "#{connection.class} does not support :returning"
|
@@ -192,7 +195,7 @@ module ActiveRecord
|
|
192
195
|
|
193
196
|
|
194
197
|
def readonly_columns
|
195
|
-
primary_keys + model.readonly_attributes
|
198
|
+
primary_keys + model.readonly_attributes
|
196
199
|
end
|
197
200
|
|
198
201
|
def unique_by_columns
|
@@ -301,7 +304,7 @@ module ActiveRecord
|
|
301
304
|
end
|
302
305
|
|
303
306
|
def extract_types_from_columns_on(table_name, keys:)
|
304
|
-
columns =
|
307
|
+
columns = @model.schema_cache.columns_hash(table_name)
|
305
308
|
|
306
309
|
unknown_column = (keys - columns.keys).first
|
307
310
|
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
|
@@ -178,7 +178,10 @@ module ActiveRecord
|
|
178
178
|
def can_use_fast_cache_version?(timestamp)
|
179
179
|
timestamp.is_a?(String) &&
|
180
180
|
cache_timestamp_format == :usec &&
|
181
|
-
|
181
|
+
# FIXME: checking out a connection for this is wasteful
|
182
|
+
# we should store/cache this information in the schema cache
|
183
|
+
# or similar.
|
184
|
+
self.class.with_connection(&:default_timezone) == :utc &&
|
182
185
|
!updated_at_came_from_user?
|
183
186
|
end
|
184
187
|
|
@@ -13,17 +13,13 @@ module ActiveRecord
|
|
13
13
|
class NullInternalMetadata # :nodoc:
|
14
14
|
end
|
15
15
|
|
16
|
-
attr_reader :
|
16
|
+
attr_reader :arel_table
|
17
17
|
|
18
|
-
def initialize(
|
19
|
-
@
|
18
|
+
def initialize(pool)
|
19
|
+
@pool = pool
|
20
20
|
@arel_table = Arel::Table.new(table_name)
|
21
21
|
end
|
22
22
|
|
23
|
-
def enabled?
|
24
|
-
connection.use_metadata_table?
|
25
|
-
end
|
26
|
-
|
27
23
|
def primary_key
|
28
24
|
"key"
|
29
25
|
end
|
@@ -36,50 +32,66 @@ module ActiveRecord
|
|
36
32
|
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{ActiveRecord::Base.table_name_suffix}"
|
37
33
|
end
|
38
34
|
|
35
|
+
def enabled?
|
36
|
+
@pool.db_config.use_metadata_table?
|
37
|
+
end
|
38
|
+
|
39
39
|
def []=(key, value)
|
40
40
|
return unless enabled?
|
41
41
|
|
42
|
-
|
42
|
+
@pool.with_connection do |connection|
|
43
|
+
update_or_create_entry(connection, key, value)
|
44
|
+
end
|
43
45
|
end
|
44
46
|
|
45
47
|
def [](key)
|
46
48
|
return unless enabled?
|
47
49
|
|
48
|
-
|
49
|
-
entry
|
50
|
+
@pool.with_connection do |connection|
|
51
|
+
if entry = select_entry(connection, key)
|
52
|
+
entry[value_key]
|
53
|
+
end
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
57
|
def delete_all_entries
|
54
58
|
dm = Arel::DeleteManager.new(arel_table)
|
55
59
|
|
56
|
-
|
60
|
+
@pool.with_connection do |connection|
|
61
|
+
connection.delete(dm, "#{self.class} Destroy")
|
62
|
+
end
|
57
63
|
end
|
58
64
|
|
59
65
|
def count
|
60
66
|
sm = Arel::SelectManager.new(arel_table)
|
61
67
|
sm.project(*Arel::Nodes::Count.new([Arel.star]))
|
62
68
|
|
63
|
-
|
69
|
+
@pool.with_connection do |connection|
|
70
|
+
connection.select_values(sm, "#{self.class} Count").first
|
71
|
+
end
|
64
72
|
end
|
65
73
|
|
66
74
|
def create_table_and_set_flags(environment, schema_sha1 = nil)
|
67
75
|
return unless enabled?
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
77
|
+
@pool.with_connection do |connection|
|
78
|
+
create_table
|
79
|
+
update_or_create_entry(connection, :environment, environment)
|
80
|
+
update_or_create_entry(connection, :schema_sha1, schema_sha1) if schema_sha1
|
81
|
+
end
|
72
82
|
end
|
73
83
|
|
74
84
|
# Creates an internal metadata table with columns +key+ and +value+
|
75
85
|
def create_table
|
76
86
|
return unless enabled?
|
77
87
|
|
78
|
-
|
79
|
-
connection.
|
80
|
-
|
81
|
-
|
82
|
-
|
88
|
+
@pool.with_connection do |connection|
|
89
|
+
unless connection.table_exists?(table_name)
|
90
|
+
connection.create_table(table_name, id: false) do |t|
|
91
|
+
t.string :key, **connection.internal_string_options_for_primary_key
|
92
|
+
t.string :value
|
93
|
+
t.timestamps
|
94
|
+
end
|
83
95
|
end
|
84
96
|
end
|
85
97
|
end
|
@@ -87,49 +99,51 @@ module ActiveRecord
|
|
87
99
|
def drop_table
|
88
100
|
return unless enabled?
|
89
101
|
|
90
|
-
|
102
|
+
@pool.with_connection do |connection|
|
103
|
+
connection.drop_table table_name, if_exists: true
|
104
|
+
end
|
91
105
|
end
|
92
106
|
|
93
107
|
def table_exists?
|
94
|
-
|
108
|
+
@pool.schema_cache.data_source_exists?(table_name)
|
95
109
|
end
|
96
110
|
|
97
111
|
private
|
98
|
-
def update_or_create_entry(key, value)
|
99
|
-
entry = select_entry(key)
|
112
|
+
def update_or_create_entry(connection, key, value)
|
113
|
+
entry = select_entry(connection, key)
|
100
114
|
|
101
115
|
if entry
|
102
116
|
if entry[value_key] != value
|
103
|
-
update_entry(key, value)
|
117
|
+
update_entry(connection, key, value)
|
104
118
|
else
|
105
119
|
entry[value_key]
|
106
120
|
end
|
107
121
|
else
|
108
|
-
create_entry(key, value)
|
122
|
+
create_entry(connection, key, value)
|
109
123
|
end
|
110
124
|
end
|
111
125
|
|
112
|
-
def current_time
|
126
|
+
def current_time(connection)
|
113
127
|
connection.default_timezone == :utc ? Time.now.utc : Time.now
|
114
128
|
end
|
115
129
|
|
116
|
-
def create_entry(key, value)
|
130
|
+
def create_entry(connection, key, value)
|
117
131
|
im = Arel::InsertManager.new(arel_table)
|
118
132
|
im.insert [
|
119
133
|
[arel_table[primary_key], key],
|
120
134
|
[arel_table[value_key], value],
|
121
|
-
[arel_table[:created_at], current_time],
|
122
|
-
[arel_table[:updated_at], current_time]
|
135
|
+
[arel_table[:created_at], current_time(connection)],
|
136
|
+
[arel_table[:updated_at], current_time(connection)]
|
123
137
|
]
|
124
138
|
|
125
139
|
connection.insert(im, "#{self.class} Create", primary_key, key)
|
126
140
|
end
|
127
141
|
|
128
|
-
def update_entry(key, new_value)
|
142
|
+
def update_entry(connection, key, new_value)
|
129
143
|
um = Arel::UpdateManager.new(arel_table)
|
130
144
|
um.set [
|
131
145
|
[arel_table[value_key], new_value],
|
132
|
-
[arel_table[:updated_at], current_time]
|
146
|
+
[arel_table[:updated_at], current_time(connection)]
|
133
147
|
]
|
134
148
|
|
135
149
|
um.where(arel_table[primary_key].eq(key))
|
@@ -137,9 +151,9 @@ module ActiveRecord
|
|
137
151
|
connection.update(um, "#{self.class} Update")
|
138
152
|
end
|
139
153
|
|
140
|
-
def select_entry(key)
|
154
|
+
def select_entry(connection, key)
|
141
155
|
sm = Arel::SelectManager.new(arel_table)
|
142
|
-
sm.project(Arel::Nodes::SqlLiteral.new("*"))
|
156
|
+
sm.project(Arel::Nodes::SqlLiteral.new("*", retryable: true))
|
143
157
|
sm.where(arel_table[primary_key].eq(Arel::Nodes::BindParam.new(key)))
|
144
158
|
sm.order(arel_table[primary_key].asc)
|
145
159
|
sm.limit = 1
|
@@ -182,14 +182,15 @@ module ActiveRecord
|
|
182
182
|
super
|
183
183
|
end
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
185
|
+
private
|
186
|
+
def hook_attribute_type(name, cast_type)
|
187
|
+
if lock_optimistically && name == locking_column
|
188
|
+
cast_type = LockingType.new(cast_type)
|
189
|
+
end
|
190
|
+
|
191
|
+
super
|
188
192
|
end
|
189
|
-
super
|
190
|
-
end
|
191
193
|
|
192
|
-
private
|
193
194
|
def inherited(base)
|
194
195
|
super
|
195
196
|
base.class_eval do
|
@@ -6,27 +6,6 @@ module ActiveRecord
|
|
6
6
|
|
7
7
|
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
8
8
|
|
9
|
-
def self.runtime=(value)
|
10
|
-
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
11
|
-
ActiveRecord::LogSubscriber.runtime= is deprecated and will be removed in Rails 7.2.
|
12
|
-
MSG
|
13
|
-
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.runtime
|
17
|
-
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
18
|
-
ActiveRecord::LogSubscriber.runtime is deprecated and will be removed in Rails 7.2.
|
19
|
-
MSG
|
20
|
-
ActiveRecord::RuntimeRegistry.sql_runtime
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.reset_runtime
|
24
|
-
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
25
|
-
ActiveRecord::LogSubscriber.reset_runtime is deprecated and will be removed in Rails 7.2.
|
26
|
-
MSG
|
27
|
-
ActiveRecord::RuntimeRegistry.reset
|
28
|
-
end
|
29
|
-
|
30
9
|
def strict_loading_violation(event)
|
31
10
|
debug do
|
32
11
|
owner = event.payload[:owner]
|
@@ -25,10 +25,7 @@ module ActiveRecord
|
|
25
25
|
payload = [attributes_for_database, new_record?]
|
26
26
|
|
27
27
|
cached_associations = self.class.reflect_on_all_associations.select do |reflection|
|
28
|
-
|
29
|
-
association = association(reflection.name)
|
30
|
-
association.loaded? || association.target.present?
|
31
|
-
end
|
28
|
+
association_cached?(reflection.name) && association(reflection.name).loaded?
|
32
29
|
end
|
33
30
|
|
34
31
|
unless cached_associations.empty?
|
@@ -79,7 +79,7 @@ module ActiveRecord
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def add_cached_associations(record, entry)
|
82
|
-
record.class.
|
82
|
+
record.class.normalized_reflections.each_value do |reflection|
|
83
83
|
if record.association_cached?(reflection.name) && record.association(reflection.name).loaded?
|
84
84
|
entry << reflection.name << encode(record.association(reflection.name).target)
|
85
85
|
end
|
@@ -377,14 +377,13 @@ module ActiveRecord
|
|
377
377
|
end
|
378
378
|
|
379
379
|
# Forwards any missing method call to the \target.
|
380
|
-
def method_missing(method,
|
380
|
+
def method_missing(method, ...)
|
381
381
|
if delegate.respond_to?(method)
|
382
|
-
delegate.public_send(method,
|
382
|
+
delegate.public_send(method, ...)
|
383
383
|
else
|
384
384
|
super
|
385
385
|
end
|
386
386
|
end
|
387
|
-
ruby2_keywords(:method_missing)
|
388
387
|
end
|
389
388
|
end
|
390
389
|
end
|
@@ -21,8 +21,7 @@ module ActiveRecord
|
|
21
21
|
# New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
|
22
22
|
#
|
23
23
|
# There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
|
24
|
-
# 7.0 < 7.1
|
25
|
-
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1
|
24
|
+
# 5.2 < 6.0 < 6.1 < 7.0 < 7.1 < 7.2
|
26
25
|
#
|
27
26
|
# If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
|
28
27
|
# find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
|
@@ -30,7 +29,10 @@ module ActiveRecord
|
|
30
29
|
# For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
|
31
30
|
# class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
|
32
31
|
# for migrations written for 5.2, but will for migrations written for 6.0.
|
33
|
-
|
32
|
+
V7_2 = Current
|
33
|
+
|
34
|
+
class V7_1 < V7_2
|
35
|
+
end
|
34
36
|
|
35
37
|
class V7_0 < V7_1
|
36
38
|
module LegacyIndexName
|
@@ -6,13 +6,12 @@ module ActiveRecord
|
|
6
6
|
# to the connection adapter.
|
7
7
|
class DefaultStrategy < ExecutionStrategy # :nodoc:
|
8
8
|
private
|
9
|
-
def method_missing(method,
|
10
|
-
connection.send(method,
|
9
|
+
def method_missing(method, ...)
|
10
|
+
connection.send(method, ...)
|
11
11
|
end
|
12
|
-
ruby2_keywords(:method_missing)
|
13
12
|
|
14
|
-
def respond_to_missing?(method,
|
15
|
-
connection.respond_to?(method) || super
|
13
|
+
def respond_to_missing?(method, include_private = false)
|
14
|
+
connection.respond_to?(method, include_private) || super
|
16
15
|
end
|
17
16
|
|
18
17
|
def connection
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class PendingMigrationConnection # :nodoc:
|
5
|
-
def self.
|
5
|
+
def self.with_temporary_pool(db_config, &block)
|
6
6
|
pool = ActiveRecord::Base.connection_handler.establish_connection(db_config, owner_name: self)
|
7
7
|
|
8
|
-
yield pool
|
8
|
+
yield pool
|
9
9
|
ensure
|
10
10
|
ActiveRecord::Base.connection_handler.remove_connection_pool(self.name)
|
11
11
|
end
|