ibm_db 5.2.0-x86-mingw32 → 5.3.2-x86-mingw32
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/CHANGES +9 -0
- data/LICENSE +55 -18
- data/ext/Makefile +15 -13
- data/ext/ibm_db.c +62 -57
- data/ext/ibm_db.o +0 -0
- data/ext/ibm_db.so +0 -0
- data/ext/mkmf.log +26 -24
- data/ext/ruby_ibm_db_cli.c +1 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
- data/lib/ibm_db.so +1 -0
- data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
- data/test/activejob/destroy_association_async_test.rb +305 -0
- data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
- data/test/activejob/helper.rb +15 -0
- data/test/assets/schema_dump_5_1.yml +345 -0
- data/test/cases/adapter_prevent_writes_test.rb +334 -0
- data/test/cases/adapter_test.rb +432 -218
- data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
- data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
- data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
- data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
- data/test/cases/adapters/mysql2/connection_test.rb +48 -50
- data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
- data/test/cases/adapters/mysql2/enum_test.rb +32 -11
- data/test/cases/adapters/mysql2/explain_test.rb +13 -11
- data/test/cases/adapters/mysql2/json_test.rb +17 -188
- data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
- data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
- data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
- data/test/cases/adapters/mysql2/schema_test.rb +24 -22
- data/test/cases/adapters/mysql2/set_test.rb +32 -0
- data/test/cases/adapters/mysql2/sp_test.rb +10 -8
- data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
- data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
- data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
- data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
- data/test/cases/adapters/postgresql/array_test.rb +118 -63
- data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
- data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
- data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
- data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
- data/test/cases/adapters/postgresql/citext_test.rb +58 -58
- data/test/cases/adapters/postgresql/collation_test.rb +17 -15
- data/test/cases/adapters/postgresql/composite_test.rb +25 -23
- data/test/cases/adapters/postgresql/connection_test.rb +73 -85
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
- data/test/cases/adapters/postgresql/date_test.rb +42 -0
- data/test/cases/adapters/postgresql/domain_test.rb +9 -7
- data/test/cases/adapters/postgresql/enum_test.rb +12 -10
- data/test/cases/adapters/postgresql/explain_test.rb +10 -8
- data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
- data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
- data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
- data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
- data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
- data/test/cases/adapters/postgresql/integer_test.rb +2 -0
- data/test/cases/adapters/postgresql/interval_test.rb +99 -0
- data/test/cases/adapters/postgresql/json_test.rb +16 -201
- data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
- data/test/cases/adapters/postgresql/money_test.rb +47 -16
- data/test/cases/adapters/postgresql/network_test.rb +36 -28
- data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
- data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
- data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
- data/test/cases/adapters/postgresql/range_test.rb +406 -292
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
- data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
- data/test/cases/adapters/postgresql/schema_test.rb +207 -91
- data/test/cases/adapters/postgresql/serial_test.rb +9 -7
- data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
- data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
- data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
- data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
- data/test/cases/adapters/postgresql/utils_test.rb +11 -9
- data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
- data/test/cases/adapters/postgresql/xml_test.rb +10 -14
- data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
- data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
- data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
- data/test/cases/adapters/sqlite3/json_test.rb +29 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
- data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
- data/test/cases/aggregations_test.rb +14 -12
- data/test/cases/annotate_test.rb +46 -0
- data/test/cases/ar_schema_test.rb +153 -86
- data/test/cases/arel/attributes/attribute_test.rb +1145 -0
- data/test/cases/arel/attributes/math_test.rb +83 -0
- data/test/cases/arel/attributes_test.rb +27 -0
- data/test/cases/arel/collectors/bind_test.rb +40 -0
- data/test/cases/arel/collectors/composite_test.rb +47 -0
- data/test/cases/arel/collectors/sql_string_test.rb +41 -0
- data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
- data/test/cases/arel/crud_test.rb +65 -0
- data/test/cases/arel/delete_manager_test.rb +53 -0
- data/test/cases/arel/factory_methods_test.rb +46 -0
- data/test/cases/arel/helper.rb +45 -0
- data/test/cases/arel/insert_manager_test.rb +241 -0
- data/test/cases/arel/nodes/and_test.rb +30 -0
- data/test/cases/arel/nodes/as_test.rb +36 -0
- data/test/cases/arel/nodes/ascending_test.rb +46 -0
- data/test/cases/arel/nodes/bin_test.rb +35 -0
- data/test/cases/arel/nodes/binary_test.rb +29 -0
- data/test/cases/arel/nodes/bind_param_test.rb +22 -0
- data/test/cases/arel/nodes/case_test.rb +96 -0
- data/test/cases/arel/nodes/casted_test.rb +18 -0
- data/test/cases/arel/nodes/comment_test.rb +22 -0
- data/test/cases/arel/nodes/count_test.rb +35 -0
- data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
- data/test/cases/arel/nodes/descending_test.rb +46 -0
- data/test/cases/arel/nodes/distinct_test.rb +21 -0
- data/test/cases/arel/nodes/equality_test.rb +62 -0
- data/test/cases/arel/nodes/extract_test.rb +43 -0
- data/test/cases/arel/nodes/false_test.rb +21 -0
- data/test/cases/arel/nodes/grouping_test.rb +26 -0
- data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
- data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
- data/test/cases/arel/nodes/named_function_test.rb +48 -0
- data/test/cases/arel/nodes/node_test.rb +22 -0
- data/test/cases/arel/nodes/not_test.rb +31 -0
- data/test/cases/arel/nodes/or_test.rb +36 -0
- data/test/cases/arel/nodes/over_test.rb +69 -0
- data/test/cases/arel/nodes/select_core_test.rb +79 -0
- data/test/cases/arel/nodes/select_statement_test.rb +51 -0
- data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
- data/test/cases/arel/nodes/sum_test.rb +35 -0
- data/test/cases/arel/nodes/table_alias_test.rb +29 -0
- data/test/cases/arel/nodes/true_test.rb +21 -0
- data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
- data/test/cases/arel/nodes/update_statement_test.rb +60 -0
- data/test/cases/arel/nodes/window_test.rb +81 -0
- data/test/cases/arel/nodes_test.rb +34 -0
- data/test/cases/arel/select_manager_test.rb +1238 -0
- data/test/cases/arel/support/fake_record.rb +135 -0
- data/test/cases/arel/table_test.rb +216 -0
- data/test/cases/arel/update_manager_test.rb +126 -0
- data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
- data/test/cases/arel/visitors/dot_test.rb +90 -0
- data/test/cases/arel/visitors/mysql_test.rb +157 -0
- data/test/cases/arel/visitors/postgres_test.rb +366 -0
- data/test/cases/arel/visitors/sqlite_test.rb +75 -0
- data/test/cases/arel/visitors/to_sql_test.rb +750 -0
- data/test/cases/associations/belongs_to_associations_test.rb +510 -158
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
- data/test/cases/associations/callbacks_test.rb +56 -38
- data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
- data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
- data/test/cases/associations/eager_singularization_test.rb +21 -21
- data/test/cases/associations/eager_test.rb +559 -415
- data/test/cases/associations/extension_test.rb +18 -12
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
- data/test/cases/associations/has_many_associations_test.rb +1038 -465
- data/test/cases/associations/has_many_through_associations_test.rb +558 -249
- data/test/cases/associations/has_one_associations_test.rb +294 -129
- data/test/cases/associations/has_one_through_associations_test.rb +121 -75
- data/test/cases/associations/inner_join_association_test.rb +114 -38
- data/test/cases/associations/inverse_associations_test.rb +606 -398
- data/test/cases/associations/join_model_test.rb +158 -148
- data/test/cases/associations/left_outer_join_association_test.rb +59 -24
- data/test/cases/associations/nested_through_associations_test.rb +166 -109
- data/test/cases/associations/required_test.rb +35 -10
- data/test/cases/associations_test.rb +241 -110
- data/test/cases/attribute_methods/read_test.rb +11 -11
- data/test/cases/attribute_methods_test.rb +413 -298
- data/test/cases/attributes_test.rb +145 -27
- data/test/cases/autosave_association_test.rb +681 -436
- data/test/cases/base_prevent_writes_test.rb +229 -0
- data/test/cases/base_test.rb +599 -542
- data/test/cases/batches_test.rb +288 -82
- data/test/cases/binary_test.rb +26 -31
- data/test/cases/bind_parameter_test.rb +194 -21
- data/test/cases/boolean_test.rb +52 -0
- data/test/cases/cache_key_test.rb +110 -5
- data/test/cases/calculations_test.rb +740 -177
- data/test/cases/callbacks_test.rb +74 -207
- data/test/cases/clone_test.rb +15 -10
- data/test/cases/coders/json_test.rb +2 -0
- data/test/cases/coders/yaml_column_test.rb +16 -13
- data/test/cases/collection_cache_key_test.rb +177 -20
- data/test/cases/column_alias_test.rb +9 -7
- data/test/cases/column_definition_test.rb +10 -68
- data/test/cases/comment_test.rb +166 -107
- data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
- data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
- data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
- data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
- data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
- data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
- data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
- data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
- data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
- data/test/cases/connection_management_test.rb +13 -11
- data/test/cases/connection_pool_test.rb +316 -83
- data/test/cases/core_test.rb +82 -58
- data/test/cases/counter_cache_test.rb +204 -50
- data/test/cases/custom_locking_test.rb +5 -3
- data/test/cases/database_configurations/hash_config_test.rb +74 -0
- data/test/cases/database_configurations/resolver_test.rb +150 -0
- data/test/cases/database_configurations_test.rb +145 -0
- data/test/cases/database_selector_test.rb +296 -0
- data/test/cases/database_statements_test.rb +18 -16
- data/test/cases/date_test.rb +8 -16
- data/test/cases/date_time_precision_test.rb +100 -78
- data/test/cases/date_time_test.rb +23 -8
- data/test/cases/defaults_test.rb +106 -71
- data/test/cases/delegated_type_test.rb +57 -0
- data/test/cases/dirty_test.rb +419 -223
- data/test/cases/disconnected_test.rb +6 -6
- data/test/cases/dup_test.rb +54 -27
- data/test/cases/enum_test.rb +461 -82
- data/test/cases/errors_test.rb +7 -7
- data/test/cases/explain_subscriber_test.rb +17 -15
- data/test/cases/explain_test.rb +11 -19
- data/test/cases/filter_attributes_test.rb +153 -0
- data/test/cases/finder_respond_to_test.rb +14 -14
- data/test/cases/finder_test.rb +669 -287
- data/test/cases/fixture_set/file_test.rb +34 -38
- data/test/cases/fixtures_test.rb +833 -176
- data/test/cases/forbidden_attributes_protection_test.rb +32 -67
- data/test/cases/habtm_destroy_order_test.rb +25 -25
- data/test/cases/helper.rb +78 -49
- data/test/cases/hot_compatibility_test.rb +33 -32
- data/test/cases/i18n_test.rb +18 -17
- data/test/cases/inheritance_test.rb +180 -115
- data/test/cases/insert_all_test.rb +489 -0
- data/test/cases/instrumentation_test.rb +101 -0
- data/test/cases/integration_test.rb +119 -31
- data/test/cases/invalid_connection_test.rb +18 -16
- data/test/cases/invertible_migration_test.rb +183 -43
- data/test/cases/json_attribute_test.rb +35 -0
- data/test/cases/json_serialization_test.rb +57 -58
- data/test/cases/json_shared_test_cases.rb +290 -0
- data/test/cases/locking_test.rb +413 -119
- data/test/cases/log_subscriber_test.rb +68 -26
- data/test/cases/marshal_serialization_test.rb +39 -0
- data/test/cases/migration/change_schema_test.rb +118 -72
- data/test/cases/migration/change_table_test.rb +138 -30
- data/test/cases/migration/check_constraint_test.rb +162 -0
- data/test/cases/migration/column_attributes_test.rb +45 -35
- data/test/cases/migration/column_positioning_test.rb +18 -6
- data/test/cases/migration/columns_test.rb +93 -77
- data/test/cases/migration/command_recorder_test.rb +121 -34
- data/test/cases/migration/compatibility_test.rb +578 -23
- data/test/cases/migration/create_join_table_test.rb +35 -25
- data/test/cases/migration/foreign_key_test.rb +503 -284
- data/test/cases/migration/helper.rb +4 -3
- data/test/cases/migration/index_test.rb +119 -70
- data/test/cases/migration/logger_test.rb +9 -6
- data/test/cases/migration/pending_migrations_test.rb +88 -34
- data/test/cases/migration/references_foreign_key_test.rb +164 -150
- data/test/cases/migration/references_index_test.rb +38 -19
- data/test/cases/migration/references_statements_test.rb +15 -14
- data/test/cases/migration/rename_table_test.rb +53 -30
- data/test/cases/migration_test.rb +637 -269
- data/test/cases/migrator_test.rb +191 -135
- data/test/cases/mixin_test.rb +7 -11
- data/test/cases/modules_test.rb +36 -34
- data/test/cases/multi_db_migrator_test.rb +223 -0
- data/test/cases/multiparameter_attributes_test.rb +60 -33
- data/test/cases/multiple_db_test.rb +16 -22
- data/test/cases/nested_attributes_test.rb +341 -320
- data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
- data/test/cases/null_relation_test.rb +84 -0
- data/test/cases/numeric_data_test.rb +93 -0
- data/test/cases/persistence_test.rb +361 -269
- data/test/cases/pooled_connections_test.rb +18 -26
- data/test/cases/prepared_statement_status_test.rb +48 -0
- data/test/cases/primary_keys_test.rb +210 -104
- data/test/cases/query_cache_test.rb +610 -141
- data/test/cases/quoting_test.rb +132 -31
- data/test/cases/readonly_test.rb +49 -48
- data/test/cases/reaper_test.rb +146 -32
- data/test/cases/reflection_test.rb +167 -156
- data/test/cases/relation/delegation_test.rb +49 -36
- data/test/cases/relation/delete_all_test.rb +117 -0
- data/test/cases/relation/merging_test.rb +319 -42
- data/test/cases/relation/mutation_test.rb +55 -93
- data/test/cases/relation/or_test.rb +129 -29
- data/test/cases/relation/predicate_builder_test.rb +21 -6
- data/test/cases/relation/record_fetch_warning_test.rb +5 -3
- data/test/cases/relation/select_test.rb +67 -0
- data/test/cases/relation/update_all_test.rb +317 -0
- data/test/cases/relation/where_chain_test.rb +68 -32
- data/test/cases/relation/where_clause_test.rb +136 -61
- data/test/cases/relation/where_test.rb +155 -48
- data/test/cases/relation_test.rb +266 -112
- data/test/cases/relations_test.rb +969 -744
- data/test/cases/reload_models_test.rb +13 -9
- data/test/cases/reserved_word_test.rb +141 -0
- data/test/cases/result_test.rb +68 -17
- data/test/cases/sanitize_test.rb +87 -71
- data/test/cases/schema_dumper_test.rb +221 -128
- data/test/cases/schema_loading_test.rb +3 -2
- data/test/cases/scoping/default_scoping_test.rb +185 -144
- data/test/cases/scoping/named_scoping_test.rb +177 -89
- data/test/cases/scoping/relation_scoping_test.rb +197 -75
- data/test/cases/secure_token_test.rb +18 -3
- data/test/cases/serialization_test.rb +30 -28
- data/test/cases/serialized_attribute_test.rb +133 -42
- data/test/cases/signed_id_test.rb +168 -0
- data/test/cases/statement_cache_test.rb +41 -24
- data/test/cases/statement_invalid_test.rb +42 -0
- data/test/cases/store_test.rb +180 -55
- data/test/cases/strict_loading_test.rb +473 -0
- data/test/cases/suppressor_test.rb +26 -12
- data/test/cases/tasks/database_tasks_test.rb +1258 -194
- data/test/cases/tasks/mysql_rake_test.rb +370 -298
- data/test/cases/tasks/postgresql_rake_test.rb +481 -251
- data/test/cases/tasks/sqlite_rake_test.rb +225 -178
- data/test/cases/test_case.rb +51 -40
- data/test/cases/test_databases_test.rb +79 -0
- data/test/cases/test_fixtures_test.rb +79 -19
- data/test/cases/time_precision_test.rb +98 -76
- data/test/cases/timestamp_test.rb +102 -99
- data/test/cases/touch_later_test.rb +12 -10
- data/test/cases/transaction_callbacks_test.rb +344 -90
- data/test/cases/transaction_isolation_test.rb +12 -12
- data/test/cases/transactions_test.rb +612 -162
- data/test/cases/type/adapter_specific_registry_test.rb +14 -2
- data/test/cases/type/date_time_test.rb +4 -2
- data/test/cases/type/integer_test.rb +4 -2
- data/test/cases/type/string_test.rb +10 -8
- data/test/cases/type/time_test.rb +28 -0
- data/test/cases/type/type_map_test.rb +29 -28
- data/test/cases/type/unsigned_integer_test.rb +19 -0
- data/test/cases/type_test.rb +2 -0
- data/test/cases/types_test.rb +3 -1
- data/test/cases/unconnected_test.rb +14 -1
- data/test/cases/unsafe_raw_sql_test.rb +274 -0
- data/test/cases/validations/absence_validation_test.rb +19 -17
- data/test/cases/validations/association_validation_test.rb +30 -28
- data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
- data/test/cases/validations/i18n_validation_test.rb +22 -21
- data/test/cases/validations/length_validation_test.rb +34 -33
- data/test/cases/validations/numericality_validation_test.rb +181 -0
- data/test/cases/validations/presence_validation_test.rb +21 -19
- data/test/cases/validations/uniqueness_validation_test.rb +156 -86
- data/test/cases/validations_repair_helper.rb +2 -0
- data/test/cases/validations_test.rb +61 -26
- data/test/cases/view_test.rb +122 -116
- data/test/cases/yaml_serialization_test.rb +79 -34
- data/test/config.example.yml +19 -19
- data/test/config.rb +3 -1
- data/test/config.yml +16 -6
- data/test/fixtures/all/namespaced/accounts.yml +2 -0
- data/test/fixtures/author_addresses.yml +1 -8
- data/test/fixtures/authors.yml +1 -7
- data/test/fixtures/binaries.yml +4 -0
- data/test/fixtures/books.yml +9 -2
- data/test/fixtures/categories_posts.yml +3 -0
- data/test/fixtures/citations.yml +5 -0
- data/test/fixtures/comments.yml +7 -0
- data/test/fixtures/companies.yml +5 -0
- data/test/fixtures/computers.yml +2 -0
- data/test/fixtures/customers.yml +10 -1
- data/test/fixtures/developers.yml +1 -1
- data/test/fixtures/essays.yml +10 -0
- data/test/fixtures/faces.yml +3 -3
- data/test/fixtures/humans.yml +5 -0
- data/test/fixtures/interests.yml +7 -7
- data/test/fixtures/memberships.yml +7 -0
- data/test/fixtures/minimalistics.yml +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +2 -2
- data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
- data/test/fixtures/naked/yml/parrots.yml +1 -0
- data/test/fixtures/other_books.yml +26 -0
- data/test/fixtures/other_posts.yml +1 -0
- data/test/fixtures/parrots.yml +7 -1
- data/test/fixtures/pirates.yml +3 -0
- data/test/fixtures/posts.yml +11 -3
- data/test/fixtures/readers.yml +6 -0
- data/test/fixtures/reserved_words/values.yml +2 -2
- data/test/fixtures/sponsors.yml +3 -0
- data/test/fixtures/strict_zines.yml +2 -0
- data/test/fixtures/subscribers.yml +1 -1
- data/test/fixtures/tasks.yml +1 -1
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/migrations/10_urban/9_add_expressions.rb +2 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
- data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
- data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
- data/test/migrations/missing/1_people_have_last_names.rb +2 -0
- data/test/migrations/missing/3_we_need_reminders.rb +2 -0
- data/test/migrations/missing/4_innocent_jointable.rb +3 -1
- data/test/migrations/rename/1_we_need_things.rb +2 -0
- data/test/migrations/rename/2_rename_things.rb +2 -0
- data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
- data/test/migrations/to_copy2/1_create_articles.rb +2 -0
- data/test/migrations/to_copy2/2_create_comments.rb +3 -1
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
- data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
- data/test/migrations/valid/2_we_need_reminders.rb +2 -0
- data/test/migrations/valid/3_innocent_jointable.rb +3 -1
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
- data/test/models/account.rb +46 -0
- data/test/models/admin/account.rb +3 -1
- data/test/models/admin/randomly_named_c1.rb +2 -0
- data/test/models/admin/user.rb +16 -8
- data/test/models/admin.rb +4 -2
- data/test/models/aircraft.rb +3 -1
- data/test/models/arunit2_model.rb +2 -0
- data/test/models/author.rb +153 -102
- data/test/models/auto_id.rb +2 -0
- data/test/models/autoloadable/extra_firm.rb +2 -0
- data/test/models/binary.rb +3 -1
- data/test/models/binary_field.rb +6 -0
- data/test/models/bird.rb +13 -1
- data/test/models/book.rb +14 -4
- data/test/models/book_destroy_async.rb +24 -0
- data/test/models/boolean.rb +5 -0
- data/test/models/bulb.rb +13 -4
- data/test/models/cake_designer.rb +2 -0
- data/test/models/car.rb +17 -10
- data/test/models/carrier.rb +2 -0
- data/test/models/cart.rb +5 -0
- data/test/models/cat.rb +2 -0
- data/test/models/categorization.rb +8 -6
- data/test/models/category.rb +28 -16
- data/test/models/chef.rb +2 -0
- data/test/models/citation.rb +5 -1
- data/test/models/club.rb +13 -10
- data/test/models/college.rb +4 -2
- data/test/models/column.rb +2 -0
- data/test/models/column_name.rb +2 -0
- data/test/models/comment.rb +32 -10
- data/test/models/company.rb +102 -106
- data/test/models/company_in_module.rb +27 -26
- data/test/models/computer.rb +3 -1
- data/test/models/contact.rb +15 -13
- data/test/models/content.rb +5 -3
- data/test/models/contract.rb +21 -3
- data/test/models/country.rb +2 -4
- data/test/models/course.rb +3 -1
- data/test/models/customer.rb +10 -8
- data/test/models/customer_carrier.rb +2 -0
- data/test/models/dashboard.rb +2 -0
- data/test/models/default.rb +2 -0
- data/test/models/department.rb +2 -0
- data/test/models/destroy_async_parent.rb +15 -0
- data/test/models/destroy_async_parent_soft_delete.rb +20 -0
- data/test/models/developer.rb +152 -85
- data/test/models/dl_keyed_belongs_to.rb +13 -0
- data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
- data/test/models/dl_keyed_has_many.rb +5 -0
- data/test/models/dl_keyed_has_many_through.rb +5 -0
- data/test/models/dl_keyed_has_one.rb +5 -0
- data/test/models/dl_keyed_join.rb +10 -0
- data/test/models/dog.rb +2 -0
- data/test/models/dog_lover.rb +2 -0
- data/test/models/doubloon.rb +3 -1
- data/test/models/drink_designer.rb +17 -0
- data/test/models/edge.rb +4 -2
- data/test/models/electron.rb +2 -0
- data/test/models/engine.rb +3 -2
- data/test/models/entrant.rb +2 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +6 -3
- data/test/models/essay_destroy_async.rb +12 -0
- data/test/models/event.rb +3 -1
- data/test/models/eye.rb +5 -3
- data/test/models/face.rb +14 -6
- data/test/models/family.rb +6 -0
- data/test/models/family_tree.rb +6 -0
- data/test/models/friendship.rb +5 -3
- data/test/models/frog.rb +8 -0
- data/test/models/guid.rb +3 -1
- data/test/models/guitar.rb +2 -0
- data/test/models/hotel.rb +5 -3
- data/test/models/human.rb +39 -0
- data/test/models/image.rb +3 -1
- data/test/models/interest.rb +14 -3
- data/test/models/invoice.rb +4 -2
- data/test/models/item.rb +3 -1
- data/test/models/job.rb +5 -3
- data/test/models/joke.rb +4 -2
- data/test/models/keyboard.rb +3 -1
- data/test/models/legacy_thing.rb +2 -0
- data/test/models/lesson.rb +2 -0
- data/test/models/line_item.rb +3 -1
- data/test/models/liquid.rb +2 -0
- data/test/models/matey.rb +3 -1
- data/test/models/measurement.rb +4 -0
- data/test/models/member.rb +23 -20
- data/test/models/member_detail.rb +3 -0
- data/test/models/member_type.rb +2 -0
- data/test/models/membership.rb +4 -1
- data/test/models/mentor.rb +3 -1
- data/test/models/message.rb +5 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/minivan.rb +3 -2
- data/test/models/mixed_case_monkey.rb +3 -1
- data/test/models/molecule.rb +2 -0
- data/test/models/mouse.rb +6 -0
- data/test/models/movie.rb +2 -0
- data/test/models/node.rb +4 -2
- data/test/models/non_primary_key.rb +2 -0
- data/test/models/notification.rb +2 -0
- data/test/models/numeric_data.rb +12 -0
- data/test/models/order.rb +4 -2
- data/test/models/organization.rb +9 -7
- data/test/models/other_dog.rb +3 -1
- data/test/models/owner.rb +6 -4
- data/test/models/parrot.rb +12 -4
- data/test/models/person.rb +59 -54
- data/test/models/personal_legacy_thing.rb +3 -1
- data/test/models/pet.rb +4 -2
- data/test/models/pet_treasure.rb +2 -0
- data/test/models/pirate.rb +67 -43
- data/test/models/possession.rb +3 -1
- data/test/models/post.rb +184 -86
- data/test/models/price_estimate.rb +11 -1
- data/test/models/professor.rb +3 -1
- data/test/models/project.rb +14 -12
- data/test/models/publisher/article.rb +2 -0
- data/test/models/publisher/magazine.rb +2 -0
- data/test/models/publisher.rb +2 -0
- data/test/models/randomly_named_c1.rb +2 -0
- data/test/models/rating.rb +5 -1
- data/test/models/reader.rb +7 -5
- data/test/models/recipe.rb +2 -0
- data/test/models/record.rb +2 -0
- data/test/models/reference.rb +6 -3
- data/test/models/reply.rb +39 -21
- data/test/models/room.rb +6 -0
- data/test/models/section.rb +6 -0
- data/test/models/seminar.rb +6 -0
- data/test/models/session.rb +6 -0
- data/test/models/ship.rb +12 -9
- data/test/models/ship_part.rb +5 -3
- data/test/models/shop.rb +4 -2
- data/test/models/shop_account.rb +2 -0
- data/test/models/speedometer.rb +2 -0
- data/test/models/sponsor.rb +8 -5
- data/test/models/squeak.rb +6 -0
- data/test/models/strict_zine.rb +7 -0
- data/test/models/string_key_object.rb +2 -0
- data/test/models/student.rb +2 -0
- data/test/models/subscriber.rb +4 -2
- data/test/models/subscription.rb +5 -1
- data/test/models/tag.rb +6 -3
- data/test/models/tagging.rb +13 -6
- data/test/models/task.rb +2 -0
- data/test/models/topic.rb +54 -19
- data/test/models/toy.rb +4 -0
- data/test/models/traffic_light.rb +2 -0
- data/test/models/treasure.rb +5 -3
- data/test/models/treaty.rb +2 -4
- data/test/models/tree.rb +2 -0
- data/test/models/tuning_peg.rb +2 -0
- data/test/models/tyre.rb +2 -0
- data/test/models/user.rb +12 -4
- data/test/models/uuid_child.rb +2 -0
- data/test/models/uuid_item.rb +2 -0
- data/test/models/uuid_parent.rb +2 -0
- data/test/models/vegetables.rb +12 -3
- data/test/models/vertex.rb +6 -4
- data/test/models/warehouse_thing.rb +2 -0
- data/test/models/wheel.rb +3 -1
- data/test/models/without_table.rb +3 -1
- data/test/models/zine.rb +3 -1
- data/test/schema/mysql2_specific_schema.rb +49 -35
- data/test/schema/oracle_specific_schema.rb +13 -15
- data/test/schema/postgresql_specific_schema.rb +51 -40
- data/test/schema/schema.rb +334 -154
- data/test/schema/sqlite_specific_schema.rb +9 -16
- data/test/support/config.rb +26 -26
- data/test/support/connection.rb +14 -8
- data/test/support/connection_helper.rb +3 -1
- data/test/support/ddl_helper.rb +2 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
- data/test/support/schema_dumping_helper.rb +2 -0
- data/test/support/stubs/strong_parameters.rb +40 -0
- data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
- data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
- metadata +190 -14
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cases/helper"
|
2
4
|
require "rack"
|
3
5
|
|
@@ -14,7 +16,7 @@ module ActiveRecord
|
|
14
16
|
|
15
17
|
def call(env)
|
16
18
|
@calls << env
|
17
|
-
[200, {}, [
|
19
|
+
[200, {}, ["hi mom"]]
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -25,7 +27,7 @@ module ActiveRecord
|
|
25
27
|
|
26
28
|
# make sure we have an active connection
|
27
29
|
assert ActiveRecord::Base.connection
|
28
|
-
|
30
|
+
assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
29
31
|
end
|
30
32
|
|
31
33
|
def test_app_delegation
|
@@ -39,20 +41,20 @@ module ActiveRecord
|
|
39
41
|
_, _, body = @management.call(@env)
|
40
42
|
bits = []
|
41
43
|
body.each { |bit| bits << bit }
|
42
|
-
assert_equal [
|
44
|
+
assert_equal ["hi mom"], bits
|
43
45
|
end
|
44
46
|
|
45
47
|
def test_connections_are_cleared_after_body_close
|
46
48
|
_, _, body = @management.call(@env)
|
47
49
|
body.close
|
48
|
-
|
50
|
+
assert_not_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
49
51
|
end
|
50
52
|
|
51
53
|
def test_active_connections_are_not_cleared_on_body_close_during_transaction
|
52
54
|
ActiveRecord::Base.transaction do
|
53
55
|
_, _, body = @management.call(@env)
|
54
56
|
body.close
|
55
|
-
|
57
|
+
assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
@@ -60,7 +62,7 @@ module ActiveRecord
|
|
60
62
|
app = Class.new(App) { def call(env); raise NotImplementedError; end }.new
|
61
63
|
explosive = middleware(app)
|
62
64
|
assert_raises(NotImplementedError) { explosive.call(@env) }
|
63
|
-
|
65
|
+
assert_not_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
64
66
|
end
|
65
67
|
|
66
68
|
def test_connections_not_closed_if_exception_inside_transaction
|
@@ -68,14 +70,14 @@ module ActiveRecord
|
|
68
70
|
app = Class.new(App) { def call(env); raise RuntimeError; end }.new
|
69
71
|
explosive = middleware(app)
|
70
72
|
assert_raises(RuntimeError) { explosive.call(@env) }
|
71
|
-
|
73
|
+
assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
77
|
test "doesn't clear active connections when running in a test case" do
|
76
78
|
executor.wrap do
|
77
79
|
@management.call(@env)
|
78
|
-
|
80
|
+
assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
@@ -83,15 +85,15 @@ module ActiveRecord
|
|
83
85
|
body = Class.new(String) { def to_path; "/path"; end }.new
|
84
86
|
app = lambda { |_| [200, {}, body] }
|
85
87
|
response_body = middleware(app).call(@env)[2]
|
86
|
-
|
88
|
+
assert_respond_to response_body, :to_path
|
87
89
|
assert_equal "/path", response_body.to_path
|
88
90
|
end
|
89
91
|
|
90
92
|
test "doesn't mutate the original response" do
|
91
|
-
original_response = [200, {},
|
93
|
+
original_response = [200, {}, "hi"]
|
92
94
|
app = lambda { |_| original_response }
|
93
95
|
middleware(app).call(@env)[2]
|
94
|
-
assert_equal
|
96
|
+
assert_equal "hi", original_response.last
|
95
97
|
end
|
96
98
|
|
97
99
|
private
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cases/helper"
|
2
|
-
require
|
4
|
+
require "concurrent/atomic/count_down_latch"
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
module ConnectionAdapters
|
@@ -10,7 +12,9 @@ module ActiveRecord
|
|
10
12
|
super
|
11
13
|
|
12
14
|
# Keep a duplicate pool so we do not bother others
|
13
|
-
@
|
15
|
+
@db_config = ActiveRecord::Base.connection_pool.db_config
|
16
|
+
@pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new(ActiveRecord::Base, @db_config)
|
17
|
+
@pool = ConnectionPool.new(@pool_config)
|
14
18
|
|
15
19
|
if in_memory_db?
|
16
20
|
# Separate connections to an in-memory database create an entirely new database,
|
@@ -33,12 +37,12 @@ module ActiveRecord
|
|
33
37
|
|
34
38
|
def test_checkout_after_close
|
35
39
|
connection = pool.connection
|
36
|
-
|
40
|
+
assert_predicate connection, :in_use?
|
37
41
|
|
38
42
|
connection.close
|
39
|
-
|
43
|
+
assert_not_predicate connection, :in_use?
|
40
44
|
|
41
|
-
|
45
|
+
assert_predicate pool.connection, :in_use?
|
42
46
|
end
|
43
47
|
|
44
48
|
def test_released_connection_moves_between_threads
|
@@ -78,18 +82,20 @@ module ActiveRecord
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def test_active_connection_in_use
|
81
|
-
|
85
|
+
assert_not_predicate pool, :active_connection?
|
82
86
|
main_thread = pool.connection
|
83
87
|
|
84
|
-
|
88
|
+
assert_predicate pool, :active_connection?
|
85
89
|
|
86
90
|
main_thread.close
|
87
91
|
|
88
|
-
|
92
|
+
assert_not_predicate pool, :active_connection?
|
89
93
|
end
|
90
94
|
|
91
95
|
def test_full_pool_exception
|
92
|
-
@pool.
|
96
|
+
@pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
|
97
|
+
@pool.size.times { assert @pool.checkout }
|
98
|
+
|
93
99
|
assert_raises(ConnectionTimeoutError) do
|
94
100
|
@pool.checkout
|
95
101
|
end
|
@@ -107,6 +113,44 @@ module ActiveRecord
|
|
107
113
|
assert_equal connection, t.join.value
|
108
114
|
end
|
109
115
|
|
116
|
+
def test_full_pool_blocking_shares_load_interlock
|
117
|
+
@pool.instance_variable_set(:@size, 1)
|
118
|
+
|
119
|
+
load_interlock_latch = Concurrent::CountDownLatch.new
|
120
|
+
connection_latch = Concurrent::CountDownLatch.new
|
121
|
+
|
122
|
+
able_to_get_connection = false
|
123
|
+
able_to_load = false
|
124
|
+
|
125
|
+
thread_with_load_interlock = Thread.new do
|
126
|
+
ActiveSupport::Dependencies.interlock.running do
|
127
|
+
load_interlock_latch.count_down
|
128
|
+
connection_latch.wait
|
129
|
+
|
130
|
+
@pool.with_connection do
|
131
|
+
able_to_get_connection = true
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
thread_with_last_connection = Thread.new do
|
137
|
+
@pool.with_connection do
|
138
|
+
connection_latch.count_down
|
139
|
+
load_interlock_latch.wait
|
140
|
+
|
141
|
+
ActiveSupport::Dependencies.interlock.loading do
|
142
|
+
able_to_load = true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
thread_with_load_interlock.join
|
148
|
+
thread_with_last_connection.join
|
149
|
+
|
150
|
+
assert able_to_get_connection
|
151
|
+
assert able_to_load
|
152
|
+
end
|
153
|
+
|
110
154
|
def test_removing_releases_latch
|
111
155
|
cs = @pool.size.times.map { @pool.checkout }
|
112
156
|
t = Thread.new { @pool.checkout }
|
@@ -154,13 +198,108 @@ module ActiveRecord
|
|
154
198
|
@pool.connections.each { |conn| conn.close if conn.in_use? }
|
155
199
|
end
|
156
200
|
|
201
|
+
def test_idle_timeout_configuration
|
202
|
+
@pool.disconnect!
|
203
|
+
|
204
|
+
config = @db_config.configuration_hash.merge(idle_timeout: "0.02")
|
205
|
+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(@db_config.env_name, @db_config.name, config)
|
206
|
+
|
207
|
+
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new(ActiveRecord::Base, db_config)
|
208
|
+
@pool = ConnectionPool.new(pool_config)
|
209
|
+
idle_conn = @pool.checkout
|
210
|
+
@pool.checkin(idle_conn)
|
211
|
+
|
212
|
+
idle_conn.instance_variable_set(
|
213
|
+
:@idle_since,
|
214
|
+
Concurrent.monotonic_time - 0.01
|
215
|
+
)
|
216
|
+
|
217
|
+
@pool.flush
|
218
|
+
assert_equal 1, @pool.connections.length
|
219
|
+
|
220
|
+
idle_conn.instance_variable_set(
|
221
|
+
:@idle_since,
|
222
|
+
Concurrent.monotonic_time - 0.02
|
223
|
+
)
|
224
|
+
|
225
|
+
@pool.flush
|
226
|
+
assert_equal 0, @pool.connections.length
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_disable_flush
|
230
|
+
@pool.disconnect!
|
231
|
+
|
232
|
+
config = @db_config.configuration_hash.merge(idle_timeout: -5)
|
233
|
+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(@db_config.env_name, @db_config.name, config)
|
234
|
+
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new(ActiveRecord::Base, db_config)
|
235
|
+
@pool = ConnectionPool.new(pool_config)
|
236
|
+
idle_conn = @pool.checkout
|
237
|
+
@pool.checkin(idle_conn)
|
238
|
+
|
239
|
+
idle_conn.instance_variable_set(
|
240
|
+
:@idle_since,
|
241
|
+
Concurrent.monotonic_time - 1
|
242
|
+
)
|
243
|
+
|
244
|
+
@pool.flush
|
245
|
+
assert_equal 1, @pool.connections.length
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_flush
|
249
|
+
idle_conn = @pool.checkout
|
250
|
+
recent_conn = @pool.checkout
|
251
|
+
active_conn = @pool.checkout
|
252
|
+
|
253
|
+
@pool.checkin idle_conn
|
254
|
+
@pool.checkin recent_conn
|
255
|
+
|
256
|
+
assert_equal 3, @pool.connections.length
|
257
|
+
|
258
|
+
idle_conn.instance_variable_set(
|
259
|
+
:@idle_since,
|
260
|
+
Concurrent.monotonic_time - 1000
|
261
|
+
)
|
262
|
+
|
263
|
+
@pool.flush(30)
|
264
|
+
|
265
|
+
assert_equal 2, @pool.connections.length
|
266
|
+
|
267
|
+
assert_equal [recent_conn, active_conn].sort_by(&:__id__), @pool.connections.sort_by(&:__id__)
|
268
|
+
ensure
|
269
|
+
@pool.checkin active_conn
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_flush_bang
|
273
|
+
idle_conn = @pool.checkout
|
274
|
+
recent_conn = @pool.checkout
|
275
|
+
active_conn = @pool.checkout
|
276
|
+
_dead_conn = Thread.new { @pool.checkout }.join
|
277
|
+
|
278
|
+
@pool.checkin idle_conn
|
279
|
+
@pool.checkin recent_conn
|
280
|
+
|
281
|
+
assert_equal 4, @pool.connections.length
|
282
|
+
|
283
|
+
def idle_conn.seconds_idle
|
284
|
+
1000
|
285
|
+
end
|
286
|
+
|
287
|
+
@pool.flush!
|
288
|
+
|
289
|
+
assert_equal 1, @pool.connections.length
|
290
|
+
|
291
|
+
assert_equal [active_conn].sort_by(&:__id__), @pool.connections.sort_by(&:__id__)
|
292
|
+
ensure
|
293
|
+
@pool.checkin active_conn
|
294
|
+
end
|
295
|
+
|
157
296
|
def test_remove_connection
|
158
297
|
conn = @pool.checkout
|
159
|
-
|
298
|
+
assert_predicate conn, :in_use?
|
160
299
|
|
161
300
|
length = @pool.connections.length
|
162
301
|
@pool.remove conn
|
163
|
-
|
302
|
+
assert_predicate conn, :in_use?
|
164
303
|
assert_equal(length - 1, @pool.connections.length)
|
165
304
|
ensure
|
166
305
|
conn.close
|
@@ -175,15 +314,15 @@ module ActiveRecord
|
|
175
314
|
end
|
176
315
|
|
177
316
|
def test_active_connection?
|
178
|
-
|
317
|
+
assert_not_predicate @pool, :active_connection?
|
179
318
|
assert @pool.connection
|
180
|
-
|
319
|
+
assert_predicate @pool, :active_connection?
|
181
320
|
@pool.release_connection
|
182
|
-
|
321
|
+
assert_not_predicate @pool, :active_connection?
|
183
322
|
end
|
184
323
|
|
185
324
|
def test_checkout_behaviour
|
186
|
-
pool = ConnectionPool.new
|
325
|
+
pool = ConnectionPool.new(@pool_config)
|
187
326
|
main_connection = pool.connection
|
188
327
|
assert_not_nil main_connection
|
189
328
|
threads = []
|
@@ -203,6 +342,14 @@ module ActiveRecord
|
|
203
342
|
end.join
|
204
343
|
end
|
205
344
|
|
345
|
+
def test_checkout_order_is_lifo
|
346
|
+
conn1 = @pool.checkout
|
347
|
+
conn2 = @pool.checkout
|
348
|
+
@pool.checkin conn1
|
349
|
+
@pool.checkin conn2
|
350
|
+
assert_equal [conn2, conn1], 2.times.map { @pool.checkout }
|
351
|
+
end
|
352
|
+
|
206
353
|
# The connection pool is "fair" if threads waiting for
|
207
354
|
# connections receive them in the order in which they began
|
208
355
|
# waiting. This ensures that we don't timeout one HTTP request
|
@@ -307,14 +454,17 @@ module ActiveRecord
|
|
307
454
|
end
|
308
455
|
end
|
309
456
|
|
310
|
-
def
|
311
|
-
pool = ConnectionPool.new
|
457
|
+
def test_automatic_reconnect_restores_after_disconnect
|
458
|
+
pool = ConnectionPool.new(@pool_config)
|
312
459
|
assert pool.automatic_reconnect
|
313
460
|
assert pool.connection
|
314
461
|
|
315
462
|
pool.disconnect!
|
316
463
|
assert pool.connection
|
464
|
+
end
|
317
465
|
|
466
|
+
def test_automatic_reconnect_can_be_disabled
|
467
|
+
pool = ConnectionPool.new(@pool_config)
|
318
468
|
pool.disconnect!
|
319
469
|
pool.automatic_reconnect = false
|
320
470
|
|
@@ -341,6 +491,38 @@ module ActiveRecord
|
|
341
491
|
end
|
342
492
|
end
|
343
493
|
|
494
|
+
class ConnectionTestModel < ActiveRecord::Base
|
495
|
+
self.abstract_class = true
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_connection_notification_is_called
|
499
|
+
payloads = []
|
500
|
+
subscription = ActiveSupport::Notifications.subscribe("!connection.active_record") do |name, started, finished, unique_id, payload|
|
501
|
+
payloads << payload
|
502
|
+
end
|
503
|
+
ConnectionTestModel.establish_connection :arunit
|
504
|
+
|
505
|
+
assert_equal [:config, :shard, :spec_name], payloads[0].keys.sort
|
506
|
+
assert_equal "ActiveRecord::ConnectionAdapters::ConnectionPoolTest::ConnectionTestModel", payloads[0][:spec_name]
|
507
|
+
assert_equal ActiveRecord::Base.default_shard, payloads[0][:shard]
|
508
|
+
ensure
|
509
|
+
ActiveSupport::Notifications.unsubscribe(subscription) if subscription
|
510
|
+
end
|
511
|
+
|
512
|
+
def test_connection_notification_is_called_for_shard
|
513
|
+
payloads = []
|
514
|
+
subscription = ActiveSupport::Notifications.subscribe("!connection.active_record") do |name, started, finished, unique_id, payload|
|
515
|
+
payloads << payload
|
516
|
+
end
|
517
|
+
ConnectionTestModel.connects_to shards: { shard_two: { writing: :arunit } }
|
518
|
+
|
519
|
+
assert_equal [:config, :shard, :spec_name], payloads[0].keys.sort
|
520
|
+
assert_equal "ActiveRecord::ConnectionAdapters::ConnectionPoolTest::ConnectionTestModel", payloads[0][:spec_name]
|
521
|
+
assert_equal :shard_two, payloads[0][:shard]
|
522
|
+
ensure
|
523
|
+
ActiveSupport::Notifications.unsubscribe(subscription) if subscription
|
524
|
+
end
|
525
|
+
|
344
526
|
def test_pool_sets_connection_schema_cache
|
345
527
|
connection = pool.checkout
|
346
528
|
schema_cache = SchemaCache.new connection
|
@@ -348,7 +530,6 @@ module ActiveRecord
|
|
348
530
|
pool.schema_cache = schema_cache
|
349
531
|
|
350
532
|
pool.with_connection do |conn|
|
351
|
-
assert_not_same pool.schema_cache, conn.schema_cache
|
352
533
|
assert_equal pool.schema_cache.size, conn.schema_cache.size
|
353
534
|
assert_same pool.schema_cache.columns(:posts), conn.schema_cache.columns(:posts)
|
354
535
|
end
|
@@ -383,8 +564,8 @@ module ActiveRecord
|
|
383
564
|
all_threads_in_new_connection.wait
|
384
565
|
end
|
385
566
|
rescue Timeout::Error
|
386
|
-
flunk
|
387
|
-
|
567
|
+
flunk "pool unable to establish connections concurrently or implementation has " \
|
568
|
+
"changed, this test then needs to patch a different :new_connection method"
|
388
569
|
ensure
|
389
570
|
# clean up the threads
|
390
571
|
all_go.count_down
|
@@ -393,45 +574,46 @@ module ActiveRecord
|
|
393
574
|
end
|
394
575
|
|
395
576
|
def test_non_bang_disconnect_and_clear_reloadable_connections_throw_exception_if_threads_dont_return_their_conns
|
577
|
+
Thread.report_on_exception, original_report_on_exception = false, Thread.report_on_exception
|
396
578
|
@pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
|
397
579
|
[:disconnect, :clear_reloadable_connections].each do |group_action_method|
|
398
580
|
@pool.with_connection do |connection|
|
399
581
|
assert_raises(ExclusiveConnectionTimeoutError) do
|
400
|
-
Thread.new { @pool.
|
582
|
+
Thread.new { @pool.public_send(group_action_method) }.join
|
401
583
|
end
|
402
584
|
end
|
403
585
|
end
|
586
|
+
ensure
|
587
|
+
Thread.report_on_exception = original_report_on_exception
|
404
588
|
end
|
405
589
|
|
406
590
|
def test_disconnect_and_clear_reloadable_connections_attempt_to_wait_for_threads_to_return_their_conns
|
407
591
|
[:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method|
|
408
|
-
|
409
|
-
|
410
|
-
@pool.
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
assert @pool.active_connection?
|
421
|
-
end
|
422
|
-
ensure
|
423
|
-
thread.join if thread && !timed_join_result # clean up the other thread
|
592
|
+
thread = timed_join_result = nil
|
593
|
+
@pool.with_connection do |connection|
|
594
|
+
thread = Thread.new { @pool.send(group_action_method) }
|
595
|
+
|
596
|
+
# give the other `thread` some time to get stuck in `group_action_method`
|
597
|
+
timed_join_result = thread.join(0.3)
|
598
|
+
# thread.join # => `nil` means the other thread hasn't finished running and is still waiting for us to
|
599
|
+
# release our connection
|
600
|
+
assert_nil timed_join_result
|
601
|
+
|
602
|
+
# assert that since this is within default timeout our connection hasn't been forcefully taken away from us
|
603
|
+
assert_predicate @pool, :active_connection?
|
424
604
|
end
|
605
|
+
ensure
|
606
|
+
thread.join if thread && !timed_join_result # clean up the other thread
|
425
607
|
end
|
426
608
|
end
|
427
609
|
|
428
|
-
def
|
610
|
+
def test_bang_versions_of_disconnect_and_clear_reloadable_connections_if_unable_to_acquire_all_connections_proceed_anyway
|
429
611
|
@pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
|
430
612
|
[:disconnect!, :clear_reloadable_connections!].each do |group_action_method|
|
431
613
|
@pool.with_connection do |connection|
|
432
614
|
Thread.new { @pool.send(group_action_method) }.join
|
433
615
|
# assert connection has been forcefully taken away from us
|
434
|
-
|
616
|
+
assert_not_predicate @pool, :active_connection?
|
435
617
|
|
436
618
|
# make a new connection for with_connection to clean up
|
437
619
|
@pool.connection
|
@@ -443,43 +625,50 @@ module ActiveRecord
|
|
443
625
|
with_single_connection_pool do |pool|
|
444
626
|
[:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method|
|
445
627
|
conn = pool.connection # drain the only available connection
|
446
|
-
second_thread_done = Concurrent::
|
447
|
-
|
448
|
-
# create a first_thread and let it get into the FIFO queue first
|
449
|
-
first_thread = Thread.new do
|
450
|
-
pool.with_connection { second_thread_done.wait }
|
451
|
-
end
|
452
|
-
|
453
|
-
# wait for first_thread to get in queue
|
454
|
-
Thread.pass until pool.num_waiting_in_queue == 1
|
628
|
+
second_thread_done = Concurrent::Event.new
|
455
629
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
630
|
+
begin
|
631
|
+
# create a first_thread and let it get into the FIFO queue first
|
632
|
+
first_thread = Thread.new do
|
633
|
+
pool.with_connection { second_thread_done.wait }
|
634
|
+
end
|
635
|
+
|
636
|
+
# wait for first_thread to get in queue
|
637
|
+
Thread.pass until pool.num_waiting_in_queue == 1
|
638
|
+
|
639
|
+
# create a different, later thread, that will attempt to do a "group action",
|
640
|
+
# but because of the group action semantics it should be able to preempt the
|
641
|
+
# first_thread when a connection is made available
|
642
|
+
second_thread = Thread.new do
|
643
|
+
pool.send(group_action_method)
|
644
|
+
second_thread_done.set
|
645
|
+
end
|
646
|
+
|
647
|
+
# wait for second_thread to get in queue
|
648
|
+
Thread.pass until pool.num_waiting_in_queue == 2
|
649
|
+
|
650
|
+
# return the only available connection
|
651
|
+
pool.checkin(conn)
|
652
|
+
|
653
|
+
# if the second_thread is not able to preempt the first_thread,
|
654
|
+
# they will temporarily (until either of them timeouts with ConnectionTimeoutError)
|
655
|
+
# deadlock and a join(2) timeout will be reached
|
656
|
+
assert second_thread.join(2), "#{group_action_method} is not able to preempt other waiting threads"
|
657
|
+
|
658
|
+
ensure
|
659
|
+
# post test clean up
|
660
|
+
failed = !second_thread_done.set?
|
661
|
+
|
662
|
+
if failed
|
663
|
+
second_thread_done.set
|
664
|
+
|
665
|
+
first_thread.join(2)
|
666
|
+
second_thread.join(2)
|
667
|
+
end
|
668
|
+
|
669
|
+
first_thread.join(10) || raise("first_thread got stuck")
|
670
|
+
second_thread.join(10) || raise("second_thread got stuck")
|
462
671
|
end
|
463
|
-
|
464
|
-
# wait for second_thread to get in queue
|
465
|
-
Thread.pass until pool.num_waiting_in_queue == 2
|
466
|
-
|
467
|
-
# return the only available connection
|
468
|
-
pool.checkin(conn)
|
469
|
-
|
470
|
-
# if the second_thread is not able to preempt the first_thread,
|
471
|
-
# they will temporarily (until either of them timeouts with ConnectionTimeoutError)
|
472
|
-
# deadlock and a join(2) timeout will be reached
|
473
|
-
failed = true unless second_thread.join(2)
|
474
|
-
|
475
|
-
#--- post test clean up start
|
476
|
-
second_thread_done.count_down if failed
|
477
|
-
|
478
|
-
first_thread.join
|
479
|
-
second_thread.join
|
480
|
-
#--- post test clean up end
|
481
|
-
|
482
|
-
flunk "#{group_action_method} is not able to preempt other waiting threads" if failed
|
483
672
|
end
|
484
673
|
end
|
485
674
|
end
|
@@ -492,7 +681,7 @@ module ActiveRecord
|
|
492
681
|
end
|
493
682
|
|
494
683
|
stuck_thread = Thread.new do
|
495
|
-
pool.with_connection {}
|
684
|
+
pool.with_connection { }
|
496
685
|
end
|
497
686
|
|
498
687
|
# wait for stuck_thread to get in queue
|
@@ -501,21 +690,65 @@ module ActiveRecord
|
|
501
690
|
pool.clear_reloadable_connections
|
502
691
|
|
503
692
|
unless stuck_thread.join(2)
|
504
|
-
flunk
|
693
|
+
flunk "clear_reloadable_connections must not let other connection waiting threads get stuck in queue"
|
505
694
|
end
|
506
695
|
|
507
696
|
assert_equal 0, pool.num_waiting_in_queue
|
508
697
|
end
|
509
698
|
end
|
510
699
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
700
|
+
def test_connection_pool_stat
|
701
|
+
with_single_connection_pool do |pool|
|
702
|
+
pool.with_connection do |connection|
|
703
|
+
stats = pool.stat
|
704
|
+
assert_equal({ size: 1, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }, stats)
|
705
|
+
end
|
706
|
+
|
707
|
+
stats = pool.stat
|
708
|
+
assert_equal({ size: 1, connections: 1, busy: 0, dead: 0, idle: 1, waiting: 0, checkout_timeout: 5 }, stats)
|
709
|
+
|
710
|
+
Thread.new do
|
711
|
+
pool.checkout
|
712
|
+
Thread.current.kill
|
713
|
+
end.join
|
714
|
+
|
715
|
+
stats = pool.stat
|
716
|
+
assert_equal({ size: 1, connections: 1, busy: 0, dead: 1, idle: 0, waiting: 0, checkout_timeout: 5 }, stats)
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
def test_public_connections_access_threadsafe
|
721
|
+
_conn1 = @pool.checkout
|
722
|
+
conn2 = @pool.checkout
|
723
|
+
|
724
|
+
connections = @pool.connections
|
725
|
+
found_conn = nil
|
726
|
+
|
727
|
+
# Without assuming too much about implementation
|
728
|
+
# details make sure that a concurrent change to
|
729
|
+
# the pool is thread-safe.
|
730
|
+
connections.each_index do |idx|
|
731
|
+
if connections[idx] == conn2
|
732
|
+
Thread.new do
|
733
|
+
@pool.remove(conn2)
|
734
|
+
end.join
|
735
|
+
end
|
736
|
+
found_conn = connections[idx]
|
737
|
+
end
|
738
|
+
|
739
|
+
assert_not_nil found_conn
|
518
740
|
end
|
741
|
+
|
742
|
+
private
|
743
|
+
def with_single_connection_pool
|
744
|
+
config = @db_config.configuration_hash.merge(pool: 1)
|
745
|
+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new("arunit", "primary", config)
|
746
|
+
pool_config = ActiveRecord::ConnectionAdapters::PoolConfig.new(ActiveRecord::Base, db_config)
|
747
|
+
|
748
|
+
yield(pool = ConnectionPool.new(pool_config))
|
749
|
+
ensure
|
750
|
+
pool.disconnect! if pool
|
751
|
+
end
|
519
752
|
end
|
520
753
|
end
|
521
754
|
end
|