activerecord 7.0.0.alpha2 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +539 -11
  3. data/lib/active_record/associations/association.rb +2 -8
  4. data/lib/active_record/associations/builder/collection_association.rb +9 -2
  5. data/lib/active_record/associations/collection_association.rb +10 -2
  6. data/lib/active_record/associations/join_dependency.rb +6 -2
  7. data/lib/active_record/associations/preloader/association.rb +68 -48
  8. data/lib/active_record/associations/preloader/batch.rb +3 -6
  9. data/lib/active_record/associations/preloader/through_association.rb +19 -9
  10. data/lib/active_record/associations/preloader.rb +14 -24
  11. data/lib/active_record/associations/through_association.rb +2 -2
  12. data/lib/active_record/associations.rb +16 -3
  13. data/lib/active_record/asynchronous_queries_tracker.rb +3 -0
  14. data/lib/active_record/attribute_methods/dirty.rb +9 -1
  15. data/lib/active_record/attribute_methods.rb +7 -5
  16. data/lib/active_record/autosave_association.rb +3 -3
  17. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +6 -26
  18. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -2
  19. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -5
  20. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  21. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  22. data/lib/active_record/connection_adapters/abstract/quoting.rb +33 -70
  23. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  24. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +9 -2
  25. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -19
  26. data/lib/active_record/connection_adapters/abstract_adapter.rb +37 -8
  27. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/column.rb +4 -0
  29. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -2
  30. data/lib/active_record/connection_adapters/mysql/quoting.rb +23 -24
  31. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
  32. data/lib/active_record/connection_adapters/pool_config.rb +7 -5
  33. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
  34. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +2 -0
  35. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -44
  36. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  37. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +18 -1
  38. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  39. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -4
  40. data/lib/active_record/connection_adapters/postgresql_adapter.rb +48 -5
  41. data/lib/active_record/connection_adapters/schema_cache.rb +3 -1
  42. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +4 -2
  43. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
  44. data/lib/active_record/connection_handling.rb +31 -19
  45. data/lib/active_record/core.rb +13 -24
  46. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  47. data/lib/active_record/database_configurations/database_config.rb +0 -9
  48. data/lib/active_record/database_configurations/hash_config.rb +40 -8
  49. data/lib/active_record/database_configurations.rb +2 -27
  50. data/lib/active_record/delegated_type.rb +19 -0
  51. data/lib/active_record/encryption/encryptable_record.rb +1 -1
  52. data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
  53. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -2
  54. data/lib/active_record/encryption/message_serializer.rb +11 -1
  55. data/lib/active_record/encryption/scheme.rb +1 -1
  56. data/lib/active_record/enum.rb +8 -1
  57. data/lib/active_record/errors.rb +1 -1
  58. data/lib/active_record/explain_registry.rb +11 -6
  59. data/lib/active_record/fixture_set/table_row.rb +1 -1
  60. data/lib/active_record/fixtures.rb +1 -9
  61. data/lib/active_record/future_result.rb +2 -2
  62. data/lib/active_record/gem_version.rb +1 -1
  63. data/lib/active_record/insert_all.rb +52 -15
  64. data/lib/active_record/integration.rb +3 -2
  65. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  66. data/lib/active_record/locking/pessimistic.rb +9 -3
  67. data/lib/active_record/log_subscriber.rb +8 -1
  68. data/lib/active_record/middleware/shard_selector.rb +60 -0
  69. data/lib/active_record/migration.rb +2 -2
  70. data/lib/active_record/model_schema.rb +1 -28
  71. data/lib/active_record/nested_attributes.rb +11 -10
  72. data/lib/active_record/no_touching.rb +1 -1
  73. data/lib/active_record/persistence.rb +99 -21
  74. data/lib/active_record/query_logs.rb +18 -83
  75. data/lib/active_record/railtie.rb +11 -1
  76. data/lib/active_record/railties/databases.rake +4 -91
  77. data/lib/active_record/reflection.rb +22 -6
  78. data/lib/active_record/relation/calculations.rb +1 -10
  79. data/lib/active_record/relation/finder_methods.rb +0 -13
  80. data/lib/active_record/relation/query_methods.rb +5 -14
  81. data/lib/active_record/relation/record_fetch_warning.rb +5 -7
  82. data/lib/active_record/relation/where_clause.rb +2 -15
  83. data/lib/active_record/relation.rb +11 -15
  84. data/lib/active_record/result.rb +0 -5
  85. data/lib/active_record/runtime_registry.rb +10 -12
  86. data/lib/active_record/schema_dumper.rb +7 -0
  87. data/lib/active_record/schema_migration.rb +4 -0
  88. data/lib/active_record/scoping.rb +34 -22
  89. data/lib/active_record/suppressor.rb +11 -15
  90. data/lib/active_record/tasks/database_tasks.rb +18 -44
  91. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -1
  92. data/lib/active_record/validations/uniqueness.rb +1 -1
  93. data/lib/active_record.rb +41 -33
  94. data/lib/arel/crud.rb +12 -2
  95. data/lib/arel/delete_manager.rb +16 -0
  96. data/lib/arel/filter_predications.rb +9 -0
  97. data/lib/arel/nodes/delete_statement.rb +5 -1
  98. data/lib/arel/nodes/filter.rb +10 -0
  99. data/lib/arel/nodes/function.rb +1 -0
  100. data/lib/arel/nodes/update_statement.rb +5 -1
  101. data/lib/arel/nodes.rb +1 -0
  102. data/lib/arel/predications.rb +10 -2
  103. data/lib/arel/update_manager.rb +16 -0
  104. data/lib/arel/visitors/mysql.rb +2 -1
  105. data/lib/arel/visitors/to_sql.rb +15 -0
  106. data/lib/arel.rb +1 -0
  107. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  108. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  109. metadata +18 -12
