activerecord 7.2.1.1 → 8.0.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 +188 -791
- data/README.rdoc +1 -1
- data/lib/active_record/associations/association.rb +25 -5
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +4 -4
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +34 -4
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_assignment.rb +9 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -0
- data/lib/active_record/attributes.rb +1 -2
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +12 -4
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +26 -5
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +24 -25
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +20 -38
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -8
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +50 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +38 -90
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -12
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +0 -17
- data/lib/active_record/connection_handling.rb +22 -0
- data/lib/active_record/core.rb +14 -7
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -1
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +10 -1
- data/lib/active_record/encryption/encryptor.rb +15 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/encryption.rb +2 -0
- data/lib/active_record/enum.rb +7 -10
- data/lib/active_record/errors.rb +13 -5
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +22 -5
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +35 -33
- data/lib/active_record/model_schema.rb +2 -3
- data/lib/active_record/nested_attributes.rb +11 -2
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_logs.rb +97 -39
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +6 -6
- data/lib/active_record/railtie.rb +8 -14
- data/lib/active_record/reflection.rb +9 -4
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +24 -19
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +18 -18
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +6 -1
- data/lib/active_record/relation/query_methods.rb +58 -37
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation.rb +72 -61
- data/lib/active_record/result.rb +68 -7
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +5 -0
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +36 -16
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +9 -8
- data/lib/active_record.rb +15 -0
- data/lib/arel/collectors/bind.rb +1 -1
- metadata +10 -10
@@ -248,18 +248,16 @@ module ActiveRecord
|
|
248
248
|
|
249
249
|
im = Arel::InsertManager.new(arel_table)
|
250
250
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
im.insert(values.transform_keys { |name| arel_table[name] })
|
256
|
-
end
|
257
|
-
|
258
|
-
connection.insert(
|
259
|
-
im, "#{self} Create", primary_key || false, primary_key_value,
|
260
|
-
returning: returning
|
261
|
-
)
|
251
|
+
if values.empty?
|
252
|
+
im.insert(connection.empty_insert_statement_value(primary_key))
|
253
|
+
else
|
254
|
+
im.insert(values.transform_keys { |name| arel_table[name] })
|
262
255
|
end
|
256
|
+
|
257
|
+
connection.insert(
|
258
|
+
im, "#{self} Create", primary_key || false, primary_key_value,
|
259
|
+
returning: returning
|
260
|
+
)
|
263
261
|
end
|
264
262
|
|
265
263
|
def _update_record(values, constraints) # :nodoc:
|
@@ -812,159 +810,159 @@ module ActiveRecord
|
|
812
810
|
end
|
813
811
|
end
|
814
812
|
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
813
|
+
private
|
814
|
+
def init_internals
|
815
|
+
super
|
816
|
+
@_trigger_destroy_callback = @_trigger_update_callback = nil
|
817
|
+
@previously_new_record = false
|
818
|
+
end
|
821
819
|
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
820
|
+
def strict_loaded_associations
|
821
|
+
@association_cache.find_all do |_, assoc|
|
822
|
+
assoc.owner.strict_loading? && !assoc.owner.strict_loading_n_plus_one_only?
|
823
|
+
end.map(&:first)
|
824
|
+
end
|
827
825
|
|
828
|
-
|
829
|
-
|
830
|
-
|
826
|
+
def _find_record(options)
|
827
|
+
all_queries = options ? options[:all_queries] : nil
|
828
|
+
base = self.class.all(all_queries: all_queries).preload(strict_loaded_associations)
|
831
829
|
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
830
|
+
if options && options[:lock]
|
831
|
+
base.lock(options[:lock]).find_by!(_in_memory_query_constraints_hash)
|
832
|
+
else
|
833
|
+
base.find_by!(_in_memory_query_constraints_hash)
|
834
|
+
end
|
836
835
|
end
|
837
|
-
end
|
838
836
|
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
837
|
+
def _in_memory_query_constraints_hash
|
838
|
+
if self.class.query_constraints_list.nil?
|
839
|
+
{ @primary_key => id }
|
840
|
+
else
|
841
|
+
self.class.query_constraints_list.index_with do |column_name|
|
842
|
+
attribute(column_name)
|
843
|
+
end
|
845
844
|
end
|
846
845
|
end
|
847
|
-
end
|
848
846
|
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
847
|
+
def apply_scoping?(options)
|
848
|
+
!(options && options[:unscoped]) &&
|
849
|
+
(self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
|
850
|
+
end
|
853
851
|
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
852
|
+
def _query_constraints_hash
|
853
|
+
if self.class.query_constraints_list.nil?
|
854
|
+
{ @primary_key => id_in_database }
|
855
|
+
else
|
856
|
+
self.class.query_constraints_list.index_with do |column_name|
|
857
|
+
attribute_in_database(column_name)
|
858
|
+
end
|
860
859
|
end
|
861
860
|
end
|
862
|
-
end
|
863
861
|
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
def destroy_row
|
869
|
-
_delete_row
|
870
|
-
end
|
871
|
-
|
872
|
-
def _delete_row
|
873
|
-
self.class._delete_record(_query_constraints_hash)
|
874
|
-
end
|
862
|
+
# A hook to be overridden by association modules.
|
863
|
+
def destroy_associations
|
864
|
+
end
|
875
865
|
|
876
|
-
|
877
|
-
|
866
|
+
def destroy_row
|
867
|
+
_delete_row
|
868
|
+
end
|
878
869
|
|
879
|
-
|
880
|
-
|
870
|
+
def _delete_row
|
871
|
+
self.class._delete_record(_query_constraints_hash)
|
881
872
|
end
|
882
873
|
|
883
|
-
|
884
|
-
|
874
|
+
def _touch_row(attribute_names, time)
|
875
|
+
time ||= current_time_from_proper_timezone
|
885
876
|
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
_query_constraints_hash
|
890
|
-
)
|
891
|
-
end
|
877
|
+
attribute_names.each do |attr_name|
|
878
|
+
_write_attribute(attr_name, time)
|
879
|
+
end
|
892
880
|
|
893
|
-
|
894
|
-
|
895
|
-
return false if destroyed?
|
896
|
-
result = new_record? ? _create_record(&block) : _update_record(&block)
|
897
|
-
result != false
|
898
|
-
end
|
881
|
+
_update_row(attribute_names, "touch")
|
882
|
+
end
|
899
883
|
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
884
|
+
def _update_row(attribute_names, attempted_action = "update")
|
885
|
+
self.class._update_record(
|
886
|
+
attributes_with_values(attribute_names),
|
887
|
+
_query_constraints_hash
|
888
|
+
)
|
889
|
+
end
|
904
890
|
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
@_trigger_update_callback = affected_rows == 1
|
891
|
+
def create_or_update(**, &block)
|
892
|
+
_raise_readonly_record_error if readonly?
|
893
|
+
return false if destroyed?
|
894
|
+
result = new_record? ? _create_record(&block) : _update_record(&block)
|
895
|
+
result != false
|
911
896
|
end
|
912
897
|
|
913
|
-
|
898
|
+
# Updates the associated record with values matching those of the instance attributes.
|
899
|
+
# Returns the number of affected rows.
|
900
|
+
def _update_record(attribute_names = self.attribute_names)
|
901
|
+
attribute_names = attributes_for_update(attribute_names)
|
914
902
|
|
915
|
-
|
903
|
+
if attribute_names.empty?
|
904
|
+
affected_rows = 0
|
905
|
+
@_trigger_update_callback = true
|
906
|
+
else
|
907
|
+
affected_rows = _update_row(attribute_names)
|
908
|
+
@_trigger_update_callback = affected_rows == 1
|
909
|
+
end
|
916
910
|
|
917
|
-
|
918
|
-
end
|
911
|
+
@previously_new_record = false
|
919
912
|
|
920
|
-
|
921
|
-
# and returns its id.
|
922
|
-
def _create_record(attribute_names = self.attribute_names)
|
923
|
-
attribute_names = attributes_for_create(attribute_names)
|
913
|
+
yield(self) if block_given?
|
924
914
|
|
925
|
-
|
926
|
-
|
915
|
+
affected_rows
|
916
|
+
end
|
927
917
|
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
)
|
918
|
+
# Creates a record with values matching those of the instance attributes
|
919
|
+
# and returns its id.
|
920
|
+
def _create_record(attribute_names = self.attribute_names)
|
921
|
+
attribute_names = attributes_for_create(attribute_names)
|
933
922
|
|
934
|
-
|
935
|
-
|
936
|
-
end if returning_values
|
937
|
-
end
|
923
|
+
self.class.with_connection do |connection|
|
924
|
+
returning_columns = self.class._returning_columns_for_insert(connection)
|
938
925
|
|
939
|
-
|
940
|
-
|
926
|
+
returning_values = self.class._insert_record(
|
927
|
+
connection,
|
928
|
+
attributes_with_values(attribute_names),
|
929
|
+
returning_columns
|
930
|
+
)
|
941
931
|
|
942
|
-
|
932
|
+
returning_columns.zip(returning_values).each do |column, value|
|
933
|
+
_write_attribute(column, value) if !_read_attribute(column)
|
934
|
+
end if returning_values
|
935
|
+
end
|
943
936
|
|
944
|
-
|
945
|
-
|
937
|
+
@new_record = false
|
938
|
+
@previously_new_record = true
|
946
939
|
|
947
|
-
|
948
|
-
raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
|
949
|
-
end
|
940
|
+
yield(self) if block_given?
|
950
941
|
|
951
|
-
|
952
|
-
|
953
|
-
key = self.class.primary_key
|
954
|
-
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
|
955
|
-
ensure
|
956
|
-
@_association_destroy_exception = nil
|
957
|
-
end
|
942
|
+
id
|
943
|
+
end
|
958
944
|
|
959
|
-
|
960
|
-
|
961
|
-
|
945
|
+
def verify_readonly_attribute(name)
|
946
|
+
raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attribute?(name)
|
947
|
+
end
|
962
948
|
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
949
|
+
def _raise_record_not_destroyed
|
950
|
+
@_association_destroy_exception ||= nil
|
951
|
+
key = self.class.primary_key
|
952
|
+
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
|
953
|
+
ensure
|
954
|
+
@_association_destroy_exception = nil
|
955
|
+
end
|
956
|
+
|
957
|
+
def _raise_readonly_record_error
|
958
|
+
raise ReadOnlyRecord, "#{self.class} is marked as readonly"
|
959
|
+
end
|
960
|
+
|
961
|
+
def _raise_record_not_touched_error
|
962
|
+
raise ActiveRecordError, <<~MSG.squish
|
963
|
+
Cannot touch on a new or destroyed record object. Consider using
|
964
|
+
persisted?, new_record?, or destroyed? before touching.
|
965
|
+
MSG
|
966
|
+
end
|
969
967
|
end
|
970
968
|
end
|
@@ -72,14 +72,70 @@ module ActiveRecord
|
|
72
72
|
#
|
73
73
|
# config.active_record.cache_query_log_tags = true
|
74
74
|
module QueryLogs
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
class GetKeyHandler # :nodoc:
|
76
|
+
def initialize(name)
|
77
|
+
@name = name
|
78
|
+
end
|
79
|
+
|
80
|
+
def call(context)
|
81
|
+
context[@name]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class IdentityHandler # :nodoc:
|
86
|
+
def initialize(value)
|
87
|
+
@value = value
|
88
|
+
end
|
89
|
+
|
90
|
+
def call(_context)
|
91
|
+
@value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class ZeroArityHandler # :nodoc:
|
96
|
+
def initialize(proc)
|
97
|
+
@proc = proc
|
98
|
+
end
|
99
|
+
|
100
|
+
def call(_context)
|
101
|
+
@proc.call
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
@taggings = {}.freeze
|
106
|
+
@tags = [ :application ].freeze
|
107
|
+
@prepend_comment = false
|
108
|
+
@cache_query_log_tags = false
|
109
|
+
@tags_formatter = false
|
110
|
+
|
80
111
|
thread_mattr_accessor :cached_comment, instance_accessor: false
|
81
112
|
|
82
113
|
class << self
|
114
|
+
attr_reader :tags, :taggings, :tags_formatter # :nodoc:
|
115
|
+
attr_accessor :prepend_comment, :cache_query_log_tags # :nodoc:
|
116
|
+
|
117
|
+
def taggings=(taggings) # :nodoc:
|
118
|
+
@taggings = taggings.freeze
|
119
|
+
@handlers = rebuild_handlers
|
120
|
+
end
|
121
|
+
|
122
|
+
def tags=(tags) # :nodoc:
|
123
|
+
@tags = tags.freeze
|
124
|
+
@handlers = rebuild_handlers
|
125
|
+
end
|
126
|
+
|
127
|
+
def tags_formatter=(format) # :nodoc:
|
128
|
+
@formatter = case format
|
129
|
+
when :legacy
|
130
|
+
LegacyFormatter
|
131
|
+
when :sqlcommenter
|
132
|
+
SQLCommenter
|
133
|
+
else
|
134
|
+
raise ArgumentError, "Formatter is unsupported: #{format}"
|
135
|
+
end
|
136
|
+
@tags_formatter = format
|
137
|
+
end
|
138
|
+
|
83
139
|
def call(sql, connection) # :nodoc:
|
84
140
|
comment = self.comment(connection)
|
85
141
|
|
@@ -96,19 +152,6 @@ module ActiveRecord
|
|
96
152
|
self.cached_comment = nil
|
97
153
|
end
|
98
154
|
|
99
|
-
# Updates the formatter to be what the passed in format is.
|
100
|
-
def update_formatter(format)
|
101
|
-
self.tags_formatter =
|
102
|
-
case format
|
103
|
-
when :legacy
|
104
|
-
LegacyFormatter.new
|
105
|
-
when :sqlcommenter
|
106
|
-
SQLCommenter.new
|
107
|
-
else
|
108
|
-
raise ArgumentError, "Formatter is unsupported: #{formatter}"
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
155
|
if Thread.respond_to?(:each_caller_location)
|
113
156
|
def query_source_location # :nodoc:
|
114
157
|
Thread.each_caller_location do |location|
|
@@ -126,6 +169,35 @@ module ActiveRecord
|
|
126
169
|
ActiveSupport::ExecutionContext.after_change { ActiveRecord::QueryLogs.clear_cache }
|
127
170
|
|
128
171
|
private
|
172
|
+
def rebuild_handlers
|
173
|
+
handlers = []
|
174
|
+
@tags.each do |i|
|
175
|
+
if i.is_a?(Hash)
|
176
|
+
i.each do |k, v|
|
177
|
+
handlers << [k, build_handler(k, v)]
|
178
|
+
end
|
179
|
+
else
|
180
|
+
handlers << [i, build_handler(i)]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
handlers.sort_by! { |(key, _)| key.to_s }
|
184
|
+
end
|
185
|
+
|
186
|
+
def build_handler(name, handler = nil)
|
187
|
+
handler ||= @taggings[name]
|
188
|
+
if handler.nil?
|
189
|
+
GetKeyHandler.new(name)
|
190
|
+
elsif handler.respond_to?(:call)
|
191
|
+
if handler.arity == 0
|
192
|
+
ZeroArityHandler.new(handler)
|
193
|
+
else
|
194
|
+
handler
|
195
|
+
end
|
196
|
+
else
|
197
|
+
IdentityHandler.new(handler)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
129
201
|
# Returns an SQL comment +String+ containing the query log tags.
|
130
202
|
# Sets and returns a cached comment if <tt>cache_query_log_tags</tt> is +true+.
|
131
203
|
def comment(connection)
|
@@ -136,10 +208,6 @@ module ActiveRecord
|
|
136
208
|
end
|
137
209
|
end
|
138
210
|
|
139
|
-
def formatter
|
140
|
-
self.tags_formatter || self.update_formatter(:legacy)
|
141
|
-
end
|
142
|
-
|
143
211
|
def uncached_comment(connection)
|
144
212
|
content = tag_content(connection)
|
145
213
|
|
@@ -165,25 +233,15 @@ module ActiveRecord
|
|
165
233
|
context = ActiveSupport::ExecutionContext.to_h
|
166
234
|
context[:connection] ||= connection
|
167
235
|
|
168
|
-
pairs =
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
val = if handler.nil?
|
173
|
-
context[key]
|
174
|
-
elsif handler.respond_to?(:call)
|
175
|
-
if handler.arity == 0
|
176
|
-
handler.call
|
177
|
-
else
|
178
|
-
handler.call(context)
|
179
|
-
end
|
180
|
-
else
|
181
|
-
handler
|
182
|
-
end
|
183
|
-
[key, val] unless val.nil?
|
236
|
+
pairs = @handlers.filter_map do |(key, handler)|
|
237
|
+
val = handler.call(context)
|
238
|
+
@formatter.format(key, val) unless val.nil?
|
184
239
|
end
|
185
|
-
|
240
|
+
@formatter.join(pairs)
|
186
241
|
end
|
187
242
|
end
|
243
|
+
|
244
|
+
@handlers = rebuild_handlers
|
245
|
+
self.tags_formatter = :legacy
|
188
246
|
end
|
189
247
|
end
|
@@ -2,40 +2,29 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module QueryLogs
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# Formats the key value pairs into a string.
|
11
|
-
def format(pairs)
|
12
|
-
pairs.map! do |key, value|
|
13
|
-
"#{key}#{key_value_separator}#{format_value(value)}"
|
14
|
-
end.join(",")
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
attr_reader :key_value_separator
|
19
|
-
|
20
|
-
def format_value(value)
|
21
|
-
value
|
5
|
+
module LegacyFormatter # :nodoc:
|
6
|
+
class << self
|
7
|
+
# Formats the key value pairs into a string.
|
8
|
+
def format(key, value)
|
9
|
+
"#{key}:#{value}"
|
22
10
|
end
|
23
|
-
end
|
24
11
|
|
25
|
-
|
26
|
-
|
27
|
-
|
12
|
+
def join(pairs)
|
13
|
+
pairs.join(",")
|
14
|
+
end
|
28
15
|
end
|
16
|
+
end
|
29
17
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
18
|
+
class SQLCommenter # :nodoc:
|
19
|
+
class << self
|
20
|
+
def format(key, value)
|
21
|
+
"#{key}='#{ERB::Util.url_encode(value)}'"
|
22
|
+
end
|
34
23
|
|
35
|
-
|
36
|
-
|
37
|
-
"'#{ERB::Util.url_encode(value)}'"
|
24
|
+
def join(pairs)
|
25
|
+
pairs.join(",")
|
38
26
|
end
|
27
|
+
end
|
39
28
|
end
|
40
29
|
end
|
41
30
|
end
|
@@ -56,12 +56,10 @@ module ActiveRecord
|
|
56
56
|
end
|
57
57
|
|
58
58
|
# Same as <tt>#find_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
|
59
|
-
def async_find_by_sql(sql, binds = [], preparable: nil, &block)
|
60
|
-
|
61
|
-
_query_by_sql(c, sql, binds, preparable: preparable, async: true)
|
62
|
-
end
|
63
|
-
|
64
|
-
result.then do |result|
|
59
|
+
def async_find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
|
60
|
+
with_connection do |c|
|
61
|
+
_query_by_sql(c, sql, binds, preparable: preparable, allow_retry: allow_retry, async: true)
|
62
|
+
end.then do |result|
|
65
63
|
_load_from_sql(result, &block)
|
66
64
|
end
|
67
65
|
end
|
@@ -71,6 +69,8 @@ module ActiveRecord
|
|
71
69
|
end
|
72
70
|
|
73
71
|
def _load_from_sql(result_set, &block) # :nodoc:
|
72
|
+
return [] if result_set.empty?
|
73
|
+
|
74
74
|
column_types = result_set.column_types
|
75
75
|
|
76
76
|
unless column_types.empty?
|
@@ -69,6 +69,7 @@ module ActiveRecord
|
|
69
69
|
Rails.logger.broadcast_to(console)
|
70
70
|
end
|
71
71
|
ActiveRecord.verbose_query_logs = false
|
72
|
+
ActiveRecord::Base.attributes_for_inspect = :all if Rails.env.production?
|
72
73
|
end
|
73
74
|
|
74
75
|
runner do
|
@@ -356,16 +357,19 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
356
357
|
end
|
357
358
|
|
358
359
|
initializer "active_record_encryption.configuration" do |app|
|
359
|
-
ActiveSupport.on_load(:
|
360
|
-
ActiveRecord::Encryption.configure
|
360
|
+
ActiveSupport.on_load(:active_record_encryption) do
|
361
|
+
ActiveRecord::Encryption.configure(
|
361
362
|
primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
|
362
363
|
deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
|
363
364
|
key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
|
364
365
|
**app.config.active_record.encryption
|
366
|
+
)
|
365
367
|
|
366
368
|
auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
|
367
369
|
auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
|
370
|
+
end
|
368
371
|
|
372
|
+
ActiveSupport.on_load(:active_record) do
|
369
373
|
# Support extended queries for deterministic attributes and validations
|
370
374
|
if ActiveRecord::Encryption.config.extend_queries
|
371
375
|
ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
|
@@ -385,7 +389,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
385
389
|
config.after_initialize do
|
386
390
|
if app.config.active_record.query_log_tags_enabled
|
387
391
|
ActiveRecord.query_transformers << ActiveRecord::QueryLogs
|
388
|
-
ActiveRecord::QueryLogs.taggings.merge
|
392
|
+
ActiveRecord::QueryLogs.taggings = ActiveRecord::QueryLogs.taggings.merge(
|
389
393
|
application: Rails.application.class.name.split("::").first,
|
390
394
|
pid: -> { Process.pid.to_s },
|
391
395
|
socket: ->(context) { context[:connection].pool.db_config.socket },
|
@@ -400,7 +404,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
400
404
|
end
|
401
405
|
|
402
406
|
if app.config.active_record.query_log_tags_format
|
403
|
-
ActiveRecord::QueryLogs.
|
407
|
+
ActiveRecord::QueryLogs.tags_formatter = app.config.active_record.query_log_tags_format
|
404
408
|
end
|
405
409
|
|
406
410
|
if app.config.active_record.cache_query_log_tags
|
@@ -432,15 +436,5 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
432
436
|
end
|
433
437
|
end
|
434
438
|
end
|
435
|
-
|
436
|
-
initializer "active_record.attributes_for_inspect" do |app|
|
437
|
-
ActiveSupport.on_load(:active_record) do
|
438
|
-
if app.config.consider_all_requests_local
|
439
|
-
if app.config.active_record.attributes_for_inspect.nil?
|
440
|
-
ActiveRecord::Base.attributes_for_inspect = :all
|
441
|
-
end
|
442
|
-
end
|
443
|
-
end
|
444
|
-
end
|
445
439
|
end
|
446
440
|
end
|
@@ -79,7 +79,7 @@ module ActiveRecord
|
|
79
79
|
normalized_reflections.stringify_keys
|
80
80
|
end
|
81
81
|
|
82
|
-
def normalized_reflections # :nodoc
|
82
|
+
def normalized_reflections # :nodoc:
|
83
83
|
@__reflections ||= begin
|
84
84
|
ref = {}
|
85
85
|
|
@@ -562,12 +562,12 @@ module ActiveRecord
|
|
562
562
|
def foreign_key(infer_from_inverse_of: true)
|
563
563
|
@foreign_key ||= if options[:foreign_key]
|
564
564
|
if options[:foreign_key].is_a?(Array)
|
565
|
-
options[:foreign_key].map { |fk| fk.to_s.freeze }.freeze
|
565
|
+
options[:foreign_key].map { |fk| -fk.to_s.freeze }.freeze
|
566
566
|
else
|
567
567
|
options[:foreign_key].to_s.freeze
|
568
568
|
end
|
569
569
|
elsif options[:query_constraints]
|
570
|
-
options[:query_constraints].map { |fk| fk.to_s.freeze }.freeze
|
570
|
+
options[:query_constraints].map { |fk| -fk.to_s.freeze }.freeze
|
571
571
|
else
|
572
572
|
derived_fk = derive_foreign_key(infer_from_inverse_of: infer_from_inverse_of)
|
573
573
|
|
@@ -575,7 +575,12 @@ module ActiveRecord
|
|
575
575
|
derived_fk = derive_fk_query_constraints(derived_fk)
|
576
576
|
end
|
577
577
|
|
578
|
-
derived_fk
|
578
|
+
if derived_fk.is_a?(Array)
|
579
|
+
derived_fk.map! { |fk| -fk.freeze }
|
580
|
+
derived_fk.freeze
|
581
|
+
else
|
582
|
+
-derived_fk.freeze
|
583
|
+
end
|
579
584
|
end
|
580
585
|
end
|
581
586
|
|