activerecord 8.0.0.beta1 → 8.0.0.rc1

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/lib/active_record/associations/has_many_through_association.rb +7 -1
  4. data/lib/active_record/attribute_methods/primary_key.rb +2 -7
  5. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -12
  6. data/lib/active_record/callbacks.rb +1 -1
  7. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +26 -8
  8. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -5
  9. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -1
  10. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -2
  11. data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -1
  12. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -4
  13. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  14. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  15. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -10
  16. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -11
  17. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  18. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +4 -8
  19. data/lib/active_record/connection_adapters/postgresql_adapter.rb +8 -8
  20. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +1 -1
  21. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +0 -2
  22. data/lib/active_record/connection_adapters.rb +0 -56
  23. data/lib/active_record/core.rb +14 -11
  24. data/lib/active_record/enum.rb +54 -72
  25. data/lib/active_record/fixtures.rb +0 -1
  26. data/lib/active_record/gem_version.rb +1 -1
  27. data/lib/active_record/locking/optimistic.rb +1 -1
  28. data/lib/active_record/log_subscriber.rb +5 -11
  29. data/lib/active_record/marshalling.rb +4 -1
  30. data/lib/active_record/migration.rb +0 -5
  31. data/lib/active_record/model_schema.rb +2 -3
  32. data/lib/active_record/query_cache.rb +0 -4
  33. data/lib/active_record/query_logs.rb +5 -11
  34. data/lib/active_record/querying.rb +2 -2
  35. data/lib/active_record/railtie.rb +1 -24
  36. data/lib/active_record/railties/databases.rake +1 -1
  37. data/lib/active_record/reflection.rb +14 -19
  38. data/lib/active_record/relation/calculations.rb +24 -28
  39. data/lib/active_record/relation/predicate_builder.rb +8 -0
  40. data/lib/active_record/relation/query_methods.rb +66 -36
  41. data/lib/active_record/relation.rb +8 -1
  42. data/lib/active_record/result.rb +10 -9
  43. data/lib/active_record/table_metadata.rb +1 -3
  44. data/lib/active_record/tasks/database_tasks.rb +4 -31
  45. data/lib/active_record/testing/query_assertions.rb +2 -2
  46. data/lib/active_record.rb +0 -45
  47. data/lib/arel/table.rb +3 -7
  48. data/lib/arel/visitors/sqlite.rb +25 -0
  49. metadata +9 -10
  50. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -506,7 +506,7 @@ module ActiveRecord
506
506
  #
507
507
  # Post.with_recursive(post_and_replies: [Post.where(id: 42), Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id')])
508
508
  # # => ActiveRecord::Relation
509
- # # WITH post_and_replies AS (
509
+ # # WITH RECURSIVE post_and_replies AS (
510
510
  # # (SELECT * FROM posts WHERE id = 42)
511
511
  # # UNION ALL
512
512
  # # (SELECT * FROM posts JOIN posts_and_replies ON posts.in_reply_to_id = posts_and_replies.id)
@@ -1656,6 +1656,22 @@ module ActiveRecord
1656
1656
  self
1657
1657
  end
1658
1658
 
1659
+ protected
1660
+ def arel_columns(columns)
1661
+ columns.flat_map do |field|
1662
+ case field
1663
+ when Symbol, String
1664
+ arel_column(field)
1665
+ when Proc
1666
+ field.call
1667
+ when Hash
1668
+ arel_columns_from_hash(field)
1669
+ else
1670
+ field
1671
+ end
1672
+ end
1673
+ end
1674
+
1659
1675
  private
1660
1676
  def async
1661
1677
  spawn.async!
@@ -1910,12 +1926,26 @@ module ActiveRecord
1910
1926
  end
1911
1927
  end
1912
1928
 
1913
- def build_with_expression_from_value(value)
1929
+ def build_with_expression_from_value(value, nested = false)
1914
1930
  case value