@@ -332,7 +332,7 @@ db_namespace = namespace :db do
332
332
 
333
333
  desc "Retrieves the current schema version number"
334
334
  task version: :load_config do
335
- puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
335
+ puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
336
336
  end
337
337
 
338
338
  # desc "Raises an error if there are pending migrations"
@@ -469,14 +469,6 @@ db_namespace = namespace :db do
469
469
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
470
470
  end
471
471
 
472
- task load_if_ruby: ["db:create", :environment] do
473
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
474
- Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
475
- Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
476
- MSG
477
- db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :ruby
478
- end
479
-
480
472
  namespace :dump do
481
473
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
482
474
  desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
@@ -495,7 +487,7 @@ db_namespace = namespace :db do
495
487
  task name => :load_config do
496
488
  original_db_config = ActiveRecord::Base.connection_db_config
497
489
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
498
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, ENV["SCHEMA"])
490
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
499
491
  ensure
500
492
  ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
501
493
  end
@@ -533,63 +525,6 @@ db_namespace = namespace :db do
533
525
  end
534
526
  end
535
527
 
536
- namespace :structure do
537
- desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
538
- task dump: :load_config do
539
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
540
- Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 7.0.
541
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
542
- MSG
543
-
544
- db_namespace["schema:dump"].invoke
545
- db_namespace["structure:dump"].reenable
546
- end
547
-
548
- desc "Recreates the databases from the structure.sql file"
549
- task load: [:load_config, :check_protected_environments] do
550
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
551
- Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 7.0.
552
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
553
- MSG
554
- db_namespace["schema:load"].invoke
555
- end
556
-
557
- task load_if_sql: ["db:create", :environment] do
558
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
559
- Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
560
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
561
- MSG
562
- db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :sql
563
- end
564
-
565
- namespace :dump do
566
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
567
- desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
568
- task name => :load_config do
569
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
570
- Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 7.0.
571
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
572
- MSG
573
- db_namespace["schema:dump:#{name}"].invoke
574
- db_namespace["structure:dump:#{name}"].reenable
575
- end
576
- end
577
- end
578
-
579
- namespace :load do
580
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
581
- desc "Recreates the #{name} database from the structure.sql file"
582
- task name => :load_config do
583
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
584
- Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 7.0.
585
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
586
- MSG
587
- db_namespace["schema:load:#{name}"].invoke
588
- end
589
- end
590
- end
591
- end
592
-
593
528
  namespace :encryption do
594
529
  desc "Generate a set of keys for configuring Active Record encryption in a given environment"
595
530
  task :init do
