activerecord 6.1.7.10 → 7.0.0.alpha1
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +726 -1404
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +31 -9
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +14 -23
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +161 -47
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +41 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +111 -125
- data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +17 -9
- data/lib/active_record/delegated_type.rb +33 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +80 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +41 -41
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +34 -5
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +89 -10
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -31
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +72 -48
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +39 -26
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -22
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +230 -49
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +8 -4
- data/lib/active_record/relation.rb +166 -77
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +1 -6
- data/lib/active_record/tasks/database_tasks.rb +106 -22
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -13
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +3 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +43 -2
- data/lib/arel.rb +1 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +52 -14
| @@ -59,17 +59,13 @@ module ActiveRecord | |
| 59 59 | 
             
                  end
         | 
| 60 60 |  | 
| 61 61 | 
             
                  # Returns an ActiveRecord::Result instance.
         | 
| 62 | 
            -
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         | 
| 62 | 
            +
                  def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
         | 
| 63 63 | 
             
                    arel = arel_from_relation(arel)
         | 
| 64 64 | 
             
                    sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
         | 
| 65 65 |  | 
| 66 | 
            -
                     | 
| 67 | 
            -
                      select_prepared(sql, name, binds)
         | 
| 68 | 
            -
                    else
         | 
| 69 | 
            -
                      select(sql, name, binds)
         | 
| 70 | 
            -
                    end
         | 
| 66 | 
            +
                    select(sql, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
         | 
| 71 67 | 
             
                  rescue ::RangeError
         | 
| 72 | 
            -
                    ActiveRecord::Result. | 
| 68 | 
            +
                    ActiveRecord::Result.empty
         | 
| 73 69 | 
             
                  end
         | 
| 74 70 |  | 
| 75 71 | 
             
                  # Returns a record hash with the column names as keys and column values
         | 
| @@ -310,20 +306,20 @@ module ActiveRecord | |
| 310 306 | 
             
                  #
         | 
| 311 307 | 
             
                  # The mysql2 and postgresql adapters support setting the transaction
         | 
| 312 308 | 
             
                  # isolation level.
         | 
| 313 | 
            -
                  def transaction(requires_new: nil, isolation: nil, joinable: true)
         | 
| 309 | 
            +
                  def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
         | 
| 314 310 | 
             
                    if !requires_new && current_transaction.joinable?
         | 
| 315 311 | 
             
                      if isolation
         | 
| 316 312 | 
             
                        raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
         | 
| 317 313 | 
             
                      end
         | 
| 318 314 | 
             
                      yield
         | 
| 319 315 | 
             
                    else
         | 
| 320 | 
            -
                      transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) | 
| 316 | 
            +
                      transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
         | 
| 321 317 | 
             
                    end
         | 
| 322 318 | 
             
                  rescue ActiveRecord::Rollback
         | 
| 323 319 | 
             
                    # rollbacks are silently swallowed
         | 
| 324 320 | 
             
                  end
         | 
| 325 321 |  | 
| 326 | 
            -
                  attr_reader :transaction_manager  | 
| 322 | 
            +
                  attr_reader :transaction_manager # :nodoc:
         | 
| 327 323 |  | 
| 328 324 | 
             
                  delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
         | 
| 329 325 | 
             
                           :commit_transaction, :rollback_transaction, :materialize_transactions,
         | 
| @@ -340,7 +336,7 @@ module ActiveRecord | |
| 340 336 | 
             
                    current_transaction.open?
         | 
| 341 337 | 
             
                  end
         | 
| 342 338 |  | 
| 343 | 
            -
                  def reset_transaction  | 
| 339 | 
            +
                  def reset_transaction # :nodoc:
         | 
| 344 340 | 
             
                    @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
         | 
| 345 341 | 
             
                  end
         | 
| 346 342 |  | 
| @@ -378,7 +374,7 @@ module ActiveRecord | |
| 378 374 | 
             
                    exec_rollback_db_transaction
         | 
| 379 375 | 
             
                  end
         | 
| 380 376 |  | 
| 381 | 
            -
                  def exec_rollback_db_transaction() end  | 
| 377 | 
            +
                  def exec_rollback_db_transaction() end # :nodoc:
         | 
| 382 378 |  | 
| 383 379 | 
             
                  def rollback_to_savepoint(name = nil)
         | 
| 384 380 | 
             
                    exec_rollback_to_savepoint(name)
         | 
| @@ -445,6 +441,19 @@ module ActiveRecord | |
| 445 441 | 
             
                    end
         | 
| 446 442 | 
             
                  end
         | 
| 447 443 |  | 
| 444 | 
            +
                  # This is a safe default, even if not high precision on all databases
         | 
| 445 | 
            +
                  HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP").freeze # :nodoc:
         | 
| 446 | 
            +
                  private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                  # Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with
         | 
| 449 | 
            +
                  # arbitrary precision date/time columns.
         | 
| 450 | 
            +
                  #
         | 
| 451 | 
            +
                  # Adapters supporting datetime with precision should override this to
         | 
| 452 | 
            +
                  # provide as much precision as is available.
         | 
| 453 | 
            +
                  def high_precision_current_timestamp
         | 
| 454 | 
            +
                    HIGH_PRECISION_CURRENT_TIMESTAMP
         | 