1915
1931
  when Arel::Nodes::SqlLiteral then Arel::Nodes::Grouping.new(value)
1916
- when ActiveRecord::Relation then value.arel
1932
+ when ActiveRecord::Relation
1933
+ if nested
1934
+ value.arel.ast
1935
+ else
1936
+ value.arel
1937
+ end
1917
1938
  when Arel::SelectManager then value
1918
- when Array then value.map { |q| build_with_expression_from_value(q) }.reduce { |result, value| result.union(:all, value) }
1939
+ when Array
1940
+ return build_with_expression_from_value(value.first, false) if value.size == 1
1941
+
1942
+ parts = value.map do |query|
1943
+ build_with_expression_from_value(query, true)
1944
+ end
1945
+
1946
+ parts.reduce do |result, value|
1947
+ Arel::Nodes::UnionAll.new(result, value)
1948
+ end
1919
1949
  else
1920
1950
  raise ArgumentError, "Unsupported argument type: `#{value}` #{value.class}"
1921
1951
  end
@@ -1929,38 +1959,43 @@ module ActiveRecord
1929
1959
  ).join_sources.first
1930
1960
  end
1931
1961
 
1932
- def arel_columns(columns)
1933
- columns.flat_map do |field|
1934
- case field
1935
- when Symbol
1936
- arel_column(field.to_s) do |attr_name|
1937
- model.adapter_class.quote_table_name(attr_name)
1962
+ def arel_columns_from_hash(fields)
1963
+ fields.flat_map do |table_name, columns|
1964
+ table_name = table_name.name if table_name.is_a?(Symbol)
1965
+ case columns
1966
+ when Symbol, String
1967
+ arel_column_with_table(table_name, columns.to_s)
1968
+ when Array
1969
+ columns.map do |column|
1970
+ arel_column_with_table(table_name, column.to_s)
1938
1971
  end
1939
- when String
1940
- arel_column(field, &:itself)
1941
- when Proc
1942
- field.call
1943
- when Hash
1944
- arel_columns_from_hash(field)
1945
1972
  else
1946
- field
1973
+ raise TypeError, "Expected Symbol, String or Array, got: #{columns.class}"
1947
1974
  end
1948
1975
  end
1949
1976
  end
1950
1977
 
1978
+ def arel_column_with_table(table_name, column_name)
1979
+ self.references_values |= [Arel.sql(table_name, retryable: true)]
1980
+ predicate_builder.resolve_arel_attribute(table_name, column_name) do
1981
+ lookup_table_klass_from_join_dependencies(table_name)
1982
+ end
1983
+ end
1984
+
1951
1985
  def arel_column(field)
1986
+ field = field.name if is_symbol = field.is_a?(Symbol)
1987
+
1952
1988
  field = model.attribute_aliases[field] || field
1953
1989
  from = from_clause.name || from_clause.value
1954
1990
 
1955
1991
  if model.columns_hash.key?(field) && (!from || table_name_matches?(from))
1956
1992
  table[field]
1957
- elsif field.match?(/\A\w+\.\w+\z/)
1958
- table, column = field.split(".")
1959
- predicate_builder.resolve_arel_attribute(table, column) do
1960
- lookup_table_klass_from_join_dependencies(table)
1961
- end
1962
- else
1993
+ elsif /\A(?<table>(?:\w+\.)?\w+)\.(?<column>\w+)\z/ =~ field
1994
+ arel_column_with_table(table, column)
1995
+ elsif block_given?
1963
1996
  yield field
1997
+ else
1998
+ Arel.sql(is_symbol ? model.adapter_class.quote_table_name(field) : field)
1964
1999
  end
1965
2000
  end
1966
2001
 
@@ -2182,34 +2217,29 @@ module ActiveRecord
2182
2217
  def process_select_args(fields)
2183
2218
  fields.flat_map do |field|
2184
2219
  if field.is_a?(Hash)
2185
- arel_columns_from_hash(field)
2220
+ arel_column_aliases_from_hash(field)
2186
2221
  else