@@ -615,8 +550,7 @@ db_namespace = namespace :db do
615
550
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
616
551
  ActiveRecord::Schema.verbose = false
617
552
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
618
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.name)
619
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
553
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
620
554
  end
621
555
  ensure
622
556
  if should_reconnect
@@ -624,15 +558,6 @@ db_namespace = namespace :db do
624
558
  end
625
559
  end
626
560
 
627
- # desc "Recreate the test database from an existent structure.sql file"
628
- task load_structure: %w(db:test:purge) do
629
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
630
- Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 7.0.
631
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
632
- MSG
633
- db_namespace["test:load_schema"].invoke
634
- end
635
-
636
561
  # desc "Empty the test database"
637
562
  task purge: %w(load_config check_protected_environments) do
638
563
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
@@ -660,9 +585,8 @@ db_namespace = namespace :db do
660
585
  task name => "db:test:purge:#{name}" do
661
586
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
662
587
  ActiveRecord::Schema.verbose = false
663
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
664
588
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
665
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
589
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
666
590
  ensure
667
591
  if should_reconnect
668
592
  ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
@@ -670,17 +594,6 @@ db_namespace = namespace :db do
670
594
  end
671
595
  end
672
596
 
673
- # desc "Recreate the #{name} test database from an existent structure.sql file"
674
- namespace :load_structure do
675
- task name => "db:test:purge:#{name}" do
676
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
677
- Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 7.0.
678
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
679
- MSG
680
- db_namespace["test:load_schema:#{name}"].invoke
681
- end
682
- end
683
-
684
597
  # desc "Empty the #{name} test database"
685
598
  namespace :purge do
686
599
  task name => %w(load_config check_protected_environments) do
@@ -10,6 +10,7 @@ module ActiveRecord
10
10
  included do
11
11
  class_attribute :_reflections, instance_writer: false, default: {}
12
12
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
13
+ class_attribute :automatic_scope_inversing, instance_writer: false, default: false
13
14
  end
14
15
 
15
16
  class << self
@@ -234,6 +235,9 @@ module ActiveRecord
234
235
  if has_inverse? && inverse_of.nil?
235
236
  raise InverseOfAssociationNotFoundError.new(self)
236
237
  end
238
+ if has_inverse? && inverse_of == self
239
+ raise InverseOfAssociationRecursiveError.new(self)
240
+ end
237
241
  end
238
242
  end
239
243
 
@@ -631,9 +635,10 @@ module ActiveRecord
631
635
  # with the current reflection's klass name.
632
636
  def valid_inverse_reflection?(reflection)
633
637
  reflection &&
638
+ reflection != self &&
634
639
  foreign_key == reflection.foreign_key &&
635
640
  klass <= reflection.active_record &&
636
- can_find_inverse_of_automatically?(reflection)
641
+ can_find_inverse_of_automatically?(reflection, true)
637
642
  end
638
643
 
639
644
  # Checks to see if the reflection doesn't have any options that prevent
@@ -642,14 +647,25 @@ module ActiveRecord
642
647
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
643
648
  # Third, we must not have options such as <tt>:foreign_key</tt>
644
649
  # which prevent us from correctly guessing the inverse association.
645
- #
646
- # Anything with a scope can additionally ruin our attempt at finding an
647
- # inverse, so we exclude reflections with scopes.
648
- def can_find_inverse_of_automatically?(reflection)
650
+ def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
649
651
  reflection.options[:inverse_of] != false &&
650
652
  !reflection.options[:through] &&
651
653
  !reflection.options[:foreign_key] &&
654
+ scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
655
+ end
656
+
657
+ # Scopes on the potential inverse reflection prevent automatic
658
+ # <tt>inverse_of</tt>, since the scope could exclude the owner record
659
+ # we would inverse from. Scopes on the reflection itself allow for
660
+ # automatic <tt>inverse_of</tt> as long as
661
+ # <tt>config.active_record.automatic_scope_inversing<tt> is set to
662
+ # +true+ (the default for new applications).
663
+ def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
664
+ if inverse_reflection
652
665
  !reflection.scope
666
+ else
667
+ !reflection.scope || reflection.klass.automatic_scope_inversing
668
+ end
653
669
  end
654
670
 
655
671
  def derive_class_name