| 455 | 
            +
                  end
         | 
| 456 | 
            +
             | 
| 448 457 | 
             
                  private
         | 
| 449 458 | 
             
                    def execute_batch(statements, name = nil)
         | 
| 450 459 | 
             
                      statements.each do |statement|
         | 
| @@ -481,8 +490,7 @@ module ActiveRecord | |
| 481 490 | 
             
                      end
         | 
| 482 491 |  | 
| 483 492 | 
             
                      table = Arel::Table.new(table_name)
         | 
| 484 | 
            -
                      manager = Arel::InsertManager.new
         | 
| 485 | 
            -
                      manager.into(table)
         | 
| 493 | 
            +
                      manager = Arel::InsertManager.new(table)
         | 
| 486 494 |  | 
| 487 495 | 
             
                      if values_list.size == 1
         | 
| 488 496 | 
             
                        values = values_list.shift
         | 
| @@ -503,10 +511,10 @@ module ActiveRecord | |
| 503 511 | 
             
                    end
         | 
| 504 512 |  | 
| 505 513 | 
             
                    def build_fixture_statements(fixture_set)
         | 
| 506 | 
            -
                      fixture_set. | 
| 514 | 
            +
                      fixture_set.filter_map do |table_name, fixtures|
         | 
| 507 515 | 
             
                        next if fixtures.empty?
         | 
| 508 516 | 
             
                        build_fixture_sql(fixtures, table_name)
         | 
| 509 | 
            -
                      end | 
| 517 | 
            +
                      end
         | 
| 510 518 | 
             
                    end
         | 
| 511 519 |  | 
| 512 520 | 
             
                    def build_truncate_statement(table_name)
         | 
| @@ -528,12 +536,28 @@ module ActiveRecord | |
| 528 536 | 
             
                    end
         | 
| 529 537 |  | 
| 530 538 | 
             
                    # Returns an ActiveRecord::Result instance.
         | 
| 531 | 
            -
                    def select(sql, name = nil, binds = [])
         | 
| 532 | 
            -
                       | 
| 533 | 
            -
             | 
| 539 | 
            +
                    def select(sql, name = nil, binds = [], prepare: false, async: false)
         | 
| 540 | 
            +
                      if async && async_enabled?
         | 
| 541 | 
            +
                        if current_transaction.joinable?
         | 
| 542 | 
            +
                          raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
         | 
| 543 | 
            +
                        end
         | 
| 544 | 
            +
             | 
| 545 | 
            +
                        future_result = async.new(
         | 
| 546 | 
            +
                          pool,
         | 
| 547 | 
            +
                          sql,
         | 
| 548 | 
            +
                          name,
         | 
| 549 | 
            +
                          binds,
         | 
| 550 | 
            +
                          prepare: prepare,
         | 
| 551 | 
            +
                        )
         | 
| 552 | 
            +
                        if supports_concurrent_connections? && current_transaction.closed?
         | 
| 553 | 
            +
                          future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
         | 
| 554 | 
            +
                        else
         | 
| 555 | 
            +
                          future_result.execute!(self)
         | 
| 556 | 
            +
                        end
         | 
| 557 | 
            +
                        return future_result
         | 
| 558 | 
            +
                      end
         | 
| 534 559 |  | 
| 535 | 
            -
             | 
| 536 | 
            -
                      exec_query(sql, name, binds, prepare: true)
         | 
| 560 | 
            +
                      exec_query(sql, name, binds, prepare: prepare)
         | 
| 537 561 | 
             
                    end
         | 
| 538 562 |  | 
| 539 563 | 
             
                    def sql_for_insert(sql, pk, binds)
         | 
| @@ -6,7 +6,7 @@ module ActiveRecord | |
| 6 6 | 
             
              module ConnectionAdapters # :nodoc:
         | 
| 7 7 | 
             
                module QueryCache
         | 
| 8 8 | 
             
                  class << self
         | 
| 9 | 
            -
                    def included(base)  | 
| 9 | 
            +
                    def included(base) # :nodoc:
         | 
| 10 10 | 
             
                      dirties_query_cache base, :create, :insert, :update, :delete, :truncate, :truncate_tables,
         | 
| 11 11 | 
             
                        :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
         | 
| 12 12 |  | 
| @@ -93,18 +93,37 @@ module ActiveRecord | |
| 93 93 | 
             
                    end
         | 
| 94 94 | 
             
                  end
         | 
| 95 95 |  | 
| 96 | 
            -
                  def select_all(arel, name = nil, binds = [], preparable: nil)
         | 
| 97 | 
            -
                     | 
| 98 | 
            -
             | 
| 96 | 
            +
                  def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
         | 
| 97 | 
            +
                    arel = arel_from_relation(arel)
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    # If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
         | 
| 100 | 
            +
                    # Such queries should not be cached.
         | 
| 101 | 
            +
                    if @query_cache_enabled && !(arel.respond_to?(:locked) && arel.locked)
         | 
| 99 102 | 
             
                      sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
         | 
| 100 103 |  | 
| 101 | 
            -
                       | 
| 104 | 
            +
                      if async
         | 
| 105 | 
            +
                        lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
         | 
