activerecord 8.1.0.beta1 → 8.1.0
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 +126 -5
- data/lib/active_record/associations/belongs_to_association.rb +2 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +32 -13
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
- data/lib/active_record/connection_adapters/abstract/transaction.rb +9 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +25 -11
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +0 -2
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +16 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
- data/lib/active_record/connection_handling.rb +14 -9
- data/lib/active_record/database_configurations/hash_config.rb +5 -2
- data/lib/active_record/encryption/encryptor.rb +12 -0
- data/lib/active_record/errors.rb +3 -3
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +1 -1
- data/lib/active_record/model_schema.rb +26 -3
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +1 -1
- data/lib/active_record/railties/job_runtime.rb +2 -2
- data/lib/active_record/reflection.rb +3 -7
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/merger.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +7 -5
- data/lib/active_record/relation/query_methods.rb +3 -2
- data/lib/active_record/relation/where_clause.rb +2 -0
- data/lib/active_record/relation.rb +1 -1
- data/lib/active_record/runtime_registry.rb +41 -58
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/database_tasks.rb +24 -14
- data/lib/active_record/test_databases.rb +4 -2
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +9 -9
- data/lib/active_record/explain_subscriber.rb +0 -34
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
class PredicateBuilder
|
|
5
5
|
class PolymorphicArrayValue # :nodoc:
|
|
6
|
-
def initialize(
|
|
7
|
-
@
|
|
6
|
+
def initialize(reflection, values)
|
|
7
|
+
@reflection = reflection
|
|
8
8
|
@values = values
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def queries
|
|
12
|
-
return [
|
|
12
|
+
return [ reflection.join_foreign_key => values ] if values.empty?
|
|
13
13
|
|
|
14
14
|
type_to_ids_mapping.map do |type, ids|
|
|
15
15
|
query = {}
|
|
16
|
-
query[
|
|
17
|
-
query[
|
|
16
|
+
query[reflection.join_foreign_type] = type if type
|
|
17
|
+
query[reflection.join_foreign_key] = ids
|
|
18
18
|
query
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
private
|
|
23
|
-
attr_reader :
|
|
23
|
+
attr_reader :reflection, :values
|
|
24
24
|
|
|
25
25
|
def type_to_ids_mapping
|
|
26
26
|
default_hash = Hash.new { |hsh, key| hsh[key] = [] }
|
|
@@ -30,7 +30,7 @@ module ActiveRecord
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def primary_key(value)
|
|
33
|
-
|
|
33
|
+
reflection.join_primary_key(klass(value))
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def klass(value)
|
|
@@ -99,24 +99,26 @@ module ActiveRecord
|
|
|
99
99
|
elsif value.is_a?(Hash) && !table.has_column?(key)
|
|
100
100
|
table.associated_table(key, &block)
|
|
101
101
|
.predicate_builder.expand_from_hash(value.stringify_keys)
|
|
102
|
-
elsif table.associated_with
|
|
102
|
+
elsif (associated_reflection = table.associated_with(key))
|
|
103
103
|
# Find the foreign key when using queries such as:
|
|
104
104
|
# Post.where(author: author)
|
|
105
105
|
#
|
|
106
106
|
# For polymorphic relationships, find the foreign key and type:
|
|
107
107
|
# PriceEstimate.where(estimate_of: treasure)
|
|
108
|
-
|
|
109
|
-
if
|
|
108
|
+
|
|
109
|
+
if associated_reflection.polymorphic?
|
|
110
110
|
value = [value] unless value.is_a?(Array)
|
|
111
111
|
klass = PolymorphicArrayValue
|
|
112
|
-
elsif
|
|
112
|
+
elsif associated_reflection.through_reflection?
|
|
113
|
+
associated_table = table.associated_table(key)
|
|
114
|
+
|
|
113
115
|
next associated_table.predicate_builder.expand_from_hash(
|
|
114
116
|
associated_table.primary_key => value
|
|
115
117
|
)
|
|
116
118
|
end
|
|
117
119
|
|
|
118
120
|
klass ||= AssociationQueryValue
|
|
119
|
-
queries = klass.new(
|
|
121
|
+
queries = klass.new(associated_reflection, value).queries.map! do |query|
|
|
120
122
|
# If the query produced is identical to attributes don't go any deeper.
|
|
121
123
|
# Prevents stack level too deep errors when association and foreign_key are identical.
|
|
122
124
|
query == attributes ? self[key, value] : expand_from_hash(query)
|
|
@@ -426,7 +426,7 @@ module ActiveRecord
|
|
|
426
426
|
end
|
|
427
427
|
|
|
428
428
|
def _select!(*fields) # :nodoc:
|
|
429
|
-
self.select_values
|
|
429
|
+
self.select_values |= fields
|
|
430
430
|
self
|
|
431
431
|
end
|
|
432
432
|
|
|
@@ -1923,7 +1923,8 @@ module ActiveRecord
|
|
|
1923
1923
|
|
|
1924
1924
|
def build_with_expression_from_value(value, nested = false)
|
|
1925
1925
|
case value
|
|
1926
|
-
when Arel::Nodes::SqlLiteral
|
|
1926
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BoundSqlLiteral
|
|
1927
|
+
Arel::Nodes::Grouping.new(value)
|
|
1927
1928
|
when ActiveRecord::Relation
|
|
1928
1929
|
if nested
|
|
1929
1930
|
value.arel.ast
|
|
@@ -176,6 +176,8 @@ module ActiveRecord
|
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
def except_predicates(columns)
|
|
179
|
+
return predicates if columns.empty?
|
|
180
|
+
|
|
179
181
|
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
|
180
182
|
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
181
183
|
|
|
@@ -307,7 +307,7 @@ module ActiveRecord
|
|
|
307
307
|
end
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
-
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core
|
|
310
|
+
# Like #find_or_create_by, but calls {new}[rdoc-ref:Core.new]
|
|
311
311
|
# instead of {create}[rdoc-ref:Persistence::ClassMethods#create].
|
|
312
312
|
def find_or_initialize_by(attributes, &block)
|
|
313
313
|
find_by(attributes) || new(attributes, &block)
|
|
@@ -3,80 +3,63 @@
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
# This is a thread locals registry for Active Record. For example:
|
|
5
5
|
#
|
|
6
|
-
# ActiveRecord::RuntimeRegistry.sql_runtime
|
|
6
|
+
# ActiveRecord::RuntimeRegistry.stats.sql_runtime
|
|
7
7
|
#
|
|
8
8
|
# returns the connection handler local to the current unit of execution (either thread of fiber).
|
|
9
9
|
module RuntimeRegistry # :nodoc:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
class Stats
|
|
11
|
+
attr_accessor :sql_runtime, :async_sql_runtime, :queries_count, :cached_queries_count
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@sql_runtime = 0.0
|
|
15
|
+
@async_sql_runtime = 0.0
|
|
16
|
+
@queries_count = 0
|
|
17
|
+
@cached_queries_count = 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def reset_runtimes
|
|
21
|
+
sql_runtime_was = @sql_runtime
|
|
22
|
+
@sql_runtime = 0.0
|
|
23
|
+
@async_sql_runtime = 0.0
|
|
24
|
+
sql_runtime_was
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
public alias_method :reset, :initialize
|
|
14
28
|
end
|
|
15
29
|
|
|
16
|
-
|
|
17
|
-
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def async_sql_runtime
|
|
21
|
-
ActiveSupport::IsolatedExecutionState[:active_record_async_sql_runtime] ||= 0.0
|
|
22
|
-
end
|
|
30
|
+
extend self
|
|
23
31
|
|
|
24
|
-
def
|
|
25
|
-
|
|
32
|
+
def call(name, start, finish, id, payload)
|
|
33
|
+
record(
|
|
34
|
+
payload[:name],
|
|
35
|
+
(finish - start) * 1_000.0,
|
|
36
|
+
async: payload[:async],
|
|
37
|
+
lock_wait: payload[:lock_wait],
|
|
38
|
+
)
|
|
26
39
|
end
|
|
27
40
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
end
|
|
41
|
+
def record(query_name, runtime, cached: false, async: false, lock_wait: nil)
|
|
42
|
+
stats = self.stats
|
|
31
43
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
unless query_name == "TRANSACTION" || query_name == "SCHEMA"
|
|
45
|
+
stats.queries_count += 1
|
|
46
|
+
stats.cached_queries_count += 1 if cached
|
|
47
|
+
end
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
if async
|
|
50
|
+
stats.async_sql_runtime += (runtime - lock_wait)
|
|
51
|
+
end
|
|
52
|
+
stats.sql_runtime += runtime
|
|
38
53
|
end
|
|
39
54
|
|
|
40
|
-
def
|
|
41
|
-
ActiveSupport::IsolatedExecutionState[:
|
|
55
|
+
def stats
|
|
56
|
+
ActiveSupport::IsolatedExecutionState[:active_record_runtime] ||= Stats.new
|
|
42
57
|
end
|
|
43
58
|
|
|
44
59
|
def reset
|
|
45
|
-
|
|
46
|
-
reset_queries_count
|
|
47
|
-
reset_cached_queries_count
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def reset_runtimes
|
|
51
|
-
rt, self.sql_runtime = sql_runtime, 0.0
|
|
52
|
-
self.async_sql_runtime = 0.0
|
|
53
|
-
rt
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def reset_queries_count
|
|
57
|
-
qc = queries_count
|
|
58
|
-
self.queries_count = 0
|
|
59
|
-
qc
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def reset_cached_queries_count
|
|
63
|
-
qc = cached_queries_count
|
|
64
|
-
self.cached_queries_count = 0
|
|
65
|
-
qc
|
|
60
|
+
stats.reset
|
|
66
61
|
end
|
|
67
62
|
end
|
|
68
63
|
end
|
|
69
64
|
|
|
70
|
-
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record"
|
|
71
|
-
unless ["SCHEMA", "TRANSACTION"].include?(payload[:name])
|
|
72
|
-
ActiveRecord::RuntimeRegistry.queries_count += 1
|
|
73
|
-
ActiveRecord::RuntimeRegistry.cached_queries_count += 1 if payload[:cached]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
runtime = (finish - start) * 1_000.0
|
|
77
|
-
|
|
78
|
-
if payload[:async]
|
|
79
|
-
ActiveRecord::RuntimeRegistry.async_sql_runtime += (runtime - payload[:lock_wait])
|
|
80
|
-
end
|
|
81
|
-
ActiveRecord::RuntimeRegistry.sql_runtime += runtime
|
|
82
|
-
end
|
|
65
|
+
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record", ActiveRecord::RuntimeRegistry)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/structured_event_subscriber"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber # :nodoc:
|
|
7
|
+
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
|
|
8
|
+
|
|
9
|
+
def strict_loading_violation(event)
|
|
10
|
+
owner = event.payload[:owner]
|
|
11
|
+
reflection = event.payload[:reflection]
|
|
12
|
+
|
|
13
|
+
emit_debug_event("active_record.strict_loading_violation",
|
|
14
|
+
owner: owner.name,
|
|
15
|
+
class: reflection.polymorphic? ? nil : reflection.klass.name,
|
|
16
|
+
name: reflection.name,
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
debug_only :strict_loading_violation
|
|
20
|
+
|
|
21
|
+
def sql(event)
|
|
22
|
+
payload = event.payload
|
|
23
|
+
|
|
24
|
+
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
|
25
|
+
|
|
26
|
+
binds = nil
|
|
27
|
+
|
|
28
|
+
if payload[:binds]&.any?
|
|
29
|
+
casted_params = type_casted_binds(payload[:type_casted_binds])
|
|
30
|
+
|
|
31
|
+
binds = []
|
|
32
|
+
payload[:binds].each_with_index do |attr, i|
|
|
33
|
+
attribute_name = if attr.respond_to?(:name)
|
|
34
|
+
attr.name
|
|
35
|
+
elsif attr.respond_to?(:[]) && attr[i].respond_to?(:name)
|
|
36
|
+
attr[i].name
|
|
37
|
+
else
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
filtered_params = filter(attribute_name, casted_params[i])
|
|
42
|
+
|
|
43
|
+
binds << render_bind(attr, filtered_params)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
emit_debug_event("active_record.sql",
|
|
48
|
+
async: payload[:async],
|
|
49
|
+
name: payload[:name],
|
|
50
|
+
sql: payload[:sql],
|
|
51
|
+
cached: payload[:cached],
|
|
52
|
+
lock_wait: payload[:lock_wait],
|
|
53
|
+
binds: binds,
|
|
54
|
+
duration_ms: event.duration.round(2),
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
debug_only :sql
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
def type_casted_binds(casted_binds)
|
|
61
|
+
casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def render_bind(attr, value)
|
|
65
|
+
case attr
|
|
66
|
+
when ActiveModel::Attribute
|
|
67
|
+
if attr.type.binary? && attr.value
|
|
68
|
+
value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
|
69
|
+
end
|
|
70
|
+
when Array
|
|
71
|
+
attr = attr.first
|
|
72
|
+
else
|
|
73
|
+
attr = nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
[attr&.name, value]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def filter(name, value)
|
|
80
|
+
ActiveRecord::Base.inspection_filter.filter_param(name, value)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
ActiveRecord::StructuredEventSubscriber.attach_to :active_record
|
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
class TableMetadata # :nodoc:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def initialize(klass, arel_table, reflection = nil)
|
|
5
|
+
def initialize(klass, arel_table)
|
|
8
6
|
@klass = klass
|
|
9
7
|
@arel_table = arel_table
|
|
10
|
-
@reflection = reflection
|
|
11
8
|
end
|
|
12
9
|
|
|
13
10
|
def primary_key
|
|
@@ -22,7 +19,7 @@ module ActiveRecord
|
|
|
22
19
|
klass&.columns_hash&.key?(column_name)
|
|
23
20
|
end
|
|
24
21
|
|
|
25
|
-
def associated_with
|
|
22
|
+
def associated_with(table_name)
|
|
26
23
|
klass&._reflect_on_association(table_name)
|
|
27
24
|
end
|
|
28
25
|
|
|
@@ -42,26 +39,14 @@ module ActiveRecord
|
|
|
42
39
|
if association_klass
|
|
43
40
|
arel_table = association_klass.arel_table
|
|
44
41
|
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
|
45
|
-
TableMetadata.new(association_klass, arel_table
|
|
42
|
+
TableMetadata.new(association_klass, arel_table)
|
|
46
43
|
else
|
|
47
44
|
type_caster = TypeCaster::Connection.new(klass, table_name)
|
|
48
45
|
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
|
49
|
-
TableMetadata.new(nil, arel_table
|
|
46
|
+
TableMetadata.new(nil, arel_table)
|
|
50
47
|
end
|
|
51
48
|
end
|
|
52
49
|
|
|
53
|
-
def polymorphic_association?
|
|
54
|
-
reflection&.polymorphic?
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def polymorphic_name_association
|
|
58
|
-
reflection&.polymorphic_name
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def through_association?
|
|
62
|
-
reflection&.through_reflection?
|
|
63
|
-
end
|
|
64
|
-
|
|
65
50
|
def reflect_on_aggregation(aggregation_name)
|
|
66
51
|
klass&.reflect_on_aggregation(aggregation_name)
|
|
67
52
|
end
|
|
@@ -78,6 +63,6 @@ module ActiveRecord
|
|
|
78
63
|
attr_reader :arel_table
|
|
79
64
|
|
|
80
65
|
private
|
|
81
|
-
attr_reader :klass
|
|
66
|
+
attr_reader :klass
|
|
82
67
|
end
|
|
83
68
|
end
|
|
@@ -428,9 +428,15 @@ module ActiveRecord
|
|
|
428
428
|
end
|
|
429
429
|
|
|
430
430
|
def dump_all
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
seen_schemas = []
|
|
432
|
+
|
|
433
|
+
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
|
434
|
+
schema_path = schema_dump_path(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
435
|
+
|
|
436
|
+
next if seen_schemas.include?(schema_path)
|
|
437
|
+
|
|
433
438
|
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
439
|
+
seen_schemas << schema_path
|
|
434
440
|
end
|
|
435
441
|
end
|
|
436
442
|
|
|
@@ -441,18 +447,22 @@ module ActiveRecord
|
|
|
441
447
|
filename = schema_dump_path(db_config, format)
|
|
442
448
|
return unless filename
|
|
443
449
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
450
|
+
with_temporary_pool(db_config) do |pool|
|
|
451
|
+
FileUtils.mkdir_p(db_dir)
|
|
452
|
+
case format.to_sym
|
|
453
|
+
when :ruby
|
|
454
|
+
File.open(filename, "w:utf-8") do |file|
|
|
455
|
+
ActiveRecord::SchemaDumper.dump(pool, file)
|
|
456
|
+
end
|
|
457
|
+
when :sql
|
|
458
|
+
structure_dump(db_config, filename)
|
|
459
|
+
if pool.schema_migration.table_exists?
|
|
460
|
+
File.open(filename, "a") do |f|
|
|
461
|
+
pool.with_connection do |connection|
|
|
462
|
+
f.puts connection.dump_schema_versions
|
|
463
|
+
end
|
|
464
|
+
f.print "\n"
|
|
465
|
+
end
|
|
456
466
|
end
|
|
457
467
|
end
|
|
458
468
|
end
|
|
@@ -19,10 +19,12 @@ module ActiveRecord
|
|
|
19
19
|
def self.create_and_load_schema(i, env_name:)
|
|
20
20
|
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
|
21
21
|
|
|
22
|
-
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
|
22
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name, include_hidden: true).each do |db_config|
|
|
23
23
|
db_config._database = "#{db_config.database}_#{i}"
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
if db_config.database_tasks?
|
|
26
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, nil)
|
|
27
|
+
end
|
|
26
28
|
end
|
|
27
29
|
ensure
|
|
28
30
|
ActiveRecord::Base.establish_connection
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.1.0
|
|
4
|
+
version: 8.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 8.1.0
|
|
18
|
+
version: 8.1.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 8.1.0
|
|
25
|
+
version: 8.1.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: activemodel
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 8.1.0
|
|
32
|
+
version: 8.1.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 8.1.0
|
|
39
|
+
version: 8.1.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: timeout
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -253,7 +253,6 @@ files:
|
|
|
253
253
|
- lib/active_record/errors.rb
|
|
254
254
|
- lib/active_record/explain.rb
|
|
255
255
|
- lib/active_record/explain_registry.rb
|
|
256
|
-
- lib/active_record/explain_subscriber.rb
|
|
257
256
|
- lib/active_record/filter_attribute_handler.rb
|
|
258
257
|
- lib/active_record/fixture_set/file.rb
|
|
259
258
|
- lib/active_record/fixture_set/model_metadata.rb
|
|
@@ -337,6 +336,7 @@ files:
|
|
|
337
336
|
- lib/active_record/signed_id.rb
|
|
338
337
|
- lib/active_record/statement_cache.rb
|
|
339
338
|
- lib/active_record/store.rb
|
|
339
|
+
- lib/active_record/structured_event_subscriber.rb
|
|
340
340
|
- lib/active_record/suppressor.rb
|
|
341
341
|
- lib/active_record/table_metadata.rb
|
|
342
342
|
- lib/active_record/tasks/abstract_tasks.rb
|
|
@@ -478,10 +478,10 @@ licenses:
|
|
|
478
478
|
- MIT
|
|
479
479
|
metadata:
|
|
480
480
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
|
481
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.1.0
|
|
482
|
-
documentation_uri: https://api.rubyonrails.org/v8.1.0
|
|
481
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.1.0/activerecord/CHANGELOG.md
|
|
482
|
+
documentation_uri: https://api.rubyonrails.org/v8.1.0/
|
|
483
483
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
|
484
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.1.0
|
|
484
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.0/activerecord
|
|
485
485
|
rubygems_mfa_required: 'true'
|
|
486
486
|
rdoc_options:
|
|
487
487
|
- "--main"
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "active_support/notifications"
|
|
4
|
-
require "active_record/explain_registry"
|
|
5
|
-
|
|
6
|
-
module ActiveRecord
|
|
7
|
-
class ExplainSubscriber # :nodoc:
|
|
8
|
-
def start(name, id, payload)
|
|
9
|
-
# unused
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def finish(name, id, payload)
|
|
13
|
-
if ExplainRegistry.collect? && !ignore_payload?(payload)
|
|
14
|
-
ExplainRegistry.queries << payload.values_at(:sql, :binds)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on
|
|
19
|
-
# our own EXPLAINs no matter how loopingly beautiful that would be.
|
|
20
|
-
#
|
|
21
|
-
# On the other hand, we want to monitor the performance of our real database
|
|
22
|
-
# queries, not the performance of the access to the query cache.
|
|
23
|
-
IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
|
|
24
|
-
EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i
|
|
25
|
-
def ignore_payload?(payload)
|
|
26
|
-
payload[:exception] ||
|
|
27
|
-
payload[:cached] ||
|
|
28
|
-
IGNORED_PAYLOADS.include?(payload[:name]) ||
|
|
29
|
-
!payload[:sql].match?(EXPLAINED_SQLS)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
ActiveSupport::Notifications.subscribe("sql.active_record", new)
|
|
33
|
-
end
|
|
34
|
-
end
|