@@ -736,7 +752,7 @@ module ActiveRecord
736
752
  end
737
753
 
738
754
  private
739
- def can_find_inverse_of_automatically?(_)
755
+ def can_find_inverse_of_automatically?(*)
740
756
  !polymorphic? && super
741
757
  end
742
758
  end
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  #
32
32
  # Article.group(:status, :category).count
33
33
  # # => {["draft", "business"]=>10, ["draft", "technology"]=>4,
34
- # ["published", "business"]=>0, ["published", "technology"]=>2}
34
+ # # ["published", "business"]=>0, ["published", "technology"]=>2}
35
35
  #
36
36
  # If #count is used with {Relation#select}[rdoc-ref:QueryMethods#select], it will count the selected columns:
37
37
  #
@@ -329,15 +329,6 @@ module ActiveRecord
329
329
  group_fields = group_values
330
330
  group_fields = group_fields.uniq if group_fields.size > 1
331
331
 
332
- unless group_fields == group_values
333
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
334
- `#{operation}` with group by duplicated fields does no longer affect to result in Rails 7.0.
335
- To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields
336
- (`#{klass.name&.tableize || klass.table_name}.uniq!(:group).#{operation}(#{column_name.inspect})`).
337
- MSG
338
- group_fields = group_values
339
- end
340
-
341
332
  if group_fields.size == 1 && group_fields.first.respond_to?(:to_sym)
342
333
  association = klass._reflect_on_association(group_fields.first)
343
334
  associated = association && association.belongs_to? # only count belongs_to associations
@@ -140,8 +140,6 @@ module ActiveRecord
140
140
  # Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
141
141
  #
142
142
  def first(limit = nil)
143
- check_reorder_deprecation unless loaded?
144
-
145
143
  if limit
146
144
  find_nth_with_limit(0, limit)
147
145
  else
@@ -390,17 +388,6 @@ module ActiveRecord
390
388
  end
391
389
 
392
390
  private
393
- def check_reorder_deprecation
394
- if !order_values.empty? && order_values.all?(&:blank?)
395
- blank_value = order_values.first
396
- ActiveSupport::Deprecation.warn(<<~MSG.squish)
397
- `.reorder(#{blank_value.inspect})` with `.first` / `.first!` no longer
398
- takes non-deterministic result in Rails 7.0.
399
- To continue taking non-deterministic result, use `.take` / `.take!` instead.
400
- MSG
401
- end
402
- end
403
-
404
391
  def construct_relation_for_exists(conditions)
405
392
  conditions = sanitize_forbidden_attributes(conditions)
406
393
 
@@ -432,6 +432,7 @@ module ActiveRecord
432
432
  references = column_references([column])
433
433
  self.references_values |= references unless references.empty?
434
434
 
435
+ values = values.map { |value| type_caster.type_cast_for_database(column, value) }
435
436
  column = order_column(column.to_s) if column.is_a?(Symbol)
436
437
 
437
438
  spawn.order!(connection.field_ordered_value(column, values))
@@ -448,14 +449,14 @@ module ActiveRecord
448
449
  # generates a query with 'ORDER BY id ASC, name ASC'.
449
450
  def reorder(*args)
450
451
  check_if_method_has_arguments!(__callee__, args) do
451
- sanitize_order_arguments(args) unless args.all?(&:blank?)
452
+ sanitize_order_arguments(args)
452
453
  end
453
454
  spawn.reorder!(*args)
454
455
  end
455
456
 
456
457
  # Same as #reorder but operates on relation in-place instead of copying.
457
458
  def reorder!(*args) # :nodoc:
458
- preprocess_order_args(args) unless args.all?(&:blank?)
459
+ preprocess_order_args(args)
459
460
  args.uniq!
460
461
  self.reordering_value = true
461
462
  self.order_values = args
@@ -1339,14 +1340,6 @@ module ActiveRecord
1339
1340
  unless annotate_values.empty?
1340
1341
  annotates = annotate_values
1341
1342
  annotates = annotates.uniq if annotates.size > 1