| 106 | 
            +
                      else
         | 
| 107 | 
            +
                        cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
         | 
| 108 | 
            +
                      end
         | 
| 102 109 | 
             
                    else
         | 
| 103 110 | 
             
                      super
         | 
| 104 111 | 
             
                    end
         | 
| 105 112 | 
             
                  end
         | 
| 106 113 |  | 
| 107 114 | 
             
                  private
         | 
| 115 | 
            +
                    def lookup_sql_cache(sql, name, binds)
         | 
| 116 | 
            +
                      @lock.synchronize do
         | 
| 117 | 
            +
                        if @query_cache[sql].key?(binds)
         | 
| 118 | 
            +
                          ActiveSupport::Notifications.instrument(
         | 
| 119 | 
            +
                            "sql.active_record",
         | 
| 120 | 
            +
                            cache_notification_info(sql, name, binds)
         | 
| 121 | 
            +
                          )
         | 
| 122 | 
            +
                          @query_cache[sql][binds]
         | 
| 123 | 
            +
                        end
         | 
| 124 | 
            +
                      end
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
             | 
| 108 127 | 
             
                    def cache_sql(sql, name, binds)
         | 
| 109 128 | 
             
                      @lock.synchronize do
         | 
| 110 129 | 
             
                        result =
         | 
| @@ -134,13 +153,6 @@ module ActiveRecord | |
| 134 153 | 
             
                      }
         | 
| 135 154 | 
             
                    end
         | 
| 136 155 |  | 
| 137 | 
            -
                    # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
         | 
| 138 | 
            -
                    # queries should not be cached.
         | 
| 139 | 
            -
                    def locked?(arel)
         | 
| 140 | 
            -
                      arel = arel.arel if arel.is_a?(Relation)
         | 
| 141 | 
            -
                      arel.respond_to?(:locked) && arel.locked
         | 
| 142 | 
            -
                    end
         | 
| 143 | 
            -
             | 
| 144 156 | 
             
                    def configure_query_cache!
         | 
| 145 157 | 
             
                      enable_query_cache! if pool.query_cache_enabled
         | 
| 146 158 | 
             
                    end
         | 
| @@ -43,6 +43,13 @@ module ActiveRecord | |
| 43 43 | 
             
                    _type_cast(value)
         | 
| 44 44 | 
             
                  end
         | 
| 45 45 |  | 
| 46 | 
            +
                  # Quote a value to be used as a bound parameter of unknown type. For example,
         | 
| 47 | 
            +
                  # MySQL might perform dangerous castings when comparing a string to a number,
         | 
| 48 | 
            +
                  # so this method will cast numbers to string.
         | 
| 49 | 
            +
                  def quote_bound_value(value)
         | 
| 50 | 
            +
                    _quote(value)
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 46 53 | 
             
                  # If you are having to call this function, you are likely doing something
         | 
| 47 54 | 
             
                  # wrong. The column does not have sufficient type information if the user
         | 
| 48 55 | 
             
                  # provided a custom type on the class level either explicitly (via
         | 
| @@ -59,7 +66,7 @@ module ActiveRecord | |
| 59 66 | 
             
                  # Quotes a string, escaping any ' (single quote) and \ (backslash)
         | 
| 60 67 | 
             
                  # characters.
         | 
| 61 68 | 
             
                  def quote_string(s)
         | 