2187
2222
  field
2188
2223
  end
2189
2224
  end
2190
2225
  end
2191
2226
 
2192
- def arel_columns_from_hash(fields)
2227
+ def arel_column_aliases_from_hash(fields)
2193
2228
  fields.flat_map do |key, columns_aliases|
2229
+ table_name = key.is_a?(Symbol) ? key.name : key
2194
2230
  case columns_aliases
2195
2231
  when Hash
2196
2232
  columns_aliases.map do |column, column_alias|
2197
- if values[:joins]&.include?(key)
2198
- references = PredicateBuilder.references({ key.to_s => fields[key] })
2199
- self.references_values |= references unless references.empty?
2200
- end
2201
- arel_column("#{key}.#{column}") do
2202
- predicate_builder.resolve_arel_attribute(key.to_s, column)
2203
- end.as(column_alias.to_s)
2233
+ arel_column_with_table(table_name, column.to_s)
2234
+ .as(model.adapter_class.quote_column_name(column_alias.to_s))
2204
2235
  end
2205
2236
  when Array
2206
2237
  columns_aliases.map do |column|
2207
- arel_column("#{key}.#{column}", &:itself)
2238
+ arel_column_with_table(table_name, column.to_s)
2208
2239
  end
2209
2240
  when String, Symbol
2210
- arel_column(key.to_s) do
2211
- predicate_builder.resolve_arel_attribute(model.table_name, key.to_s)
2212
- end.as(columns_aliases.to_s)
2241
+ arel_column(key)
2242
+ .as(model.adapter_class.quote_column_name(columns_aliases.to_s))
2213
2243
  end
2214
2244
  end
2215
2245
  end
@@ -74,7 +74,14 @@ module ActiveRecord
74
74
  alias :loaded? :loaded
75
75
  alias :locked? :lock_value
76
76
 
77
- def initialize(model, table: model.arel_table, predicate_builder: model.predicate_builder, values: {})
77
+ def initialize(model, table: nil, predicate_builder: nil, values: {})
78
+ if table
79
+ predicate_builder ||= model.predicate_builder.with(TableMetadata.new(model, table))
80
+ else
81
+ table = model.arel_table
82
+ predicate_builder ||= model.predicate_builder
83
+ end
84
+
78
85
  @model = model
79
86
  @table = table
80
87
  @values = values
@@ -127,9 +127,9 @@ module ActiveRecord
127
127
  # Returns an +Enumerator+ if no block is given.
128
128
  def each(&block)
129
129
  if block_given?
130
- indexed_rows.each(&block)
130
+ hash_rows.each(&block)
131
131
  else
132
- indexed_rows.to_enum { @rows.size }
132
+ hash_rows.to_enum { @rows.size }
133
133
  end
134
134
  end
135
135
 
@@ -191,6 +191,7 @@ module ActiveRecord
191
191
  def initialize_copy(other)
192
192
  @rows = rows.dup
193
193
  @column_types = column_types.dup
194
+ @hash_rows = nil
194
195
  end
195
196
 
196
197
  def freeze # :nodoc:
@@ -212,6 +213,13 @@ module ActiveRecord
212
213
  end
213
214
  end
214
215
 
216
+ def indexed_rows # :nodoc:
217
+ @indexed_rows ||= begin
218
+ columns = column_indexes
219
+ @rows.map { |row| IndexedRow.new(columns, row) }.freeze
220
+ end
221
+ end
222
+
215
223
  private
216
224
  def column_type(name, index, type_overrides)
217
225
  type_overrides.fetch(name) do
@@ -221,13 +229,6 @@ module ActiveRecord
221
229
  end
222
230
  end
223
231
 
224
- def indexed_rows
225
- @indexed_rows ||= begin
226
- columns = column_indexes
227
- @rows.map { |row| IndexedRow.new(columns, row) }.freeze
228
- end
229
- end
230
-
231
232
  def hash_rows