1342
- unless annotates == annotate_values
1343
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
1344
- Duplicated query annotations are no longer shown in queries in Rails 7.0.
1345
- To migrate to Rails 7.0's behavior, use `uniq!(:annotate)` to deduplicate query annotations
1346
- (`#{klass.name&.tableize || klass.table_name}.uniq!(:annotate)`).
1347
- MSG
1348
- annotates = annotate_values
1349
- end
1350
1343
  arel.comment(*annotates)
1351
1344
  end
1352
1345
 
@@ -1606,8 +1599,6 @@ module ActiveRecord
1606
1599
  order_args.map! do |arg|
1607
1600
  klass.sanitize_sql_for_order(arg)
1608
1601
  end
1609
- order_args.flatten!
1610
- order_args.compact_blank!
1611
1602
  end
1612
1603
 
1613
1604
  def column_references(order_args)
@@ -1676,9 +1667,9 @@ module ActiveRecord
1676
1667
  def check_if_method_has_arguments!(method_name, args, message = nil)
1677
1668
  if args.blank?
1678
1669
  raise ArgumentError, message || "The method .#{method_name}() must contain arguments."
1679
- elsif block_given?
1680
- yield args
1681
1670
  else
1671
+ yield args if block_given?
1672
+
1682
1673
  args.flatten!
1683
1674
  args.compact_blank!
1684
1675
  end
@@ -31,17 +31,15 @@ module ActiveRecord
31
31
  end
32
32
  # :startdoc:
33
33
 
34
- class QueryRegistry # :nodoc:
35
- extend ActiveSupport::PerThreadRegistry
34
+ module QueryRegistry # :nodoc:
35
+ extend self
36
36
 
37
- attr_reader :queries
38
-
39
- def initialize
40
- @queries = []
37
+ def queries
38
+ ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
41
39
  end
42
40
 
43
41
  def reset
44
- @queries.clear
42
+ queries.clear
45
43
  end
46
44
  end
47
45
  end
@@ -163,21 +163,8 @@ module ActiveRecord
163
163
  attr = extract_attribute(node) || begin
164
164
  node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
165
165
  end
166
- next false unless attr
167
-
168
- ref = referenced_columns[attr]
169
- next false unless ref
170
-
171
- if equality_node?(node) && equality_node?(ref) || node == ref
172
- true
173
- else
174
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
175
- Merging (#{node.to_sql}) and (#{ref.to_sql}) no longer maintain
176
- both conditions, and will be replaced by the latter in Rails 7.0.
177
- To migrate to Rails 7.0's behavior, use `relation.merge(other, rewhere: true)`.
178
- MSG
179
- false
180
- end
166
+
167
+ attr && referenced_columns[attr]
181
168
  end
182
169
  end
183
170
 
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  :reverse_order, :distinct, :create_with, :skip_query_cache]
12
12
 
13
13
  CLAUSE_METHODS = [:where, :having, :from]
14
- INVALID_METHODS_FOR_DELETE_ALL = [:distinct, :group, :having]
14
+ INVALID_METHODS_FOR_DELETE_ALL = [:distinct]
15
15
 
16
16
  VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
17
17
 
@@ -33,7 +33,6 @@ module ActiveRecord
33
33
  @delegate_to_klass = false
34
34
  @future_result = nil
35
35
  @records = nil
36
- @limited_count = nil
37
36
  end
38
37
 
39
38
  def initialize_copy(other)
@@ -41,11 +40,6 @@ module ActiveRecord
41
40
  reset
42
41
  end
43
42
 
44
- def arel_attribute(name) # :nodoc:
45
- table[name]
46
- end
47
- deprecate :arel_attribute
48
-
49
43
  def bind_attribute(name, value) # :nodoc:
50
44
  if reflection = klass._reflect_on_association(name)
51
45
  name = reflection.foreign_key
@@ -295,14 +289,14 @@ module ActiveRecord
295
289
  # Returns true if there is exactly one record.
296
290
  def one?
297
291
  return super if block_given?
298
- return records.one? if limit_value || loaded?
292
+ return records.one? if loaded?
299
293
  limited_count == 1
300
294
  end
301
295
 
302
296
  # Returns true if there is more than one record.
303
297
  def many?
304
298
  return super if block_given?
305
- return records.many? if limit_value || loaded?
299
+ return records.many? if loaded?
306
300
  limited_count > 1
307
301
  end
308
302
 
