activerecord 7.2.2.1 → 8.1.2
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 +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -28,6 +28,10 @@ module ActiveRecord
|
|
|
28
28
|
# * +database+
|
|
29
29
|
# * +source_location+
|
|
30
30
|
#
|
|
31
|
+
# WARNING: Calculating the +source_location+ of a query can be slow, so you should consider its impact if using it in a production environment.
|
|
32
|
+
#
|
|
33
|
+
# Also see {config.active_record.verbose_query_logs}[https://guides.rubyonrails.org/debugging_rails_applications.html#verbose-query-logs].
|
|
34
|
+
#
|
|
31
35
|
# Action Controller adds default tags when loaded:
|
|
32
36
|
#
|
|
33
37
|
# * +controller+
|
|
@@ -65,21 +69,77 @@ module ActiveRecord
|
|
|
65
69
|
#
|
|
66
70
|
# Tag comments can be prepended to the query:
|
|
67
71
|
#
|
|
68
|
-
#
|
|
72
|
+
# config.active_record.query_log_tags_prepend_comment = true
|
|
69
73
|
#
|
|
70
74
|
# For applications where the content will not change during the lifetime of
|
|
71
75
|
# the request or job execution, the tags can be cached for reuse in every query:
|
|
72
76
|
#
|
|
73
77
|
# config.active_record.cache_query_log_tags = true
|
|
74
78
|
module QueryLogs
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
class GetKeyHandler # :nodoc:
|
|
80
|
+
def initialize(name)
|
|
81
|
+
@name = name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def call(context)
|
|
85
|
+
context[@name]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class IdentityHandler # :nodoc:
|
|
90
|
+
def initialize(value)
|
|
91
|
+
@value = value
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def call(_context)
|
|
95
|
+
@value
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class ZeroArityHandler # :nodoc:
|
|
100
|
+
def initialize(proc)
|
|
101
|
+
@proc = proc
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def call(_context)
|
|
105
|
+
@proc.call
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
@taggings = {}.freeze
|
|
110
|
+
@tags = [ :application ].freeze
|
|
111
|
+
@prepend_comment = false
|
|
112
|
+
@cache_query_log_tags = false
|
|
113
|
+
@tags_formatter = false
|
|
114
|
+
|
|
80
115
|
thread_mattr_accessor :cached_comment, instance_accessor: false
|
|
81
116
|
|
|
82
117
|
class << self
|
|
118
|
+
attr_reader :tags, :taggings, :tags_formatter # :nodoc:
|
|
119
|
+
attr_accessor :prepend_comment, :cache_query_log_tags # :nodoc:
|
|
120
|
+
|
|
121
|
+
def taggings=(taggings) # :nodoc:
|
|
122
|
+
@taggings = taggings.freeze
|
|
123
|
+
@handlers = rebuild_handlers
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def tags=(tags) # :nodoc:
|
|
127
|
+
@tags = tags.freeze
|
|
128
|
+
@handlers = rebuild_handlers
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def tags_formatter=(format) # :nodoc:
|
|
132
|
+
@formatter = case format
|
|
133
|
+
when :legacy
|
|
134
|
+
LegacyFormatter
|
|
135
|
+
when :sqlcommenter
|
|
136
|
+
SQLCommenter
|
|
137
|
+
else
|
|
138
|
+
raise ArgumentError, "Formatter is unsupported: #{format}"
|
|
139
|
+
end
|
|
140
|
+
@tags_formatter = format
|
|
141
|
+
end
|
|
142
|
+
|
|
83
143
|
def call(sql, connection) # :nodoc:
|
|
84
144
|
comment = self.comment(connection)
|
|
85
145
|
|
|
@@ -96,36 +156,42 @@ module ActiveRecord
|
|
|
96
156
|
self.cached_comment = nil
|
|
97
157
|
end
|
|
98
158
|
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
159
|
+
def query_source_location # :nodoc:
|
|
160
|
+
LogSubscriber.backtrace_cleaner.first_clean_frame
|
|
110
161
|
end
|
|
111
162
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
163
|
+
ActiveSupport::ExecutionContext.after_change { ActiveRecord::QueryLogs.clear_cache }
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
def rebuild_handlers
|
|
167
|
+
handlers = []
|
|
168
|
+
@tags.each do |i|
|
|
169
|
+
if i.is_a?(Hash)
|
|
170
|
+
i.each do |k, v|
|
|
171
|
+
handlers << [k, build_handler(k, v)]
|
|
172
|
+
end
|
|
173
|
+
else
|
|
174
|
+
handlers << [i, build_handler(i)]
|
|
175
|
+
end
|
|
117
176
|
end
|
|
118
|
-
|
|
119
|
-
end
|
|
120
|
-
else
|
|
121
|
-
def query_source_location # :nodoc:
|
|
122
|
-
LogSubscriber.backtrace_cleaner.clean(caller_locations(1).each).first
|
|
177
|
+
handlers.sort_by! { |(key, _)| key.to_s }
|
|
123
178
|
end
|
|
124
|
-
end
|
|
125
179
|
|
|
126
|
-
|
|
180
|
+
def build_handler(name, handler = nil)
|
|
181
|
+
handler ||= @taggings[name]
|
|
182
|
+
if handler.nil?
|
|
183
|
+
GetKeyHandler.new(name)
|
|
184
|
+
elsif handler.respond_to?(:call)
|
|
185
|
+
if handler.arity == 0
|
|
186
|
+
ZeroArityHandler.new(handler)
|
|
187
|
+
else
|
|
188
|
+
handler
|
|
189
|
+
end
|
|
190
|
+
else
|
|
191
|
+
IdentityHandler.new(handler)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
127
194
|
|
|
128
|
-
private
|
|
129
195
|
# Returns an SQL comment +String+ containing the query log tags.
|
|
130
196
|
# Sets and returns a cached comment if <tt>cache_query_log_tags</tt> is +true+.
|
|
131
197
|
def comment(connection)
|
|
@@ -136,10 +202,6 @@ module ActiveRecord
|
|
|
136
202
|
end
|
|
137
203
|
end
|
|
138
204
|
|
|
139
|
-
def formatter
|
|
140
|
-
self.tags_formatter || self.update_formatter(:legacy)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
205
|
def uncached_comment(connection)
|
|
144
206
|
content = tag_content(connection)
|
|
145
207
|
|
|
@@ -149,7 +211,7 @@ module ActiveRecord
|
|
|
149
211
|
end
|
|
150
212
|
|
|
151
213
|
def escape_sql_comment(content)
|
|
152
|
-
# Sanitize a string to appear within
|
|
214
|
+
# Sanitize a string to appear within an SQL comment
|
|
153
215
|
# For compatibility, this also surrounding "/*+", "/*", and "*/"
|
|
154
216
|
# characters, possibly with single surrounding space.
|
|
155
217
|
# Then follows that by replacing any internal "*/" or "/ *" with
|
|
@@ -165,25 +227,15 @@ module ActiveRecord
|
|
|
165
227
|
context = ActiveSupport::ExecutionContext.to_h
|
|
166
228
|
context[:connection] ||= connection
|
|
167
229
|
|
|
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?
|
|
230
|
+
pairs = @handlers.filter_map do |(key, handler)|
|
|
231
|
+
val = handler.call(context)
|
|
232
|
+
@formatter.format(key, val) unless val.nil?
|
|
184
233
|
end
|
|
185
|
-
|
|
234
|
+
@formatter.join(pairs)
|
|
186
235
|
end
|
|
187
236
|
end
|
|
237
|
+
|
|
238
|
+
@handlers = rebuild_handlers
|
|
239
|
+
self.tags_formatter = :legacy
|
|
188
240
|
end
|
|
189
241
|
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
|
|
@@ -46,8 +46,8 @@ module ActiveRecord
|
|
|
46
46
|
# Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
|
|
47
47
|
# Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
|
|
48
48
|
#
|
|
49
|
-
# Note that building your own SQL query string from user input may expose your application to
|
|
50
|
-
# injection attacks
|
|
49
|
+
# Note that building your own SQL query string from user input {may expose your application to
|
|
50
|
+
# injection attacks}[https://guides.rubyonrails.org/security.html#sql-injection].
|
|
51
51
|
def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
|
|
52
52
|
result = with_connection do |c|
|
|
53
53
|
_query_by_sql(c, sql, binds, preparable: preparable, allow_retry: allow_retry)
|
|
@@ -55,13 +55,11 @@ module ActiveRecord
|
|
|
55
55
|
_load_from_sql(result, &block)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
# Same as
|
|
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|
|
|
58
|
+
# Same as #find_by_sql but perform the query asynchronously and returns an ActiveRecord::Promise.
|
|
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?
|
|
@@ -86,10 +86,10 @@ module ActiveRecord
|
|
|
86
86
|
|
|
87
87
|
message_bus.instrument("instantiation.active_record", payload) do
|
|
88
88
|
if result_set.includes_column?(inheritance_column)
|
|
89
|
-
result_set.map { |record| instantiate(record, column_types, &block) }
|
|
89
|
+
result_set.indexed_rows.map { |record| instantiate(record, column_types, &block) }
|
|
90
90
|
else
|
|
91
91
|
# Instantiate a homogeneous set
|
|
92
|
-
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
|
92
|
+
result_set.indexed_rows.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
end
|
|
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
-
# Same as
|
|
115
|
+
# Same as #count_by_sql but perform the query asynchronously and returns an ActiveRecord::Promise.
|
|
116
116
|
def async_count_by_sql(sql)
|
|
117
117
|
with_connection do |c|
|
|
118
118
|
c.select_value(sanitize_sql(sql), "#{name} Count", async: true).then(&:to_i)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_record"
|
|
4
3
|
require "rails"
|
|
4
|
+
require "active_record"
|
|
5
5
|
require "active_support/core_ext/object/try"
|
|
6
6
|
require "active_model/railtie"
|
|
7
7
|
|
|
@@ -23,8 +23,8 @@ module ActiveRecord
|
|
|
23
23
|
config.action_dispatch.rescue_responses.merge!(
|
|
24
24
|
"ActiveRecord::RecordNotFound" => :not_found,
|
|
25
25
|
"ActiveRecord::StaleObjectError" => :conflict,
|
|
26
|
-
"ActiveRecord::RecordInvalid" =>
|
|
27
|
-
"ActiveRecord::RecordNotSaved" =>
|
|
26
|
+
"ActiveRecord::RecordInvalid" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT,
|
|
27
|
+
"ActiveRecord::RecordNotSaved" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
config.active_record.use_schema_cache_dump = true
|
|
@@ -35,9 +35,12 @@ module ActiveRecord
|
|
|
35
35
|
config.active_record.query_log_tags = [ :application ]
|
|
36
36
|
config.active_record.query_log_tags_format = :legacy
|
|
37
37
|
config.active_record.cache_query_log_tags = false
|
|
38
|
+
config.active_record.query_log_tags_prepend_comment = false
|
|
38
39
|
config.active_record.raise_on_assign_to_attr_readonly = false
|
|
39
40
|
config.active_record.belongs_to_required_validates_foreign_key = true
|
|
40
41
|
config.active_record.generate_secure_token_on = :create
|
|
42
|
+
config.active_record.use_legacy_signed_id_verifier = :generate_and_verify
|
|
43
|
+
config.active_record.deprecated_associations_options = { mode: :warn, backtrace: false }
|
|
41
44
|
|
|
42
45
|
config.active_record.queues = ActiveSupport::InheritableOptions.new
|
|
43
46
|
|
|
@@ -184,30 +187,6 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
184
187
|
end
|
|
185
188
|
end
|
|
186
189
|
|
|
187
|
-
initializer "active_record.warn_on_records_fetched_greater_than" do
|
|
188
|
-
if config.active_record.warn_on_records_fetched_greater_than
|
|
189
|
-
ActiveRecord.deprecator.warn <<~MSG.squish
|
|
190
|
-
`config.active_record.warn_on_records_fetched_greater_than` is deprecated and will be
|
|
191
|
-
removed in Rails 8.0.
|
|
192
|
-
Please subscribe to `sql.active_record` notifications and access the row count field to
|
|
193
|
-
detect large result set sizes.
|
|
194
|
-
MSG
|
|
195
|
-
ActiveSupport.on_load(:active_record) do
|
|
196
|
-
require "active_record/relation/record_fetch_warning"
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
initializer "active_record.sqlite3_deprecated_warning" do
|
|
202
|
-
if config.active_record.key?(:sqlite3_production_warning)
|
|
203
|
-
config.active_record.delete(:sqlite3_production_warning)
|
|
204
|
-
ActiveRecord.deprecator.warn <<~MSG.squish
|
|
205
|
-
The `config.active_record.sqlite3_production_warning` configuration no longer has any effect
|
|
206
|
-
and can be safely removed.
|
|
207
|
-
MSG
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
190
|
initializer "active_record.sqlite3_adapter_strict_strings_by_default" do
|
|
212
191
|
config.after_initialize do
|
|
213
192
|
if config.active_record.sqlite3_adapter_strict_strings_by_default
|
|
@@ -253,10 +232,12 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
253
232
|
:query_log_tags,
|
|
254
233
|
:query_log_tags_format,
|
|
255
234
|
:cache_query_log_tags,
|
|
235
|
+
:query_log_tags_prepend_comment,
|
|
256
236
|
:sqlite3_adapter_strict_strings_by_default,
|
|
257
237
|
:check_schema_cache_dump_version,
|
|
258
238
|
:use_schema_cache_dump,
|
|
259
239
|
:postgresql_adapter_decode_dates,
|
|
240
|
+
:use_legacy_signed_id_verifier,
|
|
260
241
|
)
|
|
261
242
|
|
|
262
243
|
configs_used_in_other_initializers.each do |k, v|
|
|
@@ -298,6 +279,13 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
298
279
|
end
|
|
299
280
|
end
|
|
300
281
|
|
|
282
|
+
initializer "active_record.job_checkpoints" do
|
|
283
|
+
require "active_record/railties/job_checkpoints"
|
|
284
|
+
ActiveSupport.on_load(:active_job_continuable) do
|
|
285
|
+
prepend ActiveRecord::Railties::JobCheckpoints
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
301
289
|
initializer "active_record.set_reloader_hooks" do
|
|
302
290
|
ActiveSupport.on_load(:active_record) do
|
|
303
291
|
ActiveSupport::Reloader.before_class_unload do
|
|
@@ -343,9 +331,22 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
343
331
|
end
|
|
344
332
|
end
|
|
345
333
|
|
|
346
|
-
initializer "active_record.
|
|
347
|
-
|
|
348
|
-
|
|
334
|
+
initializer "active_record.filter_attributes_as_log_parameters" do |app|
|
|
335
|
+
ActiveRecord::FilterAttributeHandler.new(app).enable
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
initializer "active_record.configure_message_verifiers" do |app|
|
|
339
|
+
ActiveRecord.message_verifiers = app.message_verifiers
|
|
340
|
+
|
|
341
|
+
use_legacy_signed_id_verifier = app.config.active_record.use_legacy_signed_id_verifier
|
|
342
|
+
legacy_options = { digest: "SHA256", serializer: JSON, url_safe: true }
|
|
343
|
+
|
|
344
|
+
if use_legacy_signed_id_verifier == :generate_and_verify
|
|
345
|
+
app.message_verifiers.prepend { |salt| legacy_options if salt == "active_record/signed_id" }
|
|
346
|
+
elsif use_legacy_signed_id_verifier == :verify
|
|
347
|
+
app.message_verifiers.rotate { |salt| legacy_options if salt == "active_record/signed_id" }
|
|
348
|
+
elsif use_legacy_signed_id_verifier
|
|
349
|
+
raise ArgumentError, "Unrecognized value for config.active_record.use_legacy_signed_id_verifier: #{use_legacy_signed_id_verifier.inspect}"
|
|
349
350
|
end
|
|
350
351
|
end
|
|
351
352
|
|
|
@@ -390,7 +391,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
390
391
|
config.after_initialize do
|
|
391
392
|
if app.config.active_record.query_log_tags_enabled
|
|
392
393
|
ActiveRecord.query_transformers << ActiveRecord::QueryLogs
|
|
393
|
-
ActiveRecord::QueryLogs.taggings.merge
|
|
394
|
+
ActiveRecord::QueryLogs.taggings = ActiveRecord::QueryLogs.taggings.merge(
|
|
394
395
|
application: Rails.application.class.name.split("::").first,
|
|
395
396
|
pid: -> { Process.pid.to_s },
|
|
396
397
|
socket: ->(context) { context[:connection].pool.db_config.socket },
|
|
@@ -405,12 +406,16 @@ To keep using the current cache store, you can turn off cache versioning entirel
|
|
|
405
406
|
end
|
|
406
407
|
|
|
407
408
|
if app.config.active_record.query_log_tags_format
|
|
408
|
-
ActiveRecord::QueryLogs.
|
|
409
|
+
ActiveRecord::QueryLogs.tags_formatter = app.config.active_record.query_log_tags_format
|
|
409
410
|
end
|
|
410
411
|
|
|
411
412
|
if app.config.active_record.cache_query_log_tags
|
|
412
413
|
ActiveRecord::QueryLogs.cache_query_log_tags = true
|
|
413
414
|
end
|
|
415
|
+
|
|
416
|
+
if app.config.active_record.query_log_tags_prepend_comment
|
|
417
|
+
ActiveRecord::QueryLogs.prepend_comment = true
|
|
418
|
+
end
|
|
414
419
|
end
|
|
415
420
|
end
|
|
416
421
|
end
|
|
@@ -41,11 +41,14 @@ module ActiveRecord
|
|
|
41
41
|
|
|
42
42
|
def cleanup_view_runtime
|
|
43
43
|
if logger && logger.info?
|
|
44
|
-
|
|
44
|
+
runtime_stats = ActiveRecord::RuntimeRegistry.stats
|
|
45
|
+
db_rt_before_render = runtime_stats.reset_runtimes
|
|
45
46
|
self.db_runtime = (db_runtime || 0) + db_rt_before_render
|
|
47
|
+
|
|
46
48
|
runtime = super
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
|
|
50
|
+
queries_rt = runtime_stats.sql_runtime - runtime_stats.async_sql_runtime
|
|
51
|
+
db_rt_after_render = runtime_stats.reset_runtimes
|
|
49
52
|
self.db_runtime += db_rt_after_render
|
|
50
53
|
runtime - queries_rt
|
|
51
54
|
else
|
|
@@ -56,9 +59,11 @@ module ActiveRecord
|
|
|
56
59
|
def append_info_to_payload(payload)
|
|
57
60
|
super
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
payload[:
|
|
61
|
-
payload[:
|
|
62
|
+
runtime_stats = ActiveRecord::RuntimeRegistry.stats
|
|
63
|
+
payload[:db_runtime] = (db_runtime || 0) + runtime_stats.sql_runtime
|
|
64
|
+
payload[:queries_count] = runtime_stats.queries_count
|
|
65
|
+
payload[:cached_queries_count] = runtime_stats.cached_queries_count
|
|
66
|
+
runtime_stats.reset
|
|
62
67
|
end
|
|
63
68
|
end
|
|
64
69
|
end
|
|
@@ -87,22 +87,7 @@ db_namespace = namespace :db do
|
|
|
87
87
|
|
|
88
88
|
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
|
89
89
|
task migrate: :load_config do
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if db_configs.size == 1 && db_configs.first.primary?
|
|
93
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
|
94
|
-
else
|
|
95
|
-
mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
|
|
96
|
-
|
|
97
|
-
mapped_versions.sort.each do |version, db_configs|
|
|
98
|
-
db_configs.each do |db_config|
|
|
99
|
-
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(db_config) do
|
|
100
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate(version)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
90
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate_all
|
|
106
91
|
db_namespace["_dump"].invoke
|
|
107
92
|
end
|
|
108
93
|
|
|
@@ -175,8 +160,20 @@ db_namespace = namespace :db do
|
|
|
175
160
|
end
|
|
176
161
|
end
|
|
177
162
|
|
|
178
|
-
|
|
179
|
-
task reset: ["db:drop", "db:create", "db:migrate"]
|
|
163
|
+
desc "Resets your database using your migrations for the current environment"
|
|
164
|
+
task reset: ["db:drop", "db:create", "db:schema:dump", "db:migrate"]
|
|
165
|
+
|
|
166
|
+
namespace :reset do
|
|
167
|
+
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
|
168
|
+
desc "Drop and recreate the #{name} database using migrations"
|
|
169
|
+
task name => :load_config do
|
|
170
|
+
db_namespace["drop:#{name}"].invoke
|
|
171
|
+
db_namespace["create:#{name}"].invoke
|
|
172
|
+
db_namespace["schema:dump:#{name}"].invoke
|
|
173
|
+
db_namespace["migrate:#{name}"].invoke
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
180
177
|
|
|
181
178
|
desc 'Run the "up" for a given migration VERSION.'
|
|
182
179
|
task up: :load_config do
|
|
@@ -348,7 +345,7 @@ db_namespace = namespace :db do
|
|
|
348
345
|
pending_migrations << pool.migration_context.open.pending_migrations
|
|
349
346
|
end
|
|
350
347
|
|
|
351
|
-
pending_migrations
|
|
348
|
+
pending_migrations.flatten!
|
|
352
349
|
|
|
353
350
|
if pending_migrations.any?
|
|
354
351
|
puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
|
|
@@ -462,28 +459,23 @@ db_namespace = namespace :db do
|
|
|
462
459
|
namespace :schema do
|
|
463
460
|
desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
|
|
464
461
|
task dump: :load_config do
|
|
465
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
|
466
|
-
db_config = pool.db_config
|
|
467
|
-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
|
468
|
-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
|
469
|
-
end
|
|
462
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_all
|
|
470
463
|
|
|
471
464
|
db_namespace["schema:dump"].reenable
|
|
472
465
|
end
|
|
473
466
|
|
|
474
467
|
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
|
|
475
468
|
task load: [:load_config, :check_protected_environments] do
|
|
476
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(
|
|
469
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ENV["SCHEMA_FORMAT"], ENV["SCHEMA"])
|
|
477
470
|
end
|
|
478
471
|
|
|
479
472
|
namespace :dump do
|
|
480
473
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
|
481
|
-
desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on
|
|
474
|
+
desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on configuration) for #{name} database"
|
|
482
475
|
task name => :load_config do
|
|
483
476
|
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
|
|
484
477
|
db_config = pool.db_config
|
|
485
|
-
|
|
486
|
-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
|
478
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
487
479
|
end
|
|
488
480
|
|
|
489
481
|
db_namespace["schema:dump:#{name}"].reenable
|
|
@@ -493,12 +485,11 @@ db_namespace = namespace :db do
|
|
|
493
485
|
|
|
494
486
|
namespace :load do
|
|
495
487
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
|
496
|
-
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on
|
|
497
|
-
task name =>
|
|
488
|
+
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on configuration) into the #{name} database"
|
|
489
|
+
task name => [:load_config, :check_protected_environments] do
|
|
498
490
|
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
|
|
499
491
|
db_config = pool.db_config
|
|
500
|
-
|
|
501
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
|
492
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
502
493
|
end
|
|
503
494
|
end
|
|
504
495
|
end
|
|
@@ -542,13 +533,12 @@ db_namespace = namespace :db do
|
|
|
542
533
|
end
|
|
543
534
|
|
|
544
535
|
namespace :test do
|
|
545
|
-
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on
|
|
536
|
+
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on configuration)"
|
|
546
537
|
task load_schema: %w(db:test:purge) do
|
|
547
538
|
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test") do |pool|
|
|
548
539
|
db_config = pool.db_config
|
|
549
540
|
ActiveRecord::Schema.verbose = false
|
|
550
|
-
|
|
551
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
|
541
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
552
542
|
end
|
|
553
543
|
end
|
|
554
544
|
|
|
@@ -573,8 +563,7 @@ db_namespace = namespace :db do
|
|
|
573
563
|
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
|
|
574
564
|
db_config = pool.db_config
|
|
575
565
|
ActiveRecord::Schema.verbose = false
|
|
576
|
-
|
|
577
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
|
566
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
578
567
|
end
|
|
579
568
|
end
|
|
580
569
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Railties # :nodoc:
|
|
5
|
+
module JobCheckpoints # :nodoc:
|
|
6
|
+
def checkpoint!
|
|
7
|
+
if ActiveRecord.all_open_transactions.any?
|
|
8
|
+
raise ActiveJob::Continuation::CheckpointError, "Cannot checkpoint job with open transactions"
|
|
9
|
+
else
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|