232
233
  # We use transform_values to rows.
233
234
  # This is faster because we avoid any reallocs and avoid hashing entirely.
@@ -69,9 +69,7 @@ module ActiveRecord
69
69
 
70
70
  def predicate_builder
71
71
  if klass
72
- predicate_builder = klass.predicate_builder.dup
73
- predicate_builder.instance_variable_set(:@table, self)
74
- predicate_builder
72
+ klass.predicate_builder.with(self)
75
73
  else
76
74
  PredicateBuilder.new(self)
77
75
  end
@@ -446,26 +446,10 @@ module ActiveRecord
446
446
  end
447
447
  end
448
448
 
449
- def cache_dump_filename(db_config_or_name, schema_cache_path: nil)
450
- if db_config_or_name.is_a?(DatabaseConfigurations::DatabaseConfig)
451
- schema_cache_path ||
452
- db_config_or_name.schema_cache_path ||
453
- schema_cache_env ||
454
- db_config_or_name.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
455
- else
456
- ActiveRecord.deprecator.warn(<<~MSG.squish)
457
- Passing a database name to `cache_dump_filename` is deprecated and will be removed in Rails 8.0. Pass a
458
- `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object instead.
459
- MSG
460
-
461
- filename = if ActiveRecord::Base.configurations.primary?(db_config_or_name)
462
- "schema_cache.yml"
463
- else
464
- "#{db_config_or_name}_schema_cache.yml"
465
- end
466
-
467
- schema_cache_path || schema_cache_env || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
468
- end
449
+ def cache_dump_filename(db_config, schema_cache_path: nil)
450
+ schema_cache_path ||
451
+ db_config.schema_cache_path ||
452
+ db_config.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
469
453
  end
470
454
 
471
455
  def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
@@ -536,17 +520,6 @@ module ActiveRecord
536
520
  end
537
521
 
538
522
  private
539
- def schema_cache_env
540
- if ENV["SCHEMA_CACHE"]
541
- ActiveRecord.deprecator.warn(<<~MSG.squish)
542
- Setting `ENV["SCHEMA_CACHE"]` is deprecated and will be removed in Rails 8.0.
543
- Configure the `:schema_cache_path` in the database configuration instead.
544
- MSG
545
-
546
- nil
547
- end
548
- end
549
-
550
523
  def with_temporary_pool(db_config, clobber: false)
551
524
  original_db_config = migration_class.connection_db_config
552
525
  pool = migration_class.connection_handler.establish_connection(db_config, clobber: clobber)
@@ -52,7 +52,7 @@ module ActiveRecord
52
52
  # assert_queries_match(/LIMIT \?/) { Post.first }
53
53
  #
54
54
  # If the +:include_schema+ option is provided, any queries (including schema related)
55
- # that match the matcher are considered.
55
+ # that match the matcher are considered.
56
56
  #
57
57
  # assert_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
58
58
  #
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  # assert_no_queries_match(/SELECT/i) { post.comments }
81
81
  #
82
82
  # If the +:include_schema+ option is provided, any queries (including schema related)
83
- # that match the matcher are counted.
83
+ # that match the matcher are counted.
84
84
  #
85
85
  # assert_no_queries_match(/FROM pg_attribute/i, include_schema: true) { Post.columns }
86
86
  #
data/lib/active_record.rb CHANGED
@@ -268,14 +268,6 @@ module ActiveRecord
268
268
  singleton_class.attr_accessor :reading_role
269
269
  self.reading_role = :reading
270
270
 
271
- def self.legacy_connection_handling=(_)
272
- raise ArgumentError, <<~MSG.squish
273
- The `legacy_connection_handling` setter was deprecated in 7.0 and removed in 7.1,
274
- but is still defined in your configuration. Please remove this call as it no longer
275
- has any effect."
276
- MSG
277
- end
278
-
279
271
  ##
280
272
  # :singleton-method: async_query_executor
281
273
  # Sets the async_query_executor for an application. By default the thread pool executor
@@ -359,29 +351,6 @@ module ActiveRecord
359
351
  singleton_class.attr_accessor :run_after_transaction_callbacks_in_order_defined
360
352
  self.run_after_transaction_callbacks_in_order_defined = false
361
353
 
362
- def self.commit_transaction_on_non_local_return
363
- ActiveRecord.deprecator.warn <<-WARNING.squish
364
- `Rails.application.config.active_record.commit_transaction_on_non_local_return`
365
- is deprecated and will be removed in Rails 8.0.
366
- WARNING
367
- end
368
-
369
- def self.commit_transaction_on_non_local_return=(value)
370
- ActiveRecord.deprecator.warn <<-WARNING.squish
371
- `Rails.application.config.active_record.commit_transaction_on_non_local_return`
372
- is deprecated and will be removed in Rails 8.0.
373
- WARNING
374
- end
375
-
376
- ##
377
- # :singleton-method: warn_on_records_fetched_greater_than
378
- # Specify a threshold for the size of query result sets. If the number of
379
- # records in the set exceeds the threshold, a warning is logged. This can
380
- # be used to identify queries which load thousands of records and
381
- # potentially cause memory bloat.
382
- singleton_class.attr_accessor :warn_on_records_fetched_greater_than
383
- self.warn_on_records_fetched_greater_than = false
384
-
385
354
  singleton_class.attr_accessor :application_record_class
386
355
  self.application_record_class = nil
387
356
 
@@ -459,20 +428,6 @@ module ActiveRecord
459
428
  singleton_class.attr_accessor :verify_foreign_keys_for_fixtures
460
429
  self.verify_foreign_keys_for_fixtures = false
461
430
 
462
- def self.allow_deprecated_singular_associations_name
463
- ActiveRecord.deprecator.warn <<-WARNING.squish
464
- `Rails.application.config.active_record.allow_deprecated_singular_associations_name`
465
- is deprecated and will be removed in Rails 8.0.
466
- WARNING
467
- end
468
-
469
- def self.allow_deprecated_singular_associations_name=(value)
470
- ActiveRecord.deprecator.warn <<-WARNING.squish
471
- `Rails.application.config.active_record.allow_deprecated_singular_associations_name`
472
- is deprecated and will be removed in Rails 8.0.
473
- WARNING
474
- end
475
-
476
431
  singleton_class.attr_accessor :query_transformers
477
432
  self.query_transformers = []
478
433
 
data/lib/arel/table.rb CHANGED
@@ -12,13 +12,9 @@ module Arel # :nodoc: all
12
12
  attr_reader :table_alias
13
13
 
14
14
  def initialize(name, as: nil, klass: nil, type_caster: klass&.type_caster)
15
- @name =
16
- case name
17
- when Symbol then name.to_s
18
- else
19
- name
20
- end
15
+ name = name.name if name.is_a?(Symbol)
21
16
 
17
+ @name = name
22
18
  @klass = klass
23
19
  @type_caster = type_caster
24
20
 
@@ -84,7 +80,7 @@ module Arel # :nodoc: all
84
80
  end
85
81
 
86
82
  def [](name, table = self)
87
- name = name.to_s if name.is_a?(Symbol)
83
+ name = name.name if name.is_a?(Symbol)
88
84
  name = @klass.attribute_aliases[name] || name if @klass
89
85
  Attribute.new(table, name)
90
86
  end
@@ -33,6 +33,31 @@ module Arel # :nodoc: all
33
33
  collector << " IS NOT "
34
34
  visit o.right, collector
35
35
  end
36
+
37
+ # Queries used in UNION should not be wrapped by parentheses,
38
+ # because it is an invalid syntax in SQLite.
39
+ def infix_value_with_paren(o, collector, value, suppress_parens = false)
40
+ collector << "( " unless suppress_parens
41
+
42
+ left = o.left.is_a?(Nodes::Grouping) ? o.left.expr : o.left
43
+ collector = if left.class == o.class
44
+ infix_value_with_paren(left, collector, value, true)
45
+ else
46
+ grouping_parentheses left, collector, false
47
+ end
48
+
49
+ collector << value
50
+
51
+ right = o.right.is_a?(Nodes::Grouping) ? o.right.expr : o.right
52
+ collector = if right.class == o.class
53
+ infix_value_with_paren(right, collector, value, true)
54
+ else
55
+ grouping_parentheses right, collector, false
56
+ end
57
+
58
+ collector << " )" unless suppress_parens
59
+ collector
60
+ end
36
61
  end
37
62
  end
38
63
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0.beta1
4
+ version: 8.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-26 00:00:00.000000000 Z
11
+ date: 2024-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 8.0.0.beta1
19
+ version: 8.0.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 8.0.0.beta1
26
+ version: 8.0.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 8.0.0.beta1
33
+ version: 8.0.0.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 8.0.0.beta1
40
+ version: 8.0.0.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: timeout
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -318,7 +318,6 @@ files:
318
318
  - lib/active_record/relation/predicate_builder/relation_handler.rb
319
319
  - lib/active_record/relation/query_attribute.rb
320
320
  - lib/active_record/relation/query_methods.rb
321
- - lib/active_record/relation/record_fetch_warning.rb
322
321
  - lib/active_record/relation/spawn_methods.rb
323
322
  - lib/active_record/relation/where_clause.rb
324
323
  - lib/active_record/result.rb
@@ -476,10 +475,10 @@ licenses:
476
475
  - MIT
477
476
  metadata:
478
477
  bug_tracker_uri: https://github.com/rails/rails/issues
479
- changelog_uri: https://github.com/rails/rails/blob/v8.0.0.beta1/activerecord/CHANGELOG.md
480
- documentation_uri: https://api.rubyonrails.org/v8.0.0.beta1/
478
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.rc1/activerecord/CHANGELOG.md
479
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.rc1/
481
480
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
482
- source_code_uri: https://github.com/rails/rails/tree/v8.0.0.beta1/activerecord
481
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.rc1/activerecord
483
482
  rubygems_mfa_required: 'true'
484
483
  post_install_message:
485
484
  rdoc_options:
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecord
4
- class Relation
5
- module RecordFetchWarning
6
- # Deprecated: subscribe to sql.active_record notifications and
7
- # access the row count field to detect large result set sizes.
8
- #
9
- # When this module is prepended to ActiveRecord::Relation and
10
- # +config.active_record.warn_on_records_fetched_greater_than+ is
11
- # set to an integer, if the number of records a query returns is
12
- # greater than the value of +warn_on_records_fetched_greater_than+,
13
- # a warning is logged. This allows for the detection of queries that
14
- # return a large number of records, which could cause memory bloat.
15
- #
16
- # In most cases, fetching large number of records can be performed
17
- # efficiently using the ActiveRecord::Batches methods.
18
- # See ActiveRecord::Batches for more information.
19
- def exec_queries
20
- QueryRegistry.reset
21
-
22
- super.tap do |records|
23
- if model.logger && ActiveRecord.warn_on_records_fetched_greater_than
24
- if records.length > ActiveRecord.warn_on_records_fetched_greater_than
25
- model.logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
26
- end
27
- end
28
- end
29
- end
30
-
31
- # :stopdoc:
32
- ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
33
- QueryRegistry.queries << payload[:sql]
34
- end
35
- # :startdoc:
36
-
37
- module QueryRegistry # :nodoc:
38
- extend self
39
-
40
- def queries
41
- ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
42
- end
43
-
44
- def reset
45
- queries.clear
46
- end
47
- end
48
- end
49
- end
50
- end
51
-
52
- ActiveRecord::Relation.prepend ActiveRecord::Relation::RecordFetchWarning