| 62 | 
            -
                    s.gsub( | 
| 69 | 
            +
                    s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
         | 
| 63 70 | 
             
                  end
         | 
| 64 71 |  | 
| 65 72 | 
             
                  # Quotes the column name. Defaults to no quoting.
         | 
| @@ -113,10 +120,10 @@ module ActiveRecord | |
| 113 120 | 
             
                  # if the value is a Time responding to usec.
         | 
| 114 121 | 
             
                  def quoted_date(value)
         | 
| 115 122 | 
             
                    if value.acts_like?(:time)
         | 
| 116 | 
            -
                      if ActiveRecord | 
| 117 | 
            -
                        value = value.getutc if  | 
| 123 | 
            +
                      if ActiveRecord.default_timezone == :utc
         | 
| 124 | 
            +
                        value = value.getutc if !value.utc?
         | 
| 118 125 | 
             
                      else
         | 
| 119 | 
            -
                        value = value.getlocal | 
| 126 | 
            +
                        value = value.getlocal
         | 
| 120 127 | 
             
                      end
         | 
| 121 128 | 
             
                    end
         | 
| 122 129 |  | 
| @@ -138,16 +145,7 @@ module ActiveRecord | |
| 138 145 | 
             
                  end
         | 
| 139 146 |  | 
| 140 147 | 
             
                  def sanitize_as_sql_comment(value) # :nodoc:
         | 
| 141 | 
            -
                     | 
| 142 | 
            -
                    # For compatibility, this also surrounding "/*+", "/*", and "*/"
         | 
| 143 | 
            -
                    # charcacters, possibly with single surrounding space.
         | 
| 144 | 
            -
                    # Then follows that by replacing any internal "*/" or "/ *" with
         | 
| 145 | 
            -
                    # "* /" or "/ *"
         | 
| 146 | 
            -
                    comment = value.to_s.dup
         | 
| 147 | 
            -
                    comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
         | 
| 148 | 
            -
                    comment.gsub!("*/", "* /")
         | 
| 149 | 
            -
                    comment.gsub!("/*", "/ *")
         | 
| 150 | 
            -
                    comment
         | 
| 148 | 
            +
                    value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
         | 
| 151 149 | 
             
                  end
         | 
| 152 150 |  | 
| 153 151 | 
             
                  def column_name_matcher # :nodoc:
         | 
| @@ -14,8 +14,8 @@ module ActiveRecord | |
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 16 | 
             
                  delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
         | 
| 17 | 
            -
                    :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, | 
| 18 | 
            -
                    :quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?, | 
| 17 | 
            +
                    :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?,
         | 
| 18 | 
            +
                    :quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
         | 
| 19 19 | 
             
                    to: :@conn, private: true
         | 
| 20 20 |  | 
| 21 21 | 
             
                  private
         | 
| @@ -52,11 +52,11 @@ module ActiveRecord | |
| 52 52 | 
             
                      end
         | 
| 53 53 |  | 
| 54 54 | 
             
                      if supports_foreign_keys?
         | 
| 55 | 
            -
                        statements.concat(o.foreign_keys.map { | | 
| 55 | 
            +
                        statements.concat(o.foreign_keys.map { |fk| accept fk })
         | 
| 56 56 | 
             
                      end
         | 
| 57 57 |  | 
| 58 58 | 
             
                      if supports_check_constraints?
         | 
| 59 | 
            -
                        statements.concat(o.check_constraints.map { | | 
| 59 | 
            +
                        statements.concat(o.check_constraints.map { |chk| accept chk })
         | 
| 60 60 | 
             
                      end
         | 
| 61 61 |  | 
| 62 62 | 
             
                      create_sql << "(#{statements.join(', ')})" if statements.present?
         | 
| @@ -159,19 +159,6 @@ module ActiveRecord | |
| 159 159 | 
             
                      " TEMPORARY" if o.temporary
         | 
| 160 160 | 
             
                    end
         | 
| 161 161 |  | 
| 162 | 
            -
                    def foreign_key_in_create(from_table, to_table, options)
         | 
| 163 | 
            -
                      prefix = ActiveRecord::Base.table_name_prefix
         | 
| 164 | 
            -
                      suffix = ActiveRecord::Base.table_name_suffix
         | 
| 165 | 
            -
                      to_table = "#{prefix}#{to_table}#{suffix}"
         | 
| 166 | 
            -
                      options = foreign_key_options(from_table, to_table, options)
         | 
| 167 | 
            -
                      accept ForeignKeyDefinition.new(from_table, to_table, options)
         | 
| 168 | 
            -
                    end
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                    def check_constraint_in_create(table_name, expression, options)
         | 
| 171 | 
            -
                      options = check_constraint_options(table_name, expression, options)
         | 
| 172 | 
            -
                      accept CheckConstraintDefinition.new(table_name, expression, options)
         | 
| 173 | 
            -
                    end
         | 
| 174 | 
            -
             | 
| 175 162 | 
             
                    def action_sql(action, dependency)
         | 
| 176 163 | 
             
                      case dependency
         | 
| 177 164 | 
             
                      when :nullify then "ON #{action} SET NULL"
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            module ActiveRecord
         | 
| 4 | 
            -
              module ConnectionAdapters  | 
| 4 | 
            +
              module ConnectionAdapters # :nodoc:
         | 
| 5 5 | 
             
                # Abstract representation of an index definition on a table. Instances of
         | 
| 6 6 | 
             
                # this type are typically created and returned by methods in database
         | 
| 7 7 | 
             
                # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
         | 
| @@ -79,13 +79,13 @@ module ActiveRecord | |
| 79 79 |  | 
| 80 80 | 
             
                AddColumnDefinition = Struct.new(:column) # :nodoc:
         | 
| 81 81 |  | 
| 82 | 
            -
                ChangeColumnDefinition = Struct.new(:column, :name)  | 
| 82 | 
            +
                ChangeColumnDefinition = Struct.new(:column, :name) # :nodoc:
         | 
| 83 83 |  | 
| 84 84 | 
             
                CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
         | 
| 85 85 |  | 
| 86 86 | 
             
                PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
         | 
| 87 87 |  | 
| 88 | 
            -
                ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do  | 
| 88 | 
            +
                ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do # :nodoc:
         | 
| 89 89 | 
             
                  def name
         | 
| 90 90 | 
             
                    options[:name]
         | 
| 91 91 | 
             
                  end
         | 
| @@ -198,10 +198,6 @@ module ActiveRecord | |
| 198 198 |  | 
| 199 199 | 
             
                    def index_options(table_name)
         | 
| 200 200 | 
             
                      index_options = as_options(index)
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                      # legacy reference index names are used on versions 6.0 and earlier
         | 
| 203 | 
            -
                      return index_options if options[:_uses_legacy_reference_index_name]
         | 
| 204 | 
            -
             | 
| 205 201 | 
             
                      index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic
         | 
| 206 202 | 
             
                      index_options
         | 
| 207 203 | 
             
                    end
         | 
| @@ -257,6 +253,7 @@ module ActiveRecord | |
| 257 253 | 
             
                    define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
         | 
| 258 254 | 
             
                      :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
         | 
| 259 255 |  | 
| 256 | 
            +
                    alias :blob :binary
         | 
| 260 257 | 
             
                    alias :numeric :decimal
         | 
| 261 258 | 
             
                  end
         | 
| 262 259 |  | 
| @@ -281,7 +278,7 @@ module ActiveRecord | |
| 281 278 | 
             
                # Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
         | 
| 282 279 | 
             
                # is actually of this type:
         | 
| 283 280 | 
             
                #
         | 
| 284 | 
            -
                #   class SomeMigration < ActiveRecord::Migration[ | 
| 281 | 
            +
                #   class SomeMigration < ActiveRecord::Migration[7.0]
         | 
| 285 282 | 
             
                #     def up
         | 
| 286 283 | 
             
                #       create_table :foo do |t|
         | 
| 287 284 | 
             
                #         puts t.class  # => "ActiveRecord::ConnectionAdapters::TableDefinition"
         | 
| @@ -414,6 +411,12 @@ module ActiveRecord | |
| 414 411 | 
             
                      end
         | 
| 415 412 | 
             
                    end
         | 
| 416 413 |  | 
| 414 | 
            +
                    if @conn.supports_datetime_with_precision?
         | 
| 415 | 
            +
                      if type == :datetime && !options.key?(:precision)
         | 
| 416 | 
            +
                        options[:precision] = 6
         | 
| 417 | 
            +
                      end
         | 
| 418 | 
            +
                    end
         | 
| 419 | 
            +
             | 
| 417 420 | 
             
                    @columns_hash[name] = new_column_definition(name, type, **options)
         | 
| 418 421 |  | 
| 419 422 | 
             
                    if index
         | 
| @@ -438,12 +441,12 @@ module ActiveRecord | |
| 438 441 | 
             
                    indexes << [column_name, options]
         | 
| 439 442 | 
             
                  end
         | 
| 440 443 |  | 
| 441 | 
            -
                  def foreign_key( | 
| 442 | 
            -
                    foreign_keys <<  | 
| 444 | 
            +
                  def foreign_key(to_table, **options)
         | 
| 445 | 
            +
                    foreign_keys << new_foreign_key_definition(to_table, options)
         | 
| 443 446 | 
             
                  end
         | 
| 444 447 |  | 
| 445 448 | 
             
                  def check_constraint(expression, **options)
         | 
| 446 | 
            -
                    check_constraints <<  | 
| 449 | 
            +
                    check_constraints << new_check_constraint_definition(expression, options)
         | 
| 447 450 | 
             
                  end
         | 
| 448 451 |  | 
| 449 452 | 
             
                  # Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
         | 
| @@ -485,6 +488,19 @@ module ActiveRecord | |
| 485 488 | 
             
                    create_column_definition(name, type, options)
         | 
| 486 489 | 
             
                  end
         | 
| 487 490 |  | 
| 491 | 
            +
                  def new_foreign_key_definition(to_table, options) # :nodoc:
         | 
| 492 | 
            +
                    prefix = ActiveRecord::Base.table_name_prefix
         | 
| 493 | 
            +
                    suffix = ActiveRecord::Base.table_name_suffix
         | 
| 494 | 
            +
                    to_table = "#{prefix}#{to_table}#{suffix}"
         | 
| 495 | 
            +
                    options = @conn.foreign_key_options(name, to_table, options)
         | 
| 496 | 
            +
                    ForeignKeyDefinition.new(name, to_table, options)
         | 
| 497 | 
            +
                  end
         | 
| 498 | 
            +
             | 
| 499 | 
            +
                  def new_check_constraint_definition(expression, options) # :nodoc:
         | 
| 500 | 
            +
                    options = @conn.check_constraint_options(name, expression, options)
         | 
| 501 | 
            +
                    CheckConstraintDefinition.new(name, expression, options)
         | 
| 502 | 
            +
                  end
         | 
| 503 | 
            +
             | 
| 488 504 | 
             
                  private
         | 
| 489 505 | 
             
                    def create_column_definition(name, type, options)
         | 
| 490 506 | 
             
                      ColumnDefinition.new(name, type, options)
         | 
| @@ -520,7 +536,7 @@ module ActiveRecord | |
| 520 536 | 
             
                  def name; @td.name; end
         | 
| 521 537 |  | 
| 522 538 | 
             
                  def add_foreign_key(to_table, options)
         | 
| 523 | 
            -
                    @foreign_key_adds <<  | 
| 539 | 
            +
                    @foreign_key_adds << @td.new_foreign_key_definition(to_table, options)
         | 
| 524 540 | 
             
                  end
         | 
| 525 541 |  | 
| 526 542 | 
             
                  def drop_foreign_key(name)
         | 
| @@ -528,7 +544,7 @@ module ActiveRecord | |
| 528 544 | 
             
                  end
         | 
| 529 545 |  | 
| 530 546 | 
             
                  def add_check_constraint(expression, options)
         | 
| 531 | 
            -
                    @check_constraint_adds <<  | 
| 547 | 
            +
                    @check_constraint_adds << @td.new_check_constraint_definition(expression, options)
         | 
| 532 548 | 
             
                  end
         | 
| 533 549 |  | 
| 534 550 | 
             
                  def drop_check_constraint(constraint_name)
         | 
| @@ -572,6 +588,7 @@ module ActiveRecord | |
| 572 588 | 
             
                #     t.time
         | 
| 573 589 | 
             
                #     t.date
         | 
| 574 590 | 
             
                #     t.binary
         | 
| 591 | 
            +
                #     t.blob
         | 
| 575 592 | 
             
                #     t.boolean
         | 
| 576 593 | 
             
                #     t.foreign_key
         | 
| 577 594 | 
             
                #     t.json
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require "active_support/core_ext/string/access"
         | 
| 4 | 
            -
            require " | 
| 4 | 
            +
            require "openssl"
         | 
| 5 5 |  | 
| 6 6 | 
             
            module ActiveRecord
         | 
| 7 7 | 
             
              module ConnectionAdapters # :nodoc:
         | 
| @@ -29,7 +29,7 @@ module ActiveRecord | |
| 29 29 | 
             
                    table_name[0...table_alias_length].tr(".", "_")
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 |  | 
| 32 | 
            -
                  # Returns the relation names  | 
| 32 | 
            +
                  # Returns the relation names usable to back Active Record models.
         | 
| 33 33 | 
             
                  # For most adapters this means all #tables and #views.
         | 
| 34 34 | 
             
                  def data_sources
         | 
| 35 35 | 
             
                    query_values(data_source_sql, "SCHEMA")
         | 
| @@ -518,24 +518,31 @@ module ActiveRecord | |
| 518 518 |  | 
| 519 519 | 
             
                  # Add a new +type+ column named +column_name+ to +table_name+.
         | 
| 520 520 | 
             
                  #
         | 
| 521 | 
            +
                  # See {ActiveRecord::ConnectionAdapters::TableDefinition.column}[rdoc-ref:ActiveRecord::ConnectionAdapters::TableDefinition#column].
         | 
| 522 | 
            +
                  #
         | 
| 521 523 | 
             
                  # The +type+ parameter is normally one of the migrations native types,
         | 
| 522 524 | 
             
                  # which is one of the following:
         | 
| 523 525 | 
             
                  # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
         | 
| 524 526 | 
             
                  # <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
         | 
| 525 527 | 
             
                  # <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
         | 
| 526 | 
            -
                  # <tt>:binary</tt>, <tt>:boolean</tt>.
         | 
| 528 | 
            +
                  # <tt>:binary</tt>, <tt>:blob</tt>, <tt>:boolean</tt>.
         | 
| 527 529 | 
             
                  #
         | 
| 528 530 | 
             
                  # You may use a type not in this list as long as it is supported by your
         | 
| 529 531 | 
             
                  # database (for example, "polygon" in MySQL), but this will not be database
         | 
| 530 532 | 
             
                  # agnostic and should usually be avoided.
         | 
| 531 533 | 
             
                  #
         | 
| 532 534 | 
             
                  # Available options are (none of these exists by default):
         | 
| 535 | 
            +
                  # * <tt>:comment</tt> -
         | 
| 536 | 
            +
                  #   Specifies the comment for the column. This option is ignored by some backends.
         | 
| 537 | 
            +
                  # * <tt>:collation</tt> -
         | 
| 538 | 
            +
                  #   Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column.
         | 
| 539 | 
            +
                  #   If not specified, the column will have the same collation as the table.
         | 
| 540 | 
            +
                  # * <tt>:default</tt> -
         | 
| 541 | 
            +
                  #   The column's default value. Use +nil+ for +NULL+.
         | 
| 533 542 | 
             
                  # * <tt>:limit</tt> -
         | 
| 534 543 | 
             
                  #   Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
         | 
| 535 | 
            -
                  #   and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
         | 
| 544 | 
            +
                  #   and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, <tt>:blob</tt>, and <tt>:integer</tt> columns.
         | 
| 536 545 | 
             
                  #   This option is ignored by some backends.
         | 
| 537 | 
            -
                  # * <tt>:default</tt> -
         | 
| 538 | 
            -
                  #   The column's default value. Use +nil+ for +NULL+.
         | 
| 539 546 | 
             
                  # * <tt>:null</tt> -
         | 
| 540 547 | 
             
                  #   Allows or disallows +NULL+ values in the column.
         | 
| 541 548 | 
             
                  # * <tt>:precision</tt> -
         | 
| @@ -604,7 +611,13 @@ module ActiveRecord | |
| 604 611 | 
             
                  #  # Ignores the method call if the column exists
         | 
| 605 612 | 
             
                  #  add_column(:shapes, :triangle, 'polygon', if_not_exists: true)
         | 
| 606 613 | 
             
                  def add_column(table_name, column_name, type, **options)
         | 
| 607 | 
            -
                    return if options[:if_not_exists] == true && column_exists?(table_name, column_name | 
| 614 | 
            +
                    return if options[:if_not_exists] == true && column_exists?(table_name, column_name)
         | 
| 615 | 
            +
             | 
| 616 | 
            +
                    if supports_datetime_with_precision?
         | 
| 617 | 
            +
                      if type == :datetime && !options.key?(:precision)
         | 
| 618 | 
            +
                        options[:precision] = 6
         | 
| 619 | 
            +
                      end
         | 
| 620 | 
            +
                    end
         | 
| 608 621 |  | 
| 609 622 | 
             
                    at = create_alter_table table_name
         | 
| 610 623 | 
             
                    at.add_column(column_name, type, **options)
         | 
| @@ -629,9 +642,8 @@ module ActiveRecord | |
| 629 642 | 
             
                      raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)")
         | 
| 630 643 | 
             
                    end
         | 
| 631 644 |  | 
| 632 | 
            -
                    column_names | 
| 633 | 
            -
             | 
| 634 | 
            -
                    end
         | 
| 645 | 
            +
                    remove_column_fragments = remove_columns_for_alter(table_name, *column_names, type: type, **options)
         | 
| 646 | 
            +
                    execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_fragments.join(', ')}"
         | 
| 635 647 | 
             
                  end
         | 
| 636 648 |  | 
| 637 649 | 
             
                  # Removes the column from the table definition.
         | 
| @@ -901,7 +913,7 @@ module ActiveRecord | |
| 901 913 | 
             
                    remove_index(table_name, name: old_name)
         | 
| 902 914 | 
             
                  end
         | 
| 903 915 |  | 
| 904 | 
            -
                  def index_name(table_name, options)  | 
| 916 | 
            +
                  def index_name(table_name, options) # :nodoc:
         | 
| 905 917 | 
             
                    if Hash === options
         | 
| 906 918 | 
             
                      if options[:column]
         | 
| 907 919 | 
             
                        "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
         | 
| @@ -1027,6 +1039,10 @@ module ActiveRecord | |
| 1027 1039 | 
             
                  #
         | 
| 1028 1040 | 
             
                  #   ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")
         | 
| 1029 1041 | 
             
                  #
         | 
| 1042 | 
            +
                  # ====== Creating a foreign key, ignoring method call if the foreign key exists
         | 
| 1043 | 
            +
                  #
         | 
| 1044 | 
            +
                  #  add_foreign_key(:articles, :authors, if_not_exists: true)
         | 
| 1045 | 
            +
                  #
         | 
| 1030 1046 | 
             
                  # ====== Creating a foreign key on a specific column
         | 
| 1031 1047 | 
             
                  #
         | 
| 1032 1048 | 
             
                  #   add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
         | 
| @@ -1054,10 +1070,14 @@ module ActiveRecord | |
| 1054 1070 | 
             
                  #   Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
         | 
| 1055 1071 | 
             
                  # [<tt>:on_update</tt>]
         | 
| 1056 1072 | 
             
                  #   Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
         | 
| 1073 | 
            +
                  # [<tt>:if_not_exists</tt>]
         | 
| 1074 | 
            +
                  #   Specifies if the foreign key already exists to not try to re-add it. This will avoid
         | 
| 1075 | 
            +
                  #   duplicate column errors.
         | 
| 1057 1076 | 
             
                  # [<tt>:validate</tt>]
         | 
| 1058 1077 | 
             
                  #   (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
         | 
| 1059 1078 | 
             
                  def add_foreign_key(from_table, to_table, **options)
         | 
| 1060 1079 | 
             
                    return unless supports_foreign_keys?
         | 
| 1080 | 
            +
                    return if options[:if_not_exists] == true && foreign_key_exists?(from_table, to_table)
         | 
| 1061 1081 |  | 
| 1062 1082 | 
             
                    options = foreign_key_options(from_table, to_table, options)
         | 
| 1063 1083 | 
             
                    at = create_alter_table from_table
         | 
| @@ -1087,12 +1107,18 @@ module ActiveRecord | |
| 1087 1107 | 
             
                  #
         | 
| 1088 1108 | 
             
                  #   remove_foreign_key :accounts, name: :special_fk_name
         | 
| 1089 1109 | 
             
                  #
         | 
| 1110 | 
            +
                  # Checks if the foreign key exists before trying to remove it. Will silently ignore indexes that
         | 
| 1111 | 
            +
                  # don't exist.
         | 
| 1112 | 
            +
                  #
         | 
| 1113 | 
            +
                  #   remove_foreign_key :accounts, :branches, if_exists: true
         | 
| 1114 | 
            +
                  #
         | 
| 1090 1115 | 
             
                  # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
         | 
| 1091 1116 | 
             
                  # with an addition of
         | 
| 1092 1117 | 
             
                  # [<tt>:to_table</tt>]
         | 
| 1093 1118 | 
             
                  #   The name of the table that contains the referenced primary key.
         | 
| 1094 1119 | 
             
                  def remove_foreign_key(from_table, to_table = nil, **options)
         | 
| 1095 1120 | 
             
                    return unless supports_foreign_keys?
         | 
| 1121 | 
            +
                    return if options[:if_exists] == true && !foreign_key_exists?(from_table, to_table)
         | 
| 1096 1122 |  | 
| 1097 1123 | 
             
                    fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
         | 
| 1098 1124 |  | 
| @@ -1256,6 +1282,25 @@ module ActiveRecord | |
| 1256 1282 | 
             
                    columns
         | 
| 1257 1283 | 
             
                  end
         | 
| 1258 1284 |  | 
| 1285 | 
            +
                  def distinct_relation_for_primary_key(relation) # :nodoc:
         | 
| 1286 | 
            +
                    values = columns_for_distinct(
         | 
| 1287 | 
            +
                      visitor.compile(relation.table[relation.primary_key]),
         | 
| 1288 | 
            +
                      relation.order_values
         | 
| 1289 | 
            +
                    )
         | 
| 1290 | 
            +
             | 
| 1291 | 
            +
                    limited = relation.reselect(values).distinct!
         | 
| 1292 | 
            +
                    limited_ids = select_rows(limited.arel, "SQL").map(&:last)
         | 
| 1293 | 
            +
             | 
| 1294 | 
            +
                    if limited_ids.empty?
         | 
| 1295 | 
            +
                      relation.none!
         | 
| 1296 | 
            +
                    else
         | 
| 1297 | 
            +
                      relation.where!(relation.primary_key => limited_ids)
         | 
| 1298 | 
            +
                    end
         | 
| 1299 | 
            +
             | 
| 1300 | 
            +
                    relation.limit_value = relation.offset_value = nil
         | 
| 1301 | 
            +
                    relation
         | 
| 1302 | 
            +
                  end
         | 
| 1303 | 
            +
             | 
| 1259 1304 | 
             
                  # Adds timestamps (+created_at+ and +updated_at+) columns to +table_name+.
         | 
| 1260 1305 | 
             
                  # Additional options (like +:null+) are forwarded to #add_column.
         | 
| 1261 1306 | 
             
                  #
         | 
| @@ -1277,11 +1322,10 @@ module ActiveRecord | |
| 1277 1322 | 
             
                  #  remove_timestamps(:suppliers)
         | 
| 1278 1323 | 
             
                  #
         | 
| 1279 1324 | 
             
                  def remove_timestamps(table_name, **options)
         | 
| 1280 | 
            -
                     | 
| 1281 | 
            -
                    remove_column table_name, :created_at
         | 
| 1325 | 
            +
                    remove_columns table_name, :updated_at, :created_at
         | 
| 1282 1326 | 
             
                  end
         | 
| 1283 1327 |  | 
| 1284 | 
            -
                  def update_table_definition(table_name, base)  | 
| 1328 | 
            +
                  def update_table_definition(table_name, base) # :nodoc:
         | 
| 1285 1329 | 
             
                    Table.new(table_name, base)
         | 
| 1286 1330 | 
             
                  end
         | 
| 1287 1331 |  | 
| @@ -1488,7 +1532,7 @@ module ActiveRecord | |
| 1488 1532 | 
             
                    def foreign_key_name(table_name, options)
         | 
| 1489 1533 | 
             
                      options.fetch(:name) do
         | 
| 1490 1534 | 
             
                        identifier = "#{table_name}_#{options.fetch(:column)}_fk"
         | 
| 1491 | 
            -
                        hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
         | 
| 1535 | 
            +
                        hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
         | 
| 1492 1536 |  | 
| 1493 1537 | 
             
                        "fk_rails_#{hashed_identifier}"
         | 
| 1494 1538 | 
             
                      end
         | 
| @@ -1516,7 +1560,7 @@ module ActiveRecord | |
| 1516 1560 | 
             
                      options.fetch(:name) do
         | 
| 1517 1561 | 
             
                        expression = options.fetch(:expression)
         | 
| 1518 1562 | 
             
                        identifier = "#{table_name}_#{expression}_chk"
         | 
| 1519 | 
            -
                        hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
         | 
| 1563 | 
            +
                        hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
         | 
| 1520 1564 |  | 
| 1521 1565 | 
             
                        "chk_rails_#{hashed_identifier}"
         | 
| 1522 1566 | 
             
                      end
         | 
| @@ -73,7 +73,7 @@ module ActiveRecord | |
| 73 73 | 
             
                  end
         | 
| 74 74 | 
             
                end
         | 
| 75 75 |  | 
| 76 | 
            -
                class NullTransaction  | 
| 76 | 
            +
                class NullTransaction # :nodoc:
         | 
| 77 77 | 
             
                  def initialize; end
         | 
| 78 78 | 
             
                  def state; end
         | 
| 79 79 | 
             
                  def closed?; true; end
         | 
| @@ -82,7 +82,7 @@ module ActiveRecord | |
| 82 82 | 
             
                  def add_record(record, _ = true); end
         | 
| 83 83 | 
             
                end
         | 
| 84 84 |  | 
| 85 | 
            -
                class Transaction  | 
| 85 | 
            +
                class Transaction # :nodoc:
         | 
| 86 86 | 
             
                  attr_reader :connection, :state, :savepoint_name, :isolation_level
         | 
| 87 87 | 
             
                  attr_accessor :written
         | 
| 88 88 |  | 
| @@ -221,7 +221,7 @@ module ActiveRecord | |
| 221 221 | 
             
                  end
         | 
| 222 222 | 
             
                end
         | 
| 223 223 |  | 
| 224 | 
            -
                class TransactionManager  | 
| 224 | 
            +
                class TransactionManager # :nodoc:
         | 
| 225 225 | 
             
                  def initialize(connection)
         | 
| 226 226 | 
             
                    @stack = []
         | 
| 227 227 | 
             
                    @connection = connection
         |