ibm_db 5.6.1 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/Makefile +13 -9
- data/ext/extconf.rb +176 -110
- data/ext/ibm_db.c +60 -0
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +6 -6
- data/ext/ruby_ibm_db_cli.c +14 -10
- data/ext/ruby_ibm_db_cli.h +4 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/lib/IBM_DB.rb +2 -2
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1254 -277
- data/test/active_record/connection_adapters/fake_legacy_adapter.rb +17 -0
- data/test/active_record/connection_adapters/fake_misleading_legacy_adapter.rb +8 -0
- data/test/activejob/destroy_association_async_job_test.rb +62 -0
- data/test/activejob/destroy_association_async_test.rb +147 -11
- data/test/activejob/job_runtime_test.rb +41 -0
- data/test/activejob/unloadable_base_job.rb +3 -0
- data/test/cases/active_record_schema_test.rb +196 -0
- data/test/cases/active_record_test.rb +21 -0
- data/test/cases/adapter_prevent_writes_test.rb +26 -202
- data/test/cases/adapter_test.rb +592 -82
- data/test/cases/adapters/abstract_mysql_adapter/active_schema_test.rb +210 -0
- data/test/cases/adapters/abstract_mysql_adapter/adapter_prevent_writes_test.rb +111 -0
- data/test/cases/adapters/abstract_mysql_adapter/auto_increment_test.rb +48 -0
- data/test/cases/adapters/abstract_mysql_adapter/bind_parameter_test.rb +91 -0
- data/test/cases/adapters/abstract_mysql_adapter/case_sensitivity_test.rb +65 -0
- data/test/cases/adapters/abstract_mysql_adapter/charset_collation_test.rb +85 -0
- data/test/cases/adapters/abstract_mysql_adapter/connection_test.rb +267 -0
- data/test/cases/adapters/abstract_mysql_adapter/count_deleted_rows_with_lock_test.rb +29 -0
- data/test/cases/adapters/abstract_mysql_adapter/json_test.rb +24 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_boolean_test.rb +102 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_enum_test.rb +47 -0
- data/test/cases/adapters/abstract_mysql_adapter/mysql_explain_test.rb +71 -0
- data/test/cases/adapters/abstract_mysql_adapter/nested_deadlock_test.rb +191 -0
- data/test/cases/adapters/abstract_mysql_adapter/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/quoting_test.rb +49 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_migrations_test.rb +68 -0
- data/test/cases/adapters/abstract_mysql_adapter/schema_test.rb +130 -0
- data/test/cases/adapters/abstract_mysql_adapter/set_test.rb +32 -0
- data/test/cases/adapters/abstract_mysql_adapter/sp_test.rb +39 -0
- data/test/cases/adapters/abstract_mysql_adapter/sql_types_test.rb +16 -0
- data/test/cases/adapters/abstract_mysql_adapter/table_options_test.rb +125 -0
- data/test/cases/adapters/abstract_mysql_adapter/transaction_test.rb +204 -0
- data/test/cases/adapters/abstract_mysql_adapter/unsigned_type_test.rb +77 -0
- data/test/cases/adapters/abstract_mysql_adapter/virtual_column_test.rb +69 -0
- data/test/cases/adapters/abstract_mysql_adapter/warnings_test.rb +109 -0
- data/test/cases/adapters/mysql2/check_constraint_quoting_test.rb +35 -0
- data/test/cases/adapters/mysql2/dbconsole_test.rb +87 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +136 -10
- data/test/cases/adapters/mysql2/mysql2_rake_test.rb +433 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +8 -4
- data/test/cases/adapters/postgresql/array_test.rb +6 -6
- data/test/cases/adapters/postgresql/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +2 -2
- data/test/cases/adapters/postgresql/bytea_test.rb +3 -3
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +1 -1
- data/test/cases/adapters/postgresql/change_schema_test.rb +32 -1
- data/test/cases/adapters/postgresql/cidr_test.rb +17 -0
- data/test/cases/adapters/postgresql/citext_test.rb +7 -1
- data/test/cases/adapters/postgresql/collation_test.rb +1 -1
- data/test/cases/adapters/postgresql/composite_test.rb +1 -1
- data/test/cases/adapters/postgresql/connection_test.rb +43 -36
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +3 -2
- data/test/cases/adapters/postgresql/datatype_test.rb +9 -4
- data/test/cases/adapters/postgresql/date_test.rb +2 -2
- data/test/cases/adapters/postgresql/dbconsole_test.rb +109 -0
- data/test/cases/adapters/postgresql/deferred_constraints_test.rb +55 -0
- data/test/cases/adapters/postgresql/domain_test.rb +1 -1
- data/test/cases/adapters/postgresql/enum_test.rb +208 -8
- data/test/cases/adapters/postgresql/explain_test.rb +25 -6
- data/test/cases/adapters/postgresql/extension_migration_test.rb +51 -9
- data/test/cases/adapters/postgresql/foreign_table_test.rb +3 -3
- data/test/cases/adapters/postgresql/full_text_test.rb +1 -1
- data/test/cases/adapters/postgresql/geometric_test.rb +13 -6
- data/test/cases/adapters/postgresql/hstore_test.rb +22 -32
- data/test/cases/adapters/postgresql/infinity_test.rb +13 -2
- data/test/cases/adapters/postgresql/integer_test.rb +1 -1
- data/test/cases/adapters/postgresql/interval_test.rb +9 -17
- data/test/cases/adapters/postgresql/invertible_migration_test.rb +139 -0
- data/test/cases/adapters/postgresql/json_test.rb +5 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +1 -1
- data/test/cases/adapters/postgresql/money_test.rb +17 -9
- data/test/cases/adapters/postgresql/network_test.rb +13 -1
- data/test/cases/adapters/postgresql/numbers_test.rb +18 -2
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +9 -9
- data/test/cases/adapters/postgresql/partitions_test.rb +5 -2
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +7 -110
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +403 -20
- data/test/cases/adapters/postgresql/postgresql_rake_test.rb +637 -0
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +1 -1
- data/test/cases/adapters/postgresql/quoting_test.rb +60 -1
- data/test/cases/adapters/postgresql/range_test.rb +185 -21
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +29 -5
- data/test/cases/adapters/postgresql/rename_table_test.rb +35 -8
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +2 -2
- data/test/cases/adapters/postgresql/schema_test.rb +270 -20
- data/test/cases/adapters/postgresql/serial_test.rb +5 -5
- data/test/cases/adapters/postgresql/statement_pool_test.rb +6 -2
- data/test/cases/adapters/postgresql/timestamp_test.rb +122 -5
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +130 -6
- data/test/cases/adapters/postgresql/transaction_test.rb +37 -11
- data/test/cases/adapters/postgresql/type_lookup_test.rb +1 -1
- data/test/cases/adapters/postgresql/uuid_test.rb +77 -9
- data/test/cases/adapters/postgresql/virtual_column_test.rb +114 -0
- data/test/cases/adapters/postgresql/xml_test.rb +1 -1
- data/test/cases/adapters/sqlite3/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +1 -1
- data/test/cases/adapters/sqlite3/copy_table_test.rb +28 -7
- data/test/cases/adapters/sqlite3/dbconsole_test.rb +81 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +3 -3
- data/test/cases/adapters/sqlite3/quoting_test.rb +34 -3
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +9 -102
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +727 -72
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +6 -3
- data/test/cases/adapters/sqlite3/sqlite_rake_test.rb +264 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +1 -1
- data/test/cases/adapters/sqlite3/transaction_test.rb +6 -3
- data/test/cases/adapters/sqlite3/virtual_column_test.rb +138 -0
- data/test/cases/adapters/sqlite3/virtual_table_test.rb +51 -0
- data/test/cases/adapters/trilogy/dbconsole_test.rb +76 -0
- data/test/cases/adapters/trilogy/trilogy_adapter_test.rb +473 -0
- data/test/cases/adapters/trilogy/trilogy_rake_test.rb +433 -0
- data/test/cases/aggregations_test.rb +16 -0
- data/test/cases/annotate_test.rb +14 -12
- data/test/cases/arel/attributes/attribute_test.rb +86 -47
- data/test/cases/arel/collectors/bind_test.rb +1 -1
- data/test/cases/arel/collectors/composite_test.rb +11 -1
- data/test/cases/arel/collectors/sql_string_test.rb +1 -1
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +1 -1
- data/test/cases/arel/delete_manager_test.rb +0 -6
- data/test/cases/arel/factory_methods_test.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +1 -7
- data/test/cases/arel/nodes/as_test.rb +12 -0
- data/test/cases/arel/nodes/ascending_test.rb +1 -1
- data/test/cases/arel/nodes/bin_test.rb +1 -1
- data/test/cases/arel/nodes/bound_sql_literal_test.rb +31 -0
- data/test/cases/arel/nodes/cte_test.rb +46 -0
- data/test/cases/arel/nodes/descending_test.rb +1 -1
- data/test/cases/arel/nodes/equality_test.rb +3 -3
- data/test/cases/arel/nodes/filter_test.rb +37 -0
- data/test/cases/arel/nodes/fragments_test.rb +38 -0
- data/test/cases/arel/nodes/homogeneous_in_test.rb +52 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +1 -1
- data/test/cases/arel/nodes/node_test.rb +1 -1
- data/test/cases/arel/nodes/or_test.rb +2 -2
- data/test/cases/arel/nodes/sql_literal_test.rb +18 -1
- data/test/cases/arel/nodes/table_alias_test.rb +12 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +1 -1
- data/test/cases/arel/nodes/update_statement_test.rb +4 -0
- data/test/cases/arel/nodes_test.rb +3 -2
- data/test/cases/arel/select_manager_test.rb +12 -12
- data/test/cases/arel/support/fake_record.rb +22 -17
- data/test/cases/arel/table_test.rb +15 -25
- data/test/cases/arel/update_manager_test.rb +51 -6
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +1 -1
- data/test/cases/arel/visitors/dot_test.rb +177 -2
- data/test/cases/arel/visitors/mysql_test.rb +49 -1
- data/test/cases/arel/visitors/postgres_test.rb +1 -31
- data/test/cases/arel/visitors/sqlite_test.rb +1 -1
- data/test/cases/arel/visitors/to_sql_test.rb +330 -20
- data/test/cases/assertions/query_assertions_test.rb +136 -0
- data/test/cases/associations/belongs_to_associations_test.rb +502 -41
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +1 -1
- data/test/cases/associations/cascaded_eager_loading_test.rb +26 -15
- data/test/cases/associations/eager_load_nested_include_test.rb +1 -1
- data/test/cases/associations/eager_singularization_test.rb +1 -1
- data/test/cases/associations/eager_test.rb +255 -93
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +25 -53
- data/test/cases/associations/has_many_associations_test.rb +282 -72
- data/test/cases/associations/has_many_through_associations_test.rb +172 -45
- data/test/cases/associations/has_many_through_disable_joins_associations_test.rb +197 -0
- data/test/cases/associations/has_one_associations_test.rb +160 -29
- data/test/cases/associations/has_one_through_associations_test.rb +64 -15
- data/test/cases/associations/has_one_through_disable_joins_associations_test.rb +82 -0
- data/test/cases/associations/inner_join_association_test.rb +36 -6
- data/test/cases/associations/inverse_associations_test.rb +177 -40
- data/test/cases/associations/join_model_test.rb +17 -12
- data/test/cases/associations/left_outer_join_association_test.rb +14 -3
- data/test/cases/associations/nested_error_test.rb +116 -0
- data/test/cases/associations/nested_through_associations_test.rb +54 -19
- data/test/cases/associations/required_test.rb +1 -1
- data/test/cases/associations_test.rb +1278 -21
- data/test/cases/asynchronous_queries_test.rb +310 -0
- data/test/cases/attribute_methods/read_test.rb +6 -0
- data/test/cases/attribute_methods/time_zone_converter_test.rb +21 -0
- data/test/cases/attribute_methods_test.rb +565 -46
- data/test/cases/attributes_test.rb +42 -1
- data/test/cases/autosave_association_test.rb +645 -92
- data/test/cases/base_prevent_writes_test.rb +28 -159
- data/test/cases/base_test.rb +434 -209
- data/test/cases/batches_test.rb +441 -57
- data/test/cases/binary_test.rb +31 -0
- data/test/cases/bind_parameter_test.rb +107 -16
- data/test/cases/cache_key_test.rb +7 -7
- data/test/cases/calculations_test.rb +541 -110
- data/test/cases/callbacks_test.rb +0 -1
- data/test/cases/clone_test.rb +5 -4
- data/test/cases/coders/yaml_column_test.rb +97 -2
- data/test/cases/collection_cache_key_test.rb +24 -16
- data/test/cases/column_alias_test.rb +2 -8
- data/test/cases/column_definition_test.rb +12 -3
- data/test/cases/comment_test.rb +23 -26
- data/test/cases/connection_adapters/adapter_leasing_test.rb +9 -9
- data/test/cases/connection_adapters/connection_handler_test.rb +145 -99
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +79 -55
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +17 -20
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +146 -55
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +136 -23
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +96 -27
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +5 -5
- data/test/cases/connection_adapters/registration_test.rb +98 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +288 -135
- data/test/cases/connection_adapters/standalone_connection_test.rb +38 -0
- data/test/cases/connection_adapters/statement_pool_test.rb +29 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +12 -24
- data/test/cases/connection_handling_test.rb +210 -0
- data/test/cases/connection_management_test.rb +44 -7
- data/test/cases/connection_pool_test.rb +466 -99
- data/test/cases/core_test.rb +167 -9
- data/test/cases/counter_cache_test.rb +129 -2
- data/test/cases/custom_locking_test.rb +3 -3
- data/test/cases/database_configurations/hash_config_test.rb +149 -13
- data/test/cases/database_configurations/resolver_test.rb +14 -10
- data/test/cases/database_configurations/url_config_test.rb +53 -0
- data/test/cases/database_configurations_test.rb +86 -43
- data/test/cases/database_selector_test.rb +30 -8
- data/test/cases/database_statements_test.rb +10 -14
- data/test/cases/date_time_precision_test.rb +141 -11
- data/test/cases/date_time_test.rb +19 -1
- data/test/cases/defaults_test.rb +107 -41
- data/test/cases/delegated_type_test.rb +69 -9
- data/test/cases/dirty_test.rb +82 -25
- data/test/cases/disconnected_test.rb +10 -9
- data/test/cases/dup_test.rb +26 -6
- data/test/cases/encryption/cipher/aes256_gcm_test.rb +50 -0
- data/test/cases/encryption/cipher_test.rb +65 -0
- data/test/cases/encryption/concurrency_test.rb +27 -0
- data/test/cases/encryption/config_test.rb +21 -0
- data/test/cases/encryption/configurable_test.rb +93 -0
- data/test/cases/encryption/contexts_test.rb +105 -0
- data/test/cases/encryption/derived_secret_key_provider_test.rb +31 -0
- data/test/cases/encryption/deterministic_key_provider_test.rb +11 -0
- data/test/cases/encryption/encryptable_record_api_test.rb +175 -0
- data/test/cases/encryption/encryptable_record_message_pack_serialized_test.rb +42 -0
- data/test/cases/encryption/encryptable_record_test.rb +470 -0
- data/test/cases/encryption/encrypted_fixtures_test.rb +22 -0
- data/test/cases/encryption/encrypting_only_encryptor_test.rb +20 -0
- data/test/cases/encryption/encryption_schemes_test.rb +240 -0
- data/test/cases/encryption/encryptor_test.rb +113 -0
- data/test/cases/encryption/envelope_encryption_key_provider_test.rb +49 -0
- data/test/cases/encryption/extended_deterministic_queries_test.rb +81 -0
- data/test/cases/encryption/helper.rb +152 -0
- data/test/cases/encryption/key_generator_test.rb +55 -0
- data/test/cases/encryption/key_provider_test.rb +57 -0
- data/test/cases/encryption/key_test.rb +17 -0
- data/test/cases/encryption/message_pack_message_serializer_test.rb +70 -0
- data/test/cases/encryption/message_serializer_test.rb +82 -0
- data/test/cases/encryption/message_test.rb +43 -0
- data/test/cases/encryption/null_encryptor_test.rb +21 -0
- data/test/cases/encryption/properties_test.rb +69 -0
- data/test/cases/encryption/read_only_null_encryptor_test.rb +19 -0
- data/test/cases/encryption/scheme_test.rb +58 -0
- data/test/cases/encryption/unencrypted_attributes_test.rb +27 -0
- data/test/cases/encryption/uniqueness_validations_test.rb +65 -0
- data/test/cases/enum_test.rb +374 -72
- data/test/cases/errors_test.rb +7 -4
- data/test/cases/excluding_test.rb +116 -0
- data/test/cases/explain_subscriber_test.rb +6 -1
- data/test/cases/explain_test.rb +119 -10
- data/test/cases/filter_attributes_test.rb +7 -14
- data/test/cases/finder_respond_to_test.rb +3 -3
- data/test/cases/finder_test.rb +357 -72
- data/test/cases/fixture_set/file_test.rb +9 -0
- data/test/cases/fixtures_test.rb +426 -190
- data/test/cases/helper.rb +66 -192
- data/test/cases/hot_compatibility_test.rb +10 -10
- data/test/cases/inheritance_test.rb +51 -61
- data/test/cases/inherited_test.rb +40 -0
- data/test/cases/insert_all_test.rb +419 -9
- data/test/cases/instrumentation_test.rb +202 -30
- data/test/cases/integration_test.rb +25 -7
- data/test/cases/invalid_connection_test.rb +5 -5
- data/test/cases/invertible_migration_test.rb +108 -24
- data/test/cases/json_attribute_test.rb +1 -0
- data/test/cases/json_serialization_test.rb +5 -5
- data/test/cases/json_shared_test_cases.rb +5 -9
- data/test/cases/locking_test.rb +67 -31
- data/test/cases/log_subscriber_test.rb +17 -15
- data/test/cases/marshal_serialization_test.rb +78 -5
- data/test/cases/message_pack_test.rb +91 -0
- data/test/cases/migration/change_schema_test.rb +77 -46
- data/test/cases/migration/change_table_test.rb +129 -114
- data/test/cases/migration/check_constraint_test.rb +192 -10
- data/test/cases/migration/column_attributes_test.rb +4 -9
- data/test/cases/migration/column_positioning_test.rb +2 -2
- data/test/cases/migration/columns_test.rb +118 -4
- data/test/cases/migration/command_recorder_test.rb +181 -14
- data/test/cases/migration/compatibility_test.rb +883 -196
- data/test/cases/migration/create_join_table_test.rb +8 -1
- data/test/cases/migration/exclusion_constraint_test.rb +192 -0
- data/test/cases/migration/foreign_key_test.rb +356 -14
- data/test/cases/migration/helper.rb +4 -1
- data/test/cases/migration/index_test.rb +67 -2
- data/test/cases/migration/invalid_options_test.rb +129 -0
- data/test/cases/migration/logger_test.rb +7 -4
- data/test/cases/migration/pending_migrations_test.rb +103 -60
- data/test/cases/migration/references_foreign_key_test.rb +73 -4
- data/test/cases/migration/references_index_test.rb +25 -27
- data/test/cases/migration/references_statements_test.rb +27 -3
- data/test/cases/migration/rename_table_test.rb +39 -54
- data/test/cases/migration/schema_definitions_test.rb +109 -0
- data/test/cases/migration/unique_constraint_test.rb +248 -0
- data/test/cases/migration_test.rb +677 -220
- data/test/cases/migrator_test.rb +102 -75
- data/test/cases/multi_db_migrator_test.rb +55 -34
- data/test/cases/multiparameter_attributes_test.rb +26 -29
- data/test/cases/multiple_db_test.rb +42 -19
- data/test/cases/nested_attributes_test.rb +124 -6
- data/test/cases/nested_attributes_with_callbacks_test.rb +2 -2
- data/test/cases/normalized_attribute_test.rb +117 -0
- data/test/cases/null_relation_test.rb +35 -2
- data/test/cases/persistence/reload_association_cache_test.rb +20 -0
- data/test/cases/persistence_test.rb +629 -22
- data/test/cases/pooled_connections_test.rb +57 -56
- data/test/cases/prepared_statement_status_test.rb +8 -3
- data/test/cases/primary_class_test.rb +134 -0
- data/test/cases/primary_keys_test.rb +171 -55
- data/test/cases/query_cache_test.rb +558 -263
- data/test/cases/query_logs_test.rb +293 -0
- data/test/cases/quoting_test.rb +39 -72
- data/test/cases/readonly_test.rb +50 -12
- data/test/cases/reaper_test.rb +22 -6
- data/test/cases/reflection_test.rb +207 -9
- data/test/cases/relation/and_test.rb +43 -0
- data/test/cases/relation/delegation_test.rb +32 -5
- data/test/cases/relation/delete_all_test.rb +27 -6
- data/test/cases/relation/field_ordered_values_test.rb +128 -0
- data/test/cases/relation/load_async_test.rb +650 -0
- data/test/cases/relation/merging_test.rb +80 -109
- data/test/cases/relation/mutation_test.rb +12 -7
- data/test/cases/relation/or_test.rb +11 -8
- data/test/cases/relation/order_test.rb +90 -0
- data/test/cases/relation/predicate_builder_test.rb +21 -6
- data/test/cases/relation/select_test.rb +162 -3
- data/test/cases/relation/structural_compatibility_test.rb +38 -0
- data/test/cases/relation/update_all_test.rb +81 -27
- data/test/cases/relation/where_chain_test.rb +190 -3
- data/test/cases/relation/where_clause_test.rb +43 -1
- data/test/cases/relation/where_test.rb +95 -7
- data/test/cases/relation/with_test.rb +165 -0
- data/test/cases/relation_test.rb +42 -37
- data/test/cases/relations_test.rb +436 -138
- data/test/cases/reload_models_test.rb +18 -14
- data/test/cases/reserved_word_test.rb +2 -1
- data/test/cases/result_test.rb +14 -22
- data/test/cases/sanitize_test.rb +89 -27
- data/test/cases/schema_dumper_test.rb +535 -62
- data/test/cases/scoping/default_scoping_test.rb +219 -35
- data/test/cases/scoping/named_scoping_test.rb +25 -46
- data/test/cases/scoping/relation_scoping_test.rb +112 -4
- data/test/cases/secure_password_test.rb +108 -0
- data/test/cases/secure_token_test.rb +72 -0
- data/test/cases/serialization_test.rb +1 -1
- data/test/cases/serialized_attribute_test.rb +305 -60
- data/test/cases/shard_keys_test.rb +125 -0
- data/test/cases/shard_selector_test.rb +45 -0
- data/test/cases/signed_id_test.rb +57 -5
- data/test/cases/statement_cache_test.rb +31 -30
- data/test/cases/statement_invalid_test.rb +8 -4
- data/test/cases/store_test.rb +73 -9
- data/test/cases/strict_loading_test.rb +327 -13
- data/test/cases/table_metadata_test.rb +16 -0
- data/test/cases/tasks/database_tasks_test.rb +517 -244
- data/test/cases/test_case.rb +254 -60
- data/test/cases/test_case_test.rb +69 -0
- data/test/cases/test_databases_test.rb +7 -3
- data/test/cases/test_fixtures_test.rb +19 -40
- data/test/cases/time_precision_test.rb +17 -5
- data/test/cases/timestamp_test.rb +124 -16
- data/test/cases/token_for_test.rb +165 -0
- data/test/cases/touch_later_test.rb +43 -1
- data/test/cases/transaction_callbacks_test.rb +325 -8
- data/test/cases/transaction_instrumentation_test.rb +453 -0
- data/test/cases/transaction_isolation_test.rb +12 -8
- data/test/cases/transactions_test.rb +629 -112
- data/test/cases/type/date_time_test.rb +7 -1
- data/test/cases/type/time_test.rb +9 -0
- data/test/cases/type/type_map_test.rb +108 -73
- data/test/cases/type/unsigned_integer_test.rb +12 -0
- data/test/cases/type_caster/connection_test.rb +19 -0
- data/test/cases/type_test.rb +1 -1
- data/test/cases/unconnected_test.rb +7 -7
- data/test/cases/unsafe_raw_sql_test.rb +39 -8
- data/test/cases/validations/absence_validation_test.rb +1 -1
- data/test/cases/validations/association_validation_test.rb +25 -3
- data/test/cases/validations/numericality_validation_test.rb +3 -9
- data/test/cases/validations/presence_validation_test.rb +1 -1
- data/test/cases/validations/uniqueness_validation_test.rb +280 -40
- data/test/cases/validations_test.rb +2 -2
- data/test/cases/view_test.rb +33 -22
- data/test/cases/yaml_serialization_test.rb +23 -17
- data/test/config.example.yml +58 -56
- data/test/config.rb +1 -0
- data/test/fixtures/1_need_quoting.yml +2 -0
- data/test/fixtures/accounts.yml +5 -0
- data/test/fixtures/aircrafts.yml +7 -0
- data/test/fixtures/book_identifiers.yml +11 -0
- data/test/fixtures/books.yml +5 -4
- data/test/fixtures/cake_designers.yml +5 -0
- data/test/fixtures/cars.yml +6 -0
- data/test/fixtures/chefs.yml +5 -0
- data/test/fixtures/clothing_items.yml +23 -0
- data/test/fixtures/clubs.yml +1 -1
- data/test/fixtures/comments.yml +2 -1
- data/test/fixtures/cpk_authors.yml +8 -0
- data/test/fixtures/cpk_books.yml +21 -0
- data/test/fixtures/cpk_order_agreements.yml +13 -0
- data/test/fixtures/cpk_order_tags.yml +15 -0
- data/test/fixtures/cpk_orders.yml +11 -0
- data/test/fixtures/cpk_posts.yml +12 -0
- data/test/fixtures/cpk_reviews.yml +13 -0
- data/test/fixtures/cpk_tags.yml +11 -0
- data/test/fixtures/drink_designers.yml +5 -0
- data/test/fixtures/encrypted_book_that_ignores_cases.yml +4 -0
- data/test/fixtures/encrypted_books.yml +4 -0
- data/test/fixtures/fk_object_to_point_to.yml +2 -0
- data/test/fixtures/memberships.yml +15 -15
- data/test/fixtures/paragraphs.yml +5 -0
- data/test/fixtures/parrots.yml +4 -0
- data/test/fixtures/people.yml +2 -0
- data/test/fixtures/pirates.yml +2 -2
- data/test/fixtures/primary_key_error/primary_key_error.yml +6 -0
- data/test/fixtures/references.yml +3 -3
- data/test/fixtures/sharded_blog_posts.yml +14 -0
- data/test/fixtures/sharded_blog_posts_tags.yml +27 -0
- data/test/fixtures/sharded_blogs.yml +8 -0
- data/test/fixtures/sharded_comments.yml +22 -0
- data/test/fixtures/sharded_tags.yml +34 -0
- data/test/fixtures/sponsors.yml +2 -2
- data/test/fixtures/topics.yml +1 -0
- data/test/fixtures/treasures.yml +4 -0
- data/test/fixtures/virtual_columns.yml +5 -0
- data/test/fixtures/warehouse_things.yml +1 -1
- data/test/migrations/old_and_new_versions/20210716122844_add_people_description.rb +5 -0
- data/test/migrations/old_and_new_versions/20210716123013_add_people_number_of_legs.rb +5 -0
- data/test/migrations/old_and_new_versions/230_add_people_hobby.rb +5 -0
- data/test/migrations/old_and_new_versions/231_add_people_last_name.rb +5 -0
- data/test/migrations/scope/1_unscoped.rb +7 -0
- data/test/migrations/scope/2_mysql_only.mysql.rb +7 -0
- data/test/models/admin/user.rb +2 -0
- data/test/models/admin/user_json.rb +48 -0
- data/test/models/attachment.rb +7 -0
- data/test/models/author.rb +70 -3
- data/test/models/author_encrypted.rb +16 -0
- data/test/models/bird.rb +1 -1
- data/test/models/book.rb +18 -11
- data/test/models/book_destroy_async.rb +1 -1
- data/test/models/book_encrypted.rb +106 -0
- data/test/models/book_identifier.rb +5 -0
- data/test/models/branch.rb +11 -0
- data/test/models/bulb.rb +1 -1
- data/test/models/car.rb +8 -1
- data/test/models/cat.rb +1 -1
- data/test/models/category.rb +3 -1
- data/test/models/chat_message.rb +8 -0
- data/test/models/chef.rb +52 -0
- data/test/models/clothing_item.rb +12 -0
- data/test/models/club.rb +4 -1
- data/test/models/comment.rb +7 -4
- data/test/models/comment_overlapping_counter_cache.rb +15 -0
- data/test/models/company.rb +16 -2
- data/test/models/computer.rb +1 -0
- data/test/models/contact.rb +3 -3
- data/test/models/contract.rb +5 -1
- data/test/models/cpk/author.rb +9 -0
- data/test/models/cpk/book.rb +55 -0
- data/test/models/cpk/book_destroy_async.rb +9 -0
- data/test/models/cpk/car.rb +9 -0
- data/test/models/cpk/car_review.rb +9 -0
- data/test/models/cpk/chapter.rb +16 -0
- data/test/models/cpk/chapter_destroy_async.rb +10 -0
- data/test/models/cpk/comment.rb +9 -0
- data/test/models/cpk/order.rb +55 -0
- data/test/models/cpk/order_agreement.rb +10 -0
- data/test/models/cpk/order_tag.rb +10 -0
- data/test/models/cpk/post.rb +10 -0
- data/test/models/cpk/posts_tag.rb +10 -0
- data/test/models/cpk/review.rb +9 -0
- data/test/models/cpk/tag.rb +10 -0
- data/test/models/cpk.rb +15 -0
- data/test/models/customer.rb +3 -1
- data/test/models/destroy_async_parent.rb +1 -1
- data/test/models/developer.rb +44 -3
- data/test/models/discount.rb +4 -0
- data/test/models/drink_designer.rb +1 -0
- data/test/models/editor.rb +8 -0
- data/test/models/editorship.rb +6 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +6 -1
- data/test/models/essay_destroy_async.rb +1 -0
- data/test/models/eye.rb +87 -21
- data/test/models/face.rb +1 -1
- data/test/models/friendship.rb +3 -0
- data/test/models/hardback.rb +7 -0
- data/test/models/hotel.rb +2 -0
- data/test/models/human.rb +2 -2
- data/test/models/invoice.rb +2 -1
- data/test/models/invokes_an_undefined_method.rb +5 -0
- data/test/models/line_item.rb +6 -0
- data/test/models/member.rb +9 -4
- data/test/models/membership.rb +2 -2
- data/test/models/message.rb +2 -1
- data/test/models/need_quoting.rb +5 -0
- data/test/models/paragraph.rb +5 -0
- data/test/models/parrot.rb +6 -3
- data/test/models/person.rb +7 -4
- data/test/models/pirate.rb +4 -1
- data/test/models/pk_autopopulated_by_a_trigger_record.rb +5 -0
- data/test/models/post.rb +65 -2
- data/test/models/post_encrypted.rb +15 -0
- data/test/models/post_with_prefetched_pk.rb +15 -0
- data/test/models/project.rb +1 -0
- data/test/models/publication.rb +16 -0
- data/test/models/raises_argument_error.rb +5 -0
- data/test/models/raises_no_method_error.rb +5 -0
- data/test/models/recipient.rb +5 -0
- data/test/models/reference.rb +1 -1
- data/test/models/reply.rb +1 -1
- data/test/models/room.rb +3 -0
- data/test/models/sharded/blog.rb +12 -0
- data/test/models/sharded/blog_post.rb +17 -0
- data/test/models/sharded/blog_post_destroy_async.rb +14 -0
- data/test/models/sharded/blog_post_tag.rb +11 -0
- data/test/models/sharded/blog_post_with_revision.rb +11 -0
- data/test/models/sharded/comment.rb +12 -0
- data/test/models/sharded/comment_destroy_async.rb +12 -0
- data/test/models/sharded/tag.rb +11 -0
- data/test/models/sharded.rb +8 -0
- data/test/models/ship.rb +1 -1
- data/test/models/shipping_line.rb +11 -0
- data/test/models/subscriber.rb +1 -0
- data/test/models/subscription.rb +3 -1
- data/test/models/too_long_table_name.rb +5 -0
- data/test/models/topic.rb +3 -1
- data/test/models/traffic_light.rb +2 -2
- data/test/models/traffic_light_encrypted.rb +21 -0
- data/test/models/translation.rb +9 -0
- data/test/models/treasure.rb +1 -1
- data/test/models/tyre.rb +1 -1
- data/test/models/user.rb +16 -0
- data/test/models/user_with_invalid_relation.rb +28 -0
- data/test/models/uuid_comment.rb +5 -0
- data/test/models/uuid_entry.rb +5 -0
- data/test/models/uuid_message.rb +5 -0
- data/test/models/zine.rb +2 -1
- data/test/schema/mysql2_specific_schema.rb +26 -12
- data/test/schema/postgresql_specific_schema.rb +121 -13
- data/test/schema/schema.rb +361 -103
- data/test/schema/sqlite_specific_schema.rb +17 -6
- data/test/schema/trilogy_specific_schema.rb +96 -0
- data/test/support/adapter_helper.rb +104 -0
- data/test/support/async_helper.rb +15 -0
- data/test/support/config.rb +1 -1
- data/test/support/connection.rb +14 -2
- data/test/support/ddl_helper.rb +1 -1
- data/test/support/fake_adapter.rb +42 -0
- data/test/support/load_schema_helper.rb +22 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_7_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Trilogy/rails_7_1_topic_associations.dump +0 -0
- data/test/support/schema_dumping_helper.rb +15 -9
- data/test/support/tools.rb +37 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_1_no_symbol.yml +22 -0
- metadata +247 -15
data/test/cases/adapter_test.rb
CHANGED
|
@@ -10,14 +10,14 @@ require "models/event"
|
|
|
10
10
|
module ActiveRecord
|
|
11
11
|
class AdapterTest < ActiveRecord::TestCase
|
|
12
12
|
def setup
|
|
13
|
-
@connection = ActiveRecord::Base.
|
|
13
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
14
14
|
@connection.materialize_transactions
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
##
|
|
18
18
|
# PostgreSQL does not support null bytes in strings
|
|
19
19
|
unless current_adapter?(:PostgreSQLAdapter) ||
|
|
20
|
-
(current_adapter?(:SQLite3Adapter) && !ActiveRecord::Base.
|
|
20
|
+
(current_adapter?(:SQLite3Adapter) && !ActiveRecord::Base.lease_connection.prepared_statements)
|
|
21
21
|
def test_update_prepared_statement
|
|
22
22
|
b = Book.create(name: "my \x00 book")
|
|
23
23
|
b.reload
|
|
@@ -92,6 +92,10 @@ module ActiveRecord
|
|
|
92
92
|
@connection.remove_index(:accounts, name: idx_name) rescue nil
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
def test_returns_empty_indexes_for_non_existing_table
|
|
96
|
+
assert_equal [], @connection.indexes("nonexistingtable")
|
|
97
|
+
end
|
|
98
|
+
|
|
95
99
|
def test_remove_index_when_name_and_wrong_column_name_specified
|
|
96
100
|
index_name = "accounts_idx"
|
|
97
101
|
|
|
@@ -117,15 +121,26 @@ module ActiveRecord
|
|
|
117
121
|
def test_current_database
|
|
118
122
|
if @connection.respond_to?(:current_database)
|
|
119
123
|
assert_equal ARTest.test_configuration_hashes["arunit"]["database"], @connection.current_database
|
|
124
|
+
else
|
|
125
|
+
skip
|
|
120
126
|
end
|
|
121
127
|
end
|
|
122
128
|
|
|
123
|
-
|
|
129
|
+
test "#exec_query queries with no result set return an empty ActiveRecord::Result" do
|
|
124
130
|
result = @connection.exec_query "INSERT INTO subscribers(nick) VALUES('me')"
|
|
125
131
|
assert_instance_of(ActiveRecord::Result, result)
|
|
132
|
+
assert_empty result.rows
|
|
133
|
+
assert_empty result.columns
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test "#exec_query queries with an empty result set still return the columns" do
|
|
137
|
+
result = @connection.exec_query "SELECT * FROM subscribers WHERE 1=0"
|
|
138
|
+
assert_instance_of(ActiveRecord::Result, result)
|
|
139
|
+
assert_empty result.rows
|
|
140
|
+
assert_not_empty result.columns
|
|
126
141
|
end
|
|
127
142
|
|
|
128
|
-
if current_adapter?(:Mysql2Adapter)
|
|
143
|
+
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
|
|
129
144
|
def test_charset
|
|
130
145
|
assert_not_nil @connection.charset
|
|
131
146
|
assert_not_equal "character_set_database", @connection.charset
|
|
@@ -148,7 +163,7 @@ module ActiveRecord
|
|
|
148
163
|
ActiveRecord::Base.establish_connection(db_config.configuration_hash.except(:database))
|
|
149
164
|
|
|
150
165
|
config = ARTest.test_configuration_hashes
|
|
151
|
-
ActiveRecord::Base.
|
|
166
|
+
ActiveRecord::Base.lease_connection.execute(
|
|
152
167
|
"SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
|
|
153
168
|
"FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
|
|
154
169
|
)
|
|
@@ -158,6 +173,23 @@ module ActiveRecord
|
|
|
158
173
|
end
|
|
159
174
|
end
|
|
160
175
|
|
|
176
|
+
unless in_memory_db? || current_adapter?(:TrilogyAdapter)
|
|
177
|
+
def test_disable_prepared_statements
|
|
178
|
+
original_prepared_statements = ActiveRecord.disable_prepared_statements
|
|
179
|
+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
|
|
180
|
+
ActiveRecord::Base.establish_connection(db_config.configuration_hash.merge(prepared_statements: true))
|
|
181
|
+
|
|
182
|
+
assert_predicate ActiveRecord::Base.lease_connection, :prepared_statements?
|
|
183
|
+
|
|
184
|
+
ActiveRecord.disable_prepared_statements = true
|
|
185
|
+
ActiveRecord::Base.establish_connection(db_config.configuration_hash.merge(prepared_statements: true))
|
|
186
|
+
assert_not_predicate ActiveRecord::Base.lease_connection, :prepared_statements?
|
|
187
|
+
ensure
|
|
188
|
+
ActiveRecord.disable_prepared_statements = original_prepared_statements
|
|
189
|
+
ActiveRecord::Base.establish_connection :arunit
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
161
193
|
def test_table_alias
|
|
162
194
|
def @connection.test_table_alias_length() 10; end
|
|
163
195
|
class << @connection
|
|
@@ -203,7 +235,7 @@ module ActiveRecord
|
|
|
203
235
|
|
|
204
236
|
def test_numeric_value_out_of_ranges_are_translated_to_specific_exception
|
|
205
237
|
error = assert_raises(ActiveRecord::RangeError) do
|
|
206
|
-
Book.
|
|
238
|
+
Book.lease_connection.create("INSERT INTO books(author_id) VALUES (9223372036854775808)")
|
|
207
239
|
end
|
|
208
240
|
|
|
209
241
|
assert_not_nil error.cause
|
|
@@ -216,7 +248,6 @@ module ActiveRecord
|
|
|
216
248
|
actual_error = assert_raises(StandardError) do
|
|
217
249
|
@connection.execute("SELECT * FROM posts")
|
|
218
250
|
end
|
|
219
|
-
|
|
220
251
|
assert_equal original_error, actual_error
|
|
221
252
|
|
|
222
253
|
ensure
|
|
@@ -237,37 +268,7 @@ module ActiveRecord
|
|
|
237
268
|
assert result.is_a?(ActiveRecord::Result)
|
|
238
269
|
end
|
|
239
270
|
|
|
240
|
-
if ActiveRecord::Base.
|
|
241
|
-
def test_select_all_insert_update_delete_with_legacy_binds
|
|
242
|
-
binds = [[Event.column_for_attribute("id"), 1]]
|
|
243
|
-
bind_param = Arel::Nodes::BindParam.new(nil)
|
|
244
|
-
|
|
245
|
-
assert_deprecated do
|
|
246
|
-
id = @connection.insert("INSERT INTO events(id) VALUES (#{bind_param.to_sql})", nil, nil, nil, nil, binds)
|
|
247
|
-
assert_equal 1, id
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
assert_deprecated do
|
|
251
|
-
updated = @connection.update("UPDATE events SET title = 'foo' WHERE id = #{bind_param.to_sql}", nil, binds)
|
|
252
|
-
assert_equal 1, updated
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
assert_deprecated do
|
|
256
|
-
result = @connection.select_all("SELECT * FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
|
|
257
|
-
assert_equal({ "id" => 1, "title" => "foo" }, result.first)
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
assert_deprecated do
|
|
261
|
-
deleted = @connection.delete("DELETE FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
|
|
262
|
-
assert_equal 1, deleted
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
assert_deprecated do
|
|
266
|
-
result = @connection.select_all("SELECT * FROM events WHERE id = #{bind_param.to_sql}", nil, binds)
|
|
267
|
-
assert_nil result.first
|
|
268
|
-
end
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
+
if ActiveRecord::Base.lease_connection.prepared_statements
|
|
271
272
|
def test_select_all_insert_update_delete_with_casted_binds
|
|
272
273
|
binds = [Event.type_for_attribute("id").serialize(1)]
|
|
273
274
|
bind_param = Arel::Nodes::BindParam.new(nil)
|
|
@@ -332,14 +333,10 @@ module ActiveRecord
|
|
|
332
333
|
assert_equal "special_db_type", @connection.type_to_sql(:special_db_type)
|
|
333
334
|
end
|
|
334
335
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
end
|
|
336
|
+
test "inspect does not show secrets" do
|
|
337
|
+
output = @connection.inspect
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
def test_in_clause_length_is_deprecated
|
|
341
|
-
assert_deprecated { @connection.in_clause_length }
|
|
342
|
-
end
|
|
339
|
+
assert_match(/ActiveRecord::ConnectionAdapters::\w+:0x[\da-f]+ env_name="\w+" role=:writing>/, output)
|
|
343
340
|
end
|
|
344
341
|
end
|
|
345
342
|
|
|
@@ -349,7 +346,7 @@ module ActiveRecord
|
|
|
349
346
|
fixtures :fk_test_has_pk
|
|
350
347
|
|
|
351
348
|
def setup
|
|
352
|
-
@connection = ActiveRecord::Base.
|
|
349
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
353
350
|
end
|
|
354
351
|
|
|
355
352
|
def test_foreign_key_violations_are_translated_to_specific_exception_with_validate_false
|
|
@@ -413,33 +410,7 @@ module ActiveRecord
|
|
|
413
410
|
fixtures :posts, :authors, :author_addresses
|
|
414
411
|
|
|
415
412
|
def setup
|
|
416
|
-
@connection = ActiveRecord::Base.
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
unless in_memory_db?
|
|
420
|
-
test "reconnect after a disconnect" do
|
|
421
|
-
assert_predicate @connection, :active?
|
|
422
|
-
@connection.disconnect!
|
|
423
|
-
assert_not_predicate @connection, :active?
|
|
424
|
-
@connection.reconnect!
|
|
425
|
-
assert_predicate @connection, :active?
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
test "transaction state is reset after a reconnect" do
|
|
429
|
-
@connection.begin_transaction
|
|
430
|
-
assert_predicate @connection, :transaction_open?
|
|
431
|
-
@connection.reconnect!
|
|
432
|
-
assert_not_predicate @connection, :transaction_open?
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
test "transaction state is reset after a disconnect" do
|
|
436
|
-
@connection.begin_transaction
|
|
437
|
-
assert_predicate @connection, :transaction_open?
|
|
438
|
-
@connection.disconnect!
|
|
439
|
-
assert_not_predicate @connection, :transaction_open?
|
|
440
|
-
ensure
|
|
441
|
-
@connection.reconnect!
|
|
442
|
-
end
|
|
413
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
443
414
|
end
|
|
444
415
|
|
|
445
416
|
def test_create_with_query_cache
|
|
@@ -510,19 +481,19 @@ module ActiveRecord
|
|
|
510
481
|
end
|
|
511
482
|
|
|
512
483
|
# test resetting sequences in odd tables in PostgreSQL
|
|
513
|
-
if ActiveRecord::Base.
|
|
484
|
+
if ActiveRecord::Base.lease_connection.respond_to?(:reset_pk_sequence!)
|
|
514
485
|
require "models/movie"
|
|
515
486
|
require "models/subscriber"
|
|
516
487
|
|
|
517
488
|
def test_reset_empty_table_with_custom_pk
|
|
518
489
|
Movie.delete_all
|
|
519
|
-
Movie.
|
|
490
|
+
Movie.lease_connection.reset_pk_sequence! "movies"
|
|
520
491
|
assert_equal 1, Movie.create(name: "fight club").id
|
|
521
492
|
end
|
|
522
493
|
|
|
523
494
|
def test_reset_table_with_non_integer_pk
|
|
524
495
|
Subscriber.delete_all
|
|
525
|
-
Subscriber.
|
|
496
|
+
Subscriber.lease_connection.reset_pk_sequence! "subscribers"
|
|
526
497
|
sub = Subscriber.new(name: "robert drake")
|
|
527
498
|
sub.id = "bob drake"
|
|
528
499
|
assert_nothing_raised { sub.save! }
|
|
@@ -533,33 +504,572 @@ module ActiveRecord
|
|
|
533
504
|
def reset_fixtures(*fixture_names)
|
|
534
505
|
ActiveRecord::FixtureSet.reset_cache
|
|
535
506
|
|
|
536
|
-
|
|
537
|
-
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT,
|
|
507
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
508
|
+
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_names)
|
|
509
|
+
else
|
|
510
|
+
fixture_names.each do |fixture_name|
|
|
511
|
+
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT, fixture_name)
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
class AdapterConnectionTest < ActiveRecord::TestCase
|
|
518
|
+
unless in_memory_db?
|
|
519
|
+
self.use_transactional_tests = false
|
|
520
|
+
|
|
521
|
+
fixtures :posts, :authors, :author_addresses
|
|
522
|
+
|
|
523
|
+
def setup
|
|
524
|
+
@connection = ActiveRecord::Base.lease_connection
|
|
525
|
+
assert_predicate @connection, :active?
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def teardown
|
|
529
|
+
@connection.reconnect!
|
|
530
|
+
assert_predicate @connection, :active?
|
|
531
|
+
assert_not_predicate @connection, :transaction_open?
|
|
532
|
+
assert_not raw_transaction_open?(@connection)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
test "reconnect after a disconnect" do
|
|
536
|
+
@connection.disconnect!
|
|
537
|
+
assert_not_predicate @connection, :active?
|
|
538
|
+
@connection.reconnect!
|
|
539
|
+
assert_predicate @connection, :active?
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
test "materialized transaction state is reset after a reconnect" do
|
|
543
|
+
@connection.begin_transaction
|
|
544
|
+
assert_predicate @connection, :transaction_open?
|
|
545
|
+
@connection.materialize_transactions
|
|
546
|
+
assert raw_transaction_open?(@connection)
|
|
547
|
+
@connection.reconnect!
|
|
548
|
+
assert_not_predicate @connection, :transaction_open?
|
|
549
|
+
assert_not raw_transaction_open?(@connection)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
test "materialized transaction state can be restored after a reconnect" do
|
|
553
|
+
@connection.begin_transaction
|
|
554
|
+
assert_predicate @connection, :transaction_open?
|
|
555
|
+
@connection.materialize_transactions
|
|
556
|
+
assert raw_transaction_open?(@connection)
|
|
557
|
+
@connection.reconnect!(restore_transactions: true)
|
|
558
|
+
assert_predicate @connection, :transaction_open?
|
|
559
|
+
assert raw_transaction_open?(@connection)
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
test "materialized transaction state is reset after a disconnect" do
|
|
563
|
+
@connection.begin_transaction
|
|
564
|
+
assert_predicate @connection, :transaction_open?
|
|
565
|
+
@connection.materialize_transactions
|
|
566
|
+
assert raw_transaction_open?(@connection)
|
|
567
|
+
@connection.disconnect!
|
|
568
|
+
assert_not_predicate @connection, :transaction_open?
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
test "unmaterialized transaction state is reset after a reconnect" do
|
|
572
|
+
@connection.begin_transaction
|
|
573
|
+
assert_predicate @connection, :transaction_open?
|
|
574
|
+
assert_not raw_transaction_open?(@connection)
|
|
575
|
+
@connection.reconnect!
|
|
576
|
+
assert_not_predicate @connection, :transaction_open?
|
|
577
|
+
assert_not raw_transaction_open?(@connection)
|
|
578
|
+
@connection.materialize_transactions
|
|
579
|
+
assert_not raw_transaction_open?(@connection)
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
test "unmaterialized transaction state can be restored after a reconnect" do
|
|
583
|
+
@connection.begin_transaction
|
|
584
|
+
assert_predicate @connection, :transaction_open?
|
|
585
|
+
assert_not raw_transaction_open?(@connection)
|
|
586
|
+
@connection.reconnect!(restore_transactions: true)
|
|
587
|
+
assert_predicate @connection, :transaction_open?
|
|
588
|
+
assert_not raw_transaction_open?(@connection)
|
|
589
|
+
@connection.materialize_transactions
|
|
590
|
+
assert raw_transaction_open?(@connection)
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
test "unmaterialized transaction state is reset after a disconnect" do
|
|
594
|
+
@connection.begin_transaction
|
|
595
|
+
assert_predicate @connection, :transaction_open?
|
|
596
|
+
assert_not raw_transaction_open?(@connection)
|
|
597
|
+
@connection.disconnect!
|
|
598
|
+
assert_not_predicate @connection, :transaction_open?
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
test "active? detects remote disconnection" do
|
|
602
|
+
remote_disconnect @connection
|
|
603
|
+
assert_not_predicate @connection, :active?
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
test "verify! restores after remote disconnection" do
|
|
607
|
+
remote_disconnect @connection
|
|
608
|
+
@connection.verify!
|
|
609
|
+
assert_predicate @connection, :active?
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
test "reconnect! restores after remote disconnection" do
|
|
613
|
+
remote_disconnect @connection
|
|
614
|
+
@connection.reconnect!
|
|
615
|
+
assert_predicate @connection, :active?
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
test "querying a 'clean' long-failed connection restores and succeeds" do
|
|
619
|
+
remote_disconnect @connection
|
|
620
|
+
|
|
621
|
+
@connection.clean! # this simulates a fresh checkout from the pool
|
|
622
|
+
|
|
623
|
+
# Backdate last activity to simulate a connection we haven't used in a while
|
|
624
|
+
@connection.instance_variable_set(:@last_activity, Process.clock_gettime(Process::CLOCK_MONOTONIC) - 5.minutes)
|
|
625
|
+
|
|
626
|
+
# Clean did not verify / fix the connection
|
|
627
|
+
assert_not_predicate @connection, :active?
|
|
628
|
+
|
|
629
|
+
# Because the connection hasn't been verified since checkout,
|
|
630
|
+
# and the query cannot safely be retried, the connection will be
|
|
631
|
+
# verified before querying.
|
|
632
|
+
Post.delete_all
|
|
633
|
+
|
|
634
|
+
assert_predicate @connection, :active?
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
test "querying a 'clean' recently-used but now-failed connection skips verification" do
|
|
638
|
+
remote_disconnect @connection
|
|
639
|
+
|
|
640
|
+
@connection.clean! # this simulates a fresh checkout from the pool
|
|
641
|
+
|
|
642
|
+
# Clean did not verify / fix the connection
|
|
643
|
+
assert_not_predicate @connection, :active?
|
|
644
|
+
|
|
645
|
+
# Because the query cannot be retried, and we (mistakenly) believe the
|
|
646
|
+
# connection is still good, the query will fail. This is what we want,
|
|
647
|
+
# because the alternative would be excessive reverification.
|
|
648
|
+
assert_raises(ActiveRecord::AdapterError) do
|
|
649
|
+
Post.delete_all
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
test "quoting a string on a 'clean' failed connection will not prevent reconnecting" do
|
|
654
|
+
remote_disconnect @connection
|
|
655
|
+
|
|
656
|
+
@connection.clean! # this simulates a fresh checkout from the pool
|
|
657
|
+
|
|
658
|
+
# Backdate last activity to simulate a connection we haven't used in a while
|
|
659
|
+
@connection.instance_variable_set(:@last_activity, Process.clock_gettime(Process::CLOCK_MONOTONIC) - 5.minutes)
|
|
660
|
+
|
|
661
|
+
# Clean did not verify / fix the connection
|
|
662
|
+
assert_not_predicate @connection, :active?
|
|
663
|
+
|
|
664
|
+
# Quote string will not verify a broken connection (although it may
|
|
665
|
+
# reconnect in some cases)
|
|
666
|
+
Post.lease_connection.quote_string("")
|
|
667
|
+
|
|
668
|
+
# Because the connection hasn't been verified since checkout,
|
|
669
|
+
# and the query cannot safely be retried, the connection will be
|
|
670
|
+
# verified before querying.
|
|
671
|
+
Post.delete_all
|
|
672
|
+
|
|
673
|
+
assert_predicate @connection, :active?
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
test "querying after a failed non-retryable query restores and succeeds" do
|
|
677
|
+
Post.first # Connection verified (and prepared statement pool populated if enabled)
|
|
678
|
+
|
|
679
|
+
remote_disconnect @connection
|
|
680
|
+
|
|
681
|
+
assert_raises(ActiveRecord::ConnectionFailed) do
|
|
682
|
+
@connection.execute("INSERT INTO posts(title, body) VALUES ('foo', 'bar')")
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
assert Post.first # Verifying the connection causes a reconnect and the query succeeds
|
|
686
|
+
assert_predicate @connection, :active?
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
test "idempotent SELECT queries are retried and result in a reconnect" do
|
|
690
|
+
Post.first
|
|
691
|
+
|
|
692
|
+
remote_disconnect @connection
|
|
693
|
+
|
|
694
|
+
assert Post.first
|
|
695
|
+
assert_predicate @connection, :active?
|
|
696
|
+
|
|
697
|
+
remote_disconnect @connection
|
|
698
|
+
|
|
699
|
+
assert Post.where(id: [1, 2]).first
|
|
700
|
+
assert_predicate @connection, :active?
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
test "#find and #find_by queries with known attributes are retried and result in a reconnect" do
|
|
704
|
+
Post.first
|
|
705
|
+
|
|
706
|
+
remote_disconnect @connection
|
|
707
|
+
|
|
708
|
+
assert Post.find(1)
|
|
709
|
+
assert_predicate @connection, :active?
|
|
710
|
+
|
|
711
|
+
remote_disconnect @connection
|
|
712
|
+
|
|
713
|
+
assert Post.find_by(title: "Welcome to the weblog")
|
|
714
|
+
assert_predicate @connection, :active?
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
test "queries containing SQL fragments are not retried" do
|
|
718
|
+
Post.first
|
|
719
|
+
|
|
720
|
+
remote_disconnect @connection
|
|
721
|
+
|
|
722
|
+
assert_raises(ActiveRecord::ConnectionFailed) { Post.where("1 = 1").to_a }
|
|
723
|
+
assert_not_predicate @connection, :active?
|
|
724
|
+
|
|
725
|
+
remote_disconnect @connection
|
|
726
|
+
|
|
727
|
+
assert_raises(ActiveRecord::ConnectionFailed) { Post.select("title AS custom_title").first }
|
|
728
|
+
assert_not_predicate @connection, :active?
|
|
729
|
+
|
|
730
|
+
remote_disconnect @connection
|
|
731
|
+
|
|
732
|
+
assert_raises(ActiveRecord::ConnectionFailed) { Post.find_by("updated_at < ?", 2.weeks.ago) }
|
|
733
|
+
assert_not_predicate @connection, :active?
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
test "queries containing SQL functions are not retried" do
|
|
737
|
+
Post.first
|
|
738
|
+
|
|
739
|
+
remote_disconnect @connection
|
|
740
|
+
|
|
741
|
+
tags_count_attr = Post.arel_table[:tags_count]
|
|
742
|
+
abs_tags_count = Arel::Nodes::NamedFunction.new("ABS", [tags_count_attr])
|
|
743
|
+
|
|
744
|
+
assert_raises(ActiveRecord::ConnectionFailed) do
|
|
745
|
+
Post.where(abs_tags_count.eq(2)).first
|
|
746
|
+
end
|
|
747
|
+
assert_not_predicate @connection, :active?
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
test "transaction restores after remote disconnection" do
|
|
751
|
+
remote_disconnect @connection
|
|
752
|
+
Post.transaction do
|
|
753
|
+
Post.count
|
|
754
|
+
end
|
|
755
|
+
assert_predicate @connection, :active?
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
test "active transaction is restored after remote disconnection" do
|
|
759
|
+
assert_operator Post.count, :>, 0
|
|
760
|
+
Post.transaction do
|
|
761
|
+
@connection.materialize_transactions
|
|
762
|
+
remote_disconnect @connection
|
|
763
|
+
|
|
764
|
+
# Regular queries are not retryable, so the only abstract operation we can
|
|
765
|
+
# perform here is a direct verify. The outer transaction means using another
|
|
766
|
+
# here would just be a ResetParent.
|
|
767
|
+
@connection.verify!
|
|
768
|
+
|
|
769
|
+
Post.delete_all
|
|
770
|
+
|
|
771
|
+
assert_equal 0, Post.count
|
|
772
|
+
raise ActiveRecord::Rollback
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
# The deletion occurred within the outer transaction (which was then rolled
|
|
776
|
+
# back), and not directly on the freshly-reestablished connection, so the
|
|
777
|
+
# posts are still there:
|
|
778
|
+
assert_operator Post.count, :>, 0
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
test "dirty transaction cannot be restored after remote disconnection" do
|
|
782
|
+
invocations = 0
|
|
783
|
+
assert_raises ActiveRecord::ConnectionFailed do
|
|
784
|
+
Post.transaction do
|
|
785
|
+
invocations += 1
|
|
786
|
+
Post.delete_all
|
|
787
|
+
remote_disconnect @connection
|
|
788
|
+
Post.count
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
assert_equal 1, invocations # the whole transaction block is not retried
|
|
793
|
+
|
|
794
|
+
# After the (outermost) transaction block failed, the connection is
|
|
795
|
+
# ready to reconnect on next use, but hasn't done so yet
|
|
796
|
+
assert_not_predicate @connection, :active?
|
|
797
|
+
assert_operator Post.count, :>, 0
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
test "can reconnect and retry queries under limit when retry deadline is set" do
|
|
801
|
+
attempts = 0
|
|
802
|
+
@connection.stub(:retry_deadline, 0.1) do
|
|
803
|
+
@connection.send(:with_raw_connection, allow_retry: true) do
|
|
804
|
+
if attempts == 0
|
|
805
|
+
attempts += 1
|
|
806
|
+
raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
|
|
807
|
+
end
|
|
808
|
+
end
|
|
809
|
+
end
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
test "does not reconnect and retry queries when retries are disabled" do
|
|
813
|
+
assert_raises(ActiveRecord::ConnectionFailed) do
|
|
814
|
+
attempts = 0
|
|
815
|
+
@connection.send(:with_raw_connection) do
|
|
816
|
+
if attempts == 0
|
|
817
|
+
attempts += 1
|
|
818
|
+
raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
|
|
819
|
+
end
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
test "does not reconnect and retry queries that exceed retry deadline" do
|
|
825
|
+
assert_raises(ActiveRecord::ConnectionFailed) do
|
|
826
|
+
attempts = 0
|
|
827
|
+
@connection.stub(:retry_deadline, 0.1) do
|
|
828
|
+
@connection.send(:with_raw_connection, allow_retry: true) do
|
|
829
|
+
if attempts == 0
|
|
830
|
+
sleep(0.2)
|
|
831
|
+
attempts += 1
|
|
832
|
+
raise ActiveRecord::ConnectionFailed.new("Something happened to the connection")
|
|
833
|
+
end
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
test "#execute is retryable" do
|
|
840
|
+
select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
|
|
841
|
+
|
|
842
|
+
conn_id = case @connection.adapter_name
|
|
843
|
+
when "Mysql2"
|
|
844
|
+
@connection.execute("SELECT CONNECTION_ID()").to_a[0][0]
|
|
845
|
+
when "Trilogy"
|
|
846
|
+
@connection.execute("SELECT CONNECTION_ID() as connection_id").to_a[0][0]
|
|
847
|
+
when "PostgreSQL"
|
|
848
|
+
@connection.execute("SELECT pg_backend_pid()").to_a[0]["pg_backend_pid"]
|
|
849
|
+
else
|
|
850
|
+
skip("kill_connection_from_server unsupported")
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
kill_connection_from_server(conn_id)
|
|
854
|
+
|
|
855
|
+
@connection.execute(select_one_sql, allow_retry: true)
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
test "disconnect and recover on #configure_connection failure" do
|
|
859
|
+
connection = ActiveRecord::Base.connection_pool.send(:new_connection)
|
|
860
|
+
select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
|
|
861
|
+
|
|
862
|
+
failures = [ActiveRecord::ConnectionFailed.new("Oops"), ActiveRecord::ConnectionFailed.new("Oops 2")]
|
|
863
|
+
connection.singleton_class.define_method(:configure_connection) do
|
|
864
|
+
if error = failures.pop
|
|
865
|
+
raise error
|
|
866
|
+
else
|
|
867
|
+
super()
|
|
868
|
+
end
|
|
869
|
+
end
|
|
870
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
871
|
+
assert_nothing_raised do
|
|
872
|
+
connection.exec_query(select_one_sql)
|
|
873
|
+
end
|
|
874
|
+
else
|
|
875
|
+
assert_raises ActiveRecord::ConnectionFailed do
|
|
876
|
+
connection.exec_query(select_one_sql)
|
|
877
|
+
end
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
assert_equal [[1]], connection.exec_query(select_one_sql).rows
|
|
881
|
+
assert_empty failures unless current_adapter?(:IBM_DBAdapter)
|
|
882
|
+
ensure
|
|
883
|
+
connection&.disconnect!
|
|
884
|
+
end
|
|
885
|
+
|
|
886
|
+
test "disconnect and recover on #configure_connection timeout" do
|
|
887
|
+
connection = ActiveRecord::Base.connection_pool.send(:new_connection)
|
|
888
|
+
select_one_sql = current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1"
|
|
889
|
+
|
|
890
|
+
slow = [5]
|
|
891
|
+
connection.singleton_class.define_method(:configure_connection) do
|
|
892
|
+
if duration = slow.pop
|
|
893
|
+
sleep duration
|
|
894
|
+
end
|
|
895
|
+
super()
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
899
|
+
assert_nothing_raised do
|
|
900
|
+
Timeout.timeout(0.2) do
|
|
901
|
+
connection.exec_query(select_one_sql)
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
else
|
|
905
|
+
assert_raises Timeout::Error do
|
|
906
|
+
Timeout.timeout(0.2) do
|
|
907
|
+
connection.exec_query(select_one_sql)
|
|
908
|
+
end
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
assert_equal [[1]], connection.exec_query(select_one_sql).rows
|
|
913
|
+
if current_adapter?(:IBM_DBAdapter)
|
|
914
|
+
assert_equal [5], slow
|
|
915
|
+
else
|
|
916
|
+
assert_empty slow
|
|
917
|
+
end
|
|
918
|
+
ensure
|
|
919
|
+
connection&.disconnect!
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
private
|
|
923
|
+
def raw_transaction_open?(connection)
|
|
924
|
+
case connection.adapter_name
|
|
925
|
+
when "PostgreSQL"
|
|
926
|
+
connection.instance_variable_get(:@raw_connection).transaction_status == ::PG::PQTRANS_INTRANS
|
|
927
|
+
when "Mysql2", "Trilogy"
|
|
928
|
+
begin
|
|
929
|
+
connection.instance_variable_get(:@raw_connection).query("SAVEPOINT transaction_test")
|
|
930
|
+
connection.instance_variable_get(:@raw_connection).query("RELEASE SAVEPOINT transaction_test")
|
|
931
|
+
|
|
932
|
+
true
|
|
933
|
+
rescue
|
|
934
|
+
false
|
|
935
|
+
end
|
|
936
|
+
when "SQLite"
|
|
937
|
+
begin
|
|
938
|
+
connection.instance_variable_get(:@raw_connection).transaction { nil }
|
|
939
|
+
false
|
|
940
|
+
rescue
|
|
941
|
+
true
|
|
942
|
+
end
|
|
943
|
+
else
|
|
944
|
+
skip("kill_connection_from_server unsupported")
|
|
945
|
+
end
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
def remote_disconnect(connection)
|
|
949
|
+
case connection.adapter_name
|
|
950
|
+
when "PostgreSQL"
|
|
951
|
+
# Connection was left in a bad state, need to reconnect to simulate fresh disconnect
|
|
952
|
+
connection.verify! if connection.instance_variable_get(:@raw_connection).status == ::PG::CONNECTION_BAD
|
|
953
|
+
unless connection.instance_variable_get(:@raw_connection).transaction_status == ::PG::PQTRANS_INTRANS
|
|
954
|
+
connection.instance_variable_get(:@raw_connection).async_exec("begin")
|
|
955
|
+
end
|
|
956
|
+
connection.instance_variable_get(:@raw_connection).async_exec("set idle_in_transaction_session_timeout = '10ms'")
|
|
957
|
+
sleep 0.05
|
|
958
|
+
when "Mysql2", "Trilogy"
|
|
959
|
+
connection.send(:internal_execute, "set @@wait_timeout=1", materialize_transactions: false)
|
|
960
|
+
sleep 1.2
|
|
961
|
+
else
|
|
962
|
+
skip("remote_disconnect unsupported")
|
|
963
|
+
end
|
|
964
|
+
end
|
|
965
|
+
|
|
966
|
+
def kill_connection_from_server(connection_id)
|
|
967
|
+
conn = @connection.pool.checkout
|
|
968
|
+
case conn.adapter_name
|
|
969
|
+
when "Mysql2", "Trilogy"
|
|
970
|
+
conn.execute("KILL #{connection_id}")
|
|
971
|
+
when "PostgreSQL"
|
|
972
|
+
conn.execute("SELECT pg_cancel_backend(#{connection_id})")
|
|
973
|
+
else
|
|
974
|
+
skip("kill_connection_from_server unsupported")
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
conn.close
|
|
978
|
+
end
|
|
979
|
+
end
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
class AdapterThreadSafetyTest < ActiveRecord::TestCase
|
|
983
|
+
setup do
|
|
984
|
+
@threads = []
|
|
985
|
+
@connection = ActiveRecord::Base.connection_pool.checkout
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
teardown do
|
|
989
|
+
@threads.each(&:kill)
|
|
990
|
+
end
|
|
991
|
+
|
|
992
|
+
unless in_memory_db?
|
|
993
|
+
test "#active? is synchronized" do
|
|
994
|
+
threads(2, 25) { @connection.select_all(current_adapter?(:IBM_DBAdapter) ? "SELECT 1 FROM SYSIBM.SYSDUMMY1" : "SELECT 1") }
|
|
995
|
+
threads(2, 25) { @connection.verify! }
|
|
996
|
+
threads(2, 25) { @connection.disconnect! }
|
|
997
|
+
|
|
998
|
+
join
|
|
999
|
+
pass
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
test "#verify! is synchronized" do
|
|
1003
|
+
threads(2, 25) { @connection.verify! }
|
|
1004
|
+
threads(2, 25) { @connection.disconnect! }
|
|
1005
|
+
|
|
1006
|
+
join
|
|
1007
|
+
pass
|
|
1008
|
+
end
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
private
|
|
1012
|
+
def join
|
|
1013
|
+
@threads.shuffle.each(&:join)
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
def threads(count, times)
|
|
1017
|
+
@threads += count.times.map do
|
|
1018
|
+
Thread.new do
|
|
1019
|
+
times.times do
|
|
1020
|
+
yield
|
|
1021
|
+
Thread.pass
|
|
1022
|
+
end
|
|
1023
|
+
end
|
|
538
1024
|
end
|
|
539
1025
|
end
|
|
540
1026
|
end
|
|
541
1027
|
end
|
|
542
1028
|
|
|
543
|
-
if ActiveRecord::Base.
|
|
1029
|
+
if ActiveRecord::Base.lease_connection.supports_advisory_locks?
|
|
544
1030
|
class AdvisoryLocksEnabledTest < ActiveRecord::TestCase
|
|
545
1031
|
include ConnectionHelper
|
|
546
1032
|
|
|
547
1033
|
def test_advisory_locks_enabled?
|
|
548
|
-
|
|
1034
|
+
assert_predicate ActiveRecord::Base.lease_connection, :advisory_locks_enabled?
|
|
549
1035
|
|
|
550
1036
|
run_without_connection do |orig_connection|
|
|
551
1037
|
ActiveRecord::Base.establish_connection(
|
|
552
1038
|
orig_connection.merge(advisory_locks: false)
|
|
553
1039
|
)
|
|
554
1040
|
|
|
555
|
-
assert_not ActiveRecord::Base.
|
|
1041
|
+
assert_not ActiveRecord::Base.lease_connection.advisory_locks_enabled?
|
|
556
1042
|
|
|
557
1043
|
ActiveRecord::Base.establish_connection(
|
|
558
1044
|
orig_connection.merge(advisory_locks: true)
|
|
559
1045
|
)
|
|
560
1046
|
|
|
561
|
-
|
|
1047
|
+
assert_predicate ActiveRecord::Base.lease_connection, :advisory_locks_enabled?
|
|
1048
|
+
end
|
|
1049
|
+
end
|
|
1050
|
+
end
|
|
1051
|
+
end
|
|
1052
|
+
|
|
1053
|
+
if ActiveRecord::Base.lease_connection.savepoint_errors_invalidate_transactions?
|
|
1054
|
+
class InvalidateTransactionTest < ActiveRecord::TestCase
|
|
1055
|
+
def test_invalidates_transaction_on_rollback_error
|
|
1056
|
+
@invalidated = false
|
|
1057
|
+
connection = ActiveRecord::Base.lease_connection
|
|
1058
|
+
|
|
1059
|
+
connection.transaction do
|
|
1060
|
+
connection.send(:with_raw_connection) do
|
|
1061
|
+
raise ActiveRecord::Deadlocked, "made-up deadlock"
|
|
1062
|
+
end
|
|
1063
|
+
|
|
1064
|
+
rescue ActiveRecord::Deadlocked => error
|
|
1065
|
+
flunk("Rescuing wrong error") unless error.message == "made-up deadlock"
|
|
1066
|
+
|
|
1067
|
+
@invalidated = connection.current_transaction.invalidated?
|
|
562
1068
|
end
|
|
1069
|
+
|
|
1070
|
+
# asserting outside of the transaction to make sure we actually reach the end of the test
|
|
1071
|
+
# and perform the assertion
|
|
1072
|
+
assert @invalidated
|
|
563
1073
|
end
|
|
564
1074
|
end
|
|
565
1075
|
end
|