@@ -394,7 +388,7 @@ module ActiveRecord
394
388
  end
395
389
 
396
390
  if timestamp
397
- "#{size}-#{timestamp.utc.to_s(cache_timestamp_format)}"
391
+ "#{size}-#{timestamp.utc.to_formatted_s(cache_timestamp_format)}"
398
392
  else
399
393
  "#{size}"
400
394
  end
@@ -485,8 +479,9 @@ module ActiveRecord
485
479
  arel = eager_loading? ? apply_join_dependency.arel : build_arel
486
480
  arel.source.left = table
487
481
 
488
- stmt = arel.compile_update(values, table[primary_key])
489
-
482
+ group_values_arel_columns = arel_columns(group_values.uniq)
483
+ having_clause_ast = having_clause.ast unless having_clause.empty?
484
+ stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
490
485
  klass.connection.update(stmt, "#{klass} Update All").tap { reset }
491
486
  end
492
487
 
@@ -615,7 +610,9 @@ module ActiveRecord
615
610
  arel = eager_loading? ? apply_join_dependency.arel : build_arel
616
611
  arel.source.left = table
617
612
 
618
- stmt = arel.compile_delete(table[primary_key])
613
+ group_values_arel_columns = arel_columns(group_values.uniq)
614
+ having_clause_ast = having_clause.ast unless having_clause.empty?
615
+ stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
619
616
 
620
617
  klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
621
618
  end
@@ -701,7 +698,6 @@ module ActiveRecord
701
698
  @offsets = @take = nil
702
699
  @cache_keys = nil
703
700
  @records = nil
704
- @limited_count = nil
705
701
  self
706
702
  end
707
703
 
@@ -976,7 +972,7 @@ module ActiveRecord
976
972
  end
977
973
 
978
974
  def limited_count
979
- @limited_count ||= limit(2).count
975
+ limit_value ? count : limit(2).count
980
976
  end
981
977
  end
982
978
  end
@@ -72,11 +72,6 @@ module ActiveRecord
72
72
  end
73
73
  end
74
74
 
75
- alias :map! :map
76
- alias :collect! :map
77
- deprecate "map!": :map
78
- deprecate "collect!": :map
79
-
80
75
  # Returns true if there are no records, otherwise false.
81
76
  def empty?
82
77
  rows.empty?
@@ -1,22 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/per_thread_registry"
4
-
5
3
  module ActiveRecord
6
4
  # This is a thread locals registry for Active Record. For example:
7
5
  #
8
- # ActiveRecord::RuntimeRegistry.connection_handler
9
- #
10
- # returns the connection handler local to the current thread.
6
+ # ActiveRecord::RuntimeRegistry.sql_runtime
11
7
  #
12
- # See the documentation of ActiveSupport::PerThreadRegistry
13
- # for further details.
14
- class RuntimeRegistry # :nodoc:
15
- extend ActiveSupport::PerThreadRegistry
8
+ # returns the connection handler local to the current unit of execution (either thread of fiber).
9
+ module RuntimeRegistry # :nodoc:
10
+ extend self
16
11
 
17
- attr_accessor :sql_runtime
12
+ def sql_runtime
13
+ ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime]
14
+ end
18
15
 
19
- def self.sql_runtime; instance.sql_runtime; end
20
- def self.sql_runtime=(x); instance.sql_runtime = x; end
16
+ def sql_runtime=(runtime)
17
+ ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
18
+ end
21
19
  end
22
20
  end
@@ -47,6 +47,7 @@ module ActiveRecord
47
47
  def dump(stream)
48
48
  header(stream)
49
49
  extensions(stream)
50
+ types(stream)
50
51
  tables(stream)
51
52
  trailer(stream)
52
53
  stream
@@ -99,6 +100,10 @@ HEADER
99
100
  def extensions(stream)
100
101
  end
101
102
 
103
+ # (enum) types are only supported by PostgreSQL
104
+ def types(stream)
105
+ end
106
+
102
107
  def tables(stream)
103
108
  sorted_tables = @connection.tables.sort
104
109
 
@@ -154,6 +159,7 @@ HEADER
154
159
  columns.each do |column|
155
160
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
156
161
  next if column.name == pk
162
+
157
163
  type, colspec = column_spec(column)
158
164
  if type.is_a?(Symbol)
159
165
  tbl.print " t.#{type} #{column.name.inspect}"
@@ -259,6 +265,7 @@ HEADER
259
265
 
260
266
  parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
261
267
  parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
268
+ parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
262
269
 
263
270
  " #{parts.join(', ')}"
264
271
  end
@@ -41,6 +41,10 @@ module ActiveRecord
41
41
  def all_versions
42
42
  order(:version).pluck(:version)
43
43
  end
44
+
45
+ def table_exists?
46
+ connection.data_source_exists?(table_name)
47
+ end
44
48
  end
45
49
 
46
50
  def version
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/per_thread_registry"
3
+ require "active_support/core_ext/module/delegation"
4
4
 
5
5
  module ActiveRecord
6
6
  module Scoping
@@ -57,8 +57,8 @@ module ActiveRecord
57
57
  end
58
58
 
59
59
  # This class stores the +:current_scope+ and +:ignore_default_scope+ values
60
- # for different classes. The registry is stored as a thread local, which is
61
- # accessed through +ScopeRegistry.current+.
60
+ # for different classes. The registry is stored as either a thread or fiber
61
+ # local depending on the application configuration.
62
62
  #
63
63
  # This class allows you to store and get the scope values on different
64
64
  # classes and different types of scopes. For example, if you are attempting
@@ -66,22 +66,22 @@ module ActiveRecord
66
66
  # following code:
67
67
  #
68
68
  # registry = ActiveRecord::Scoping::ScopeRegistry
69
- # registry.set_value_for(:current_scope, Board, some_new_scope)
69
+ # registry.set_current_scope(Board, some_new_scope)
70
70
  #
71
71
  # Now when you run:
72
72
  #
73
- # registry.value_for(:current_scope, Board)
73
+ # registry.current_scope(Board)
74
74
  #
75
- # You will obtain whatever was defined in +some_new_scope+. The #value_for
76
- # and #set_value_for methods are delegated to the current ScopeRegistry
77
- # object, so the above example code can also be called as:
78
- #
79
- # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
80
- # Board, some_new_scope)
75
+ # You will obtain whatever was defined in +some_new_scope+.
81
76
  class ScopeRegistry # :nodoc:
82
- extend ActiveSupport::PerThreadRegistry
77
+ class << self
78
+ delegate :current_scope, :set_current_scope, :ignore_default_scope, :set_ignore_default_scope,
79
+ :global_current_scope, :set_global_current_scope, to: :instance
83
80
 
84
- VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope, :global_current_scope]
81
+ def instance
82
+ ActiveSupport::IsolatedExecutionState[:active_record_scope_registry] ||= new
83
+ end
84
+ end
85
85
 
86
86
  def initialize
87
87
  @current_scope = {}
@@ -89,16 +89,28 @@ module ActiveRecord
89
89
  @global_current_scope = {}
90
90
  end
91
91
 
92
- VALID_SCOPE_TYPES.each do |type|
93
- class_eval <<-eorb, __FILE__, __LINE__
94
- def #{type}(model, skip_inherited_scope = false)
95
- value_for(@#{type}, model, skip_inherited_scope)
96
- end
92
+ def current_scope(model, skip_inherited_scope = false)
93
+ value_for(@current_scope, model, skip_inherited_scope)
94
+ end
97
95
 
98
- def set_#{type}(model, value)
99
- set_value_for(@#{type}, model, value)
100
- end
101
- eorb
96
+ def set_current_scope(model, value)
97
+ set_value_for(@current_scope, model, value)
98
+ end
99
+
100
+ def ignore_default_scope(model, skip_inherited_scope = false)
101
+ value_for(@ignore_default_scope, model, skip_inherited_scope)
102
+ end
103
+
104
+ def set_ignore_default_scope(model, value)
105
+ set_value_for(@ignore_default_scope, model, value)
106
+ end
107
+
108
+ def global_current_scope(model, skip_inherited_scope = false)
109
+ value_for(@global_current_scope, model, skip_inherited_scope)
110
+ end
111
+
112
+ def set_global_current_scope(model, value)
113
+ set_value_for(@global_current_scope, model, value)
102
114
  end
103
115
 
104
116
  private