ibm_db 5.6.1-arm64-darwin-24
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 +7 -0
- data/CHANGES +299 -0
- data/LICENSE +55 -0
- data/MANIFEST +14 -0
- data/ParameterizedQueries README +39 -0
- data/README +210 -0
- data/ext/Makefile +270 -0
- data/ext/Makefile.nt32 +181 -0
- data/ext/Makefile.nt32.191 +212 -0
- data/ext/extconf.rb +320 -0
- data/ext/gil_release_version.h +3 -0
- data/ext/ibm_db.bundle +0 -0
- data/ext/ibm_db.c +11865 -0
- data/ext/ibm_db.o +0 -0
- data/ext/mkmf.log +98 -0
- data/ext/ruby_ibm_db.h +241 -0
- data/ext/ruby_ibm_db_cli.c +867 -0
- data/ext/ruby_ibm_db_cli.h +508 -0
- data/ext/ruby_ibm_db_cli.o +0 -0
- data/ext/unicode_support_version.h +3 -0
- data/init.rb +42 -0
- data/lib/IBM_DB.rb +27 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4407 -0
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -0
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
- data/lib/ibm_db.bundle +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +52 -0
- 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/example.log +1 -0
- data/test/assets/flowers.jpg +0 -0
- data/test/assets/schema_dump_5_1.yml +345 -0
- data/test/assets/test.txt +1 -0
- data/test/cases/adapter_prevent_writes_test.rb +334 -0
- data/test/cases/adapter_test.rb +565 -0
- data/test/cases/adapters/mysql2/active_schema_test.rb +203 -0
- data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +52 -0
- data/test/cases/adapters/mysql2/boolean_test.rb +102 -0
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +65 -0
- data/test/cases/adapters/mysql2/charset_collation_test.rb +57 -0
- data/test/cases/adapters/mysql2/connection_test.rb +208 -0
- data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +49 -0
- data/test/cases/adapters/mysql2/enum_test.rb +47 -0
- data/test/cases/adapters/mysql2/explain_test.rb +23 -0
- data/test/cases/adapters/mysql2/json_test.rb +24 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +238 -0
- 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/reserved_word_test.rb +152 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +64 -0
- data/test/cases/adapters/mysql2/schema_test.rb +128 -0
- data/test/cases/adapters/mysql2/set_test.rb +32 -0
- data/test/cases/adapters/mysql2/sp_test.rb +38 -0
- data/test/cases/adapters/mysql2/sql_types_test.rb +16 -0
- data/test/cases/adapters/mysql2/table_options_test.rb +125 -0
- data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +68 -0
- data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +113 -0
- data/test/cases/adapters/postgresql/array_test.rb +394 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +84 -0
- data/test/cases/adapters/postgresql/bytea_test.rb +135 -0
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +27 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +40 -0
- data/test/cases/adapters/postgresql/cidr_test.rb +27 -0
- data/test/cases/adapters/postgresql/citext_test.rb +78 -0
- data/test/cases/adapters/postgresql/collation_test.rb +55 -0
- data/test/cases/adapters/postgresql/composite_test.rb +134 -0
- data/test/cases/adapters/postgresql/connection_test.rb +245 -0
- data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +89 -0
- data/test/cases/adapters/postgresql/date_test.rb +42 -0
- data/test/cases/adapters/postgresql/domain_test.rb +49 -0
- data/test/cases/adapters/postgresql/enum_test.rb +93 -0
- data/test/cases/adapters/postgresql/explain_test.rb +22 -0
- data/test/cases/adapters/postgresql/extension_migration_test.rb +64 -0
- data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +46 -0
- data/test/cases/adapters/postgresql/geometric_test.rb +372 -0
- data/test/cases/adapters/postgresql/hstore_test.rb +390 -0
- data/test/cases/adapters/postgresql/infinity_test.rb +108 -0
- data/test/cases/adapters/postgresql/integer_test.rb +27 -0
- data/test/cases/adapters/postgresql/interval_test.rb +99 -0
- data/test/cases/adapters/postgresql/json_test.rb +52 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +51 -0
- data/test/cases/adapters/postgresql/money_test.rb +127 -0
- data/test/cases/adapters/postgresql/network_test.rb +102 -0
- data/test/cases/adapters/postgresql/numbers_test.rb +51 -0
- 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 +447 -0
- data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
- data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +50 -0
- data/test/cases/adapters/postgresql/range_test.rb +457 -0
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +112 -0
- data/test/cases/adapters/postgresql/rename_table_test.rb +35 -0
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +110 -0
- data/test/cases/adapters/postgresql/schema_test.rb +713 -0
- data/test/cases/adapters/postgresql/serial_test.rb +156 -0
- data/test/cases/adapters/postgresql/statement_pool_test.rb +61 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +92 -0
- 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 +35 -0
- data/test/cases/adapters/postgresql/utils_test.rb +64 -0
- data/test/cases/adapters/postgresql/uuid_test.rb +411 -0
- data/test/cases/adapters/postgresql/xml_test.rb +50 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +64 -0
- data/test/cases/adapters/sqlite3/copy_table_test.rb +101 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +23 -0
- data/test/cases/adapters/sqlite3/json_test.rb +29 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +79 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +628 -0
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +21 -0
- data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
- data/test/cases/aggregations_test.rb +170 -0
- data/test/cases/annotate_test.rb +46 -0
- data/test/cases/ar_schema_test.rb +213 -0
- 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/association_scope_test.rb +16 -0
- data/test/cases/associations/belongs_to_associations_test.rb +1493 -0
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +43 -0
- data/test/cases/associations/callbacks_test.rb +208 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +245 -0
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +156 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +127 -0
- data/test/cases/associations/eager_singularization_test.rb +148 -0
- data/test/cases/associations/eager_test.rb +1658 -0
- data/test/cases/associations/extension_test.rb +93 -0
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1025 -0
- data/test/cases/associations/has_many_associations_test.rb +3074 -0
- data/test/cases/associations/has_many_through_associations_test.rb +1580 -0
- data/test/cases/associations/has_one_associations_test.rb +872 -0
- data/test/cases/associations/has_one_through_associations_test.rb +429 -0
- data/test/cases/associations/inner_join_association_test.rb +215 -0
- data/test/cases/associations/inverse_associations_test.rb +941 -0
- data/test/cases/associations/join_model_test.rb +787 -0
- data/test/cases/associations/left_outer_join_association_test.rb +123 -0
- data/test/cases/associations/nested_through_associations_test.rb +636 -0
- data/test/cases/associations/required_test.rb +127 -0
- data/test/cases/associations_test.rb +516 -0
- data/test/cases/attribute_decorators_test.rb +126 -0
- data/test/cases/attribute_methods/read_test.rb +60 -0
- data/test/cases/attribute_methods_test.rb +1124 -0
- data/test/cases/attribute_set_test.rb +270 -0
- data/test/cases/attribute_test.rb +246 -0
- data/test/cases/attributes_test.rb +371 -0
- data/test/cases/autosave_association_test.rb +1953 -0
- data/test/cases/base_prevent_writes_test.rb +229 -0
- data/test/cases/base_test.rb +1770 -0
- data/test/cases/batches_test.rb +695 -0
- data/test/cases/binary_test.rb +39 -0
- data/test/cases/bind_parameter_test.rb +283 -0
- data/test/cases/boolean_test.rb +52 -0
- data/test/cases/cache_key_test.rb +131 -0
- data/test/cases/calculations_test.rb +1361 -0
- data/test/cases/callbacks_test.rb +503 -0
- data/test/cases/clone_test.rb +45 -0
- data/test/cases/coders/json_test.rb +17 -0
- data/test/cases/coders/yaml_column_test.rb +66 -0
- data/test/cases/collection_cache_key_test.rb +272 -0
- data/test/cases/column_alias_test.rb +19 -0
- data/test/cases/column_definition_test.rb +34 -0
- data/test/cases/comment_test.rb +204 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +60 -0
- data/test/cases/connection_adapters/connection_handler_test.rb +467 -0
- 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_specification_test.rb +12 -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 +436 -0
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +81 -0
- data/test/cases/connection_adapters/quoting_test.rb +13 -0
- data/test/cases/connection_adapters/schema_cache_test.rb +294 -0
- data/test/cases/connection_adapters/type_lookup_test.rb +119 -0
- data/test/cases/connection_management_test.rb +114 -0
- data/test/cases/connection_pool_test.rb +754 -0
- data/test/cases/connection_specification/resolver_test.rb +131 -0
- data/test/cases/core_test.rb +136 -0
- data/test/cases/counter_cache_test.rb +368 -0
- data/test/cases/custom_locking_test.rb +19 -0
- 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 +36 -0
- data/test/cases/date_test.rb +36 -0
- data/test/cases/date_time_precision_test.rb +129 -0
- data/test/cases/date_time_test.rb +76 -0
- data/test/cases/defaults_test.rb +254 -0
- data/test/cases/delegated_type_test.rb +57 -0
- data/test/cases/dirty_test.rb +959 -0
- data/test/cases/disconnected_test.rb +30 -0
- data/test/cases/dup_test.rb +184 -0
- data/test/cases/enum_test.rb +823 -0
- data/test/cases/errors_test.rb +16 -0
- data/test/cases/explain_subscriber_test.rb +66 -0
- data/test/cases/explain_test.rb +79 -0
- data/test/cases/filter_attributes_test.rb +153 -0
- data/test/cases/finder_respond_to_test.rb +60 -0
- data/test/cases/finder_test.rb +1676 -0
- data/test/cases/fixture_set/file_test.rb +152 -0
- data/test/cases/fixtures_test.rb +1645 -0
- data/test/cases/forbidden_attributes_protection_test.rb +130 -0
- data/test/cases/habtm_destroy_order_test.rb +61 -0
- data/test/cases/helper.rb +233 -0
- data/test/cases/hot_compatibility_test.rb +143 -0
- data/test/cases/i18n_test.rb +46 -0
- data/test/cases/inheritance_test.rb +671 -0
- data/test/cases/insert_all_test.rb +489 -0
- data/test/cases/instrumentation_test.rb +101 -0
- data/test/cases/integration_test.rb +243 -0
- data/test/cases/invalid_connection_test.rb +26 -0
- data/test/cases/invertible_migration_test.rb +527 -0
- data/test/cases/json_attribute_test.rb +35 -0
- data/test/cases/json_serialization_test.rb +310 -0
- data/test/cases/json_shared_test_cases.rb +290 -0
- data/test/cases/locking_test.rb +787 -0
- data/test/cases/log_subscriber_test.rb +267 -0
- data/test/cases/marshal_serialization_test.rb +39 -0
- data/test/cases/migration/change_schema_test.rb +504 -0
- data/test/cases/migration/change_table_test.rb +364 -0
- data/test/cases/migration/check_constraint_test.rb +162 -0
- data/test/cases/migration/column_attributes_test.rb +186 -0
- data/test/cases/migration/column_positioning_test.rb +68 -0
- data/test/cases/migration/columns_test.rb +326 -0
- data/test/cases/migration/command_recorder_test.rb +437 -0
- data/test/cases/migration/compatibility_test.rb +673 -0
- data/test/cases/migration/create_join_table_test.rb +167 -0
- data/test/cases/migration/foreign_key_test.rb +581 -0
- data/test/cases/migration/helper.rb +40 -0
- data/test/cases/migration/index_test.rb +267 -0
- data/test/cases/migration/logger_test.rb +39 -0
- data/test/cases/migration/pending_migrations_test.rb +106 -0
- data/test/cases/migration/references_foreign_key_test.rb +235 -0
- data/test/cases/migration/references_index_test.rb +120 -0
- data/test/cases/migration/references_statements_test.rb +137 -0
- data/test/cases/migration/rename_table_test.rb +116 -0
- data/test/cases/migration_test.rb +1525 -0
- data/test/cases/migrator_test.rb +527 -0
- data/test/cases/mixin_test.rb +64 -0
- data/test/cases/modules_test.rb +174 -0
- data/test/cases/multi_db_migrator_test.rb +223 -0
- data/test/cases/multiparameter_attributes_test.rb +399 -0
- data/test/cases/multiple_db_test.rb +116 -0
- data/test/cases/nested_attributes_test.rb +1119 -0
- data/test/cases/nested_attributes_with_callbacks_test.rb +146 -0
- data/test/cases/null_relation_test.rb +84 -0
- data/test/cases/numeric_data_test.rb +93 -0
- data/test/cases/persistence_test.rb +1093 -0
- data/test/cases/pooled_connections_test.rb +73 -0
- data/test/cases/prepared_statement_status_test.rb +48 -0
- data/test/cases/primary_keys_test.rb +482 -0
- data/test/cases/query_cache_test.rb +915 -0
- data/test/cases/quoting_test.rb +303 -0
- data/test/cases/readonly_test.rb +120 -0
- data/test/cases/reaper_test.rb +199 -0
- data/test/cases/reflection_test.rb +520 -0
- data/test/cases/relation/delegation_test.rb +76 -0
- data/test/cases/relation/delete_all_test.rb +117 -0
- data/test/cases/relation/merging_test.rb +434 -0
- data/test/cases/relation/mutation_test.rb +145 -0
- data/test/cases/relation/or_test.rb +192 -0
- data/test/cases/relation/predicate_builder_test.rb +31 -0
- data/test/cases/relation/record_fetch_warning_test.rb +42 -0
- 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 +141 -0
- data/test/cases/relation/where_clause_test.rb +257 -0
- data/test/cases/relation/where_test.rb +429 -0
- data/test/cases/relation_test.rb +482 -0
- data/test/cases/relations_test.rb +2251 -0
- data/test/cases/reload_models_test.rb +26 -0
- data/test/cases/reserved_word_test.rb +141 -0
- data/test/cases/result_test.rb +141 -0
- data/test/cases/sanitize_test.rb +192 -0
- data/test/cases/schema_dumper_test.rb +550 -0
- data/test/cases/schema_loading_test.rb +53 -0
- data/test/cases/scoping/default_scoping_test.rb +569 -0
- data/test/cases/scoping/named_scoping_test.rb +649 -0
- data/test/cases/scoping/relation_scoping_test.rb +522 -0
- data/test/cases/secure_token_test.rb +47 -0
- data/test/cases/serialization_test.rb +106 -0
- data/test/cases/serialized_attribute_test.rb +455 -0
- data/test/cases/signed_id_test.rb +168 -0
- data/test/cases/statement_cache_test.rb +153 -0
- data/test/cases/statement_invalid_test.rb +42 -0
- data/test/cases/store_test.rb +320 -0
- data/test/cases/strict_loading_test.rb +473 -0
- data/test/cases/suppressor_test.rb +77 -0
- data/test/cases/tasks/database_tasks_test.rb +1526 -0
- data/test/cases/tasks/mysql_rake_test.rb +417 -0
- data/test/cases/tasks/postgresql_rake_test.rb +534 -0
- data/test/cases/tasks/sqlite_rake_test.rb +267 -0
- data/test/cases/test_case.rb +142 -0
- data/test/cases/test_databases_test.rb +79 -0
- data/test/cases/test_fixtures_test.rb +96 -0
- data/test/cases/time_precision_test.rb +125 -0
- data/test/cases/timestamp_test.rb +504 -0
- data/test/cases/touch_later_test.rb +123 -0
- data/test/cases/transaction_callbacks_test.rb +772 -0
- data/test/cases/transaction_isolation_test.rb +106 -0
- data/test/cases/transactions_test.rb +1285 -0
- data/test/cases/type/adapter_specific_registry_test.rb +145 -0
- data/test/cases/type/date_time_test.rb +16 -0
- data/test/cases/type/integer_test.rb +29 -0
- data/test/cases/type/string_test.rb +24 -0
- data/test/cases/type/time_test.rb +28 -0
- data/test/cases/type/type_map_test.rb +178 -0
- data/test/cases/type/unsigned_integer_test.rb +19 -0
- data/test/cases/type_test.rb +41 -0
- data/test/cases/types_test.rb +26 -0
- data/test/cases/unconnected_test.rb +46 -0
- data/test/cases/unsafe_raw_sql_test.rb +274 -0
- data/test/cases/validations/absence_validation_test.rb +75 -0
- data/test/cases/validations/association_validation_test.rb +99 -0
- data/test/cases/validations/i18n_generate_message_validation_test.rb +102 -0
- data/test/cases/validations/i18n_validation_test.rb +87 -0
- data/test/cases/validations/length_validation_test.rb +80 -0
- data/test/cases/validations/numericality_validation_test.rb +181 -0
- data/test/cases/validations/presence_validation_test.rb +105 -0
- data/test/cases/validations/uniqueness_validation_test.rb +618 -0
- data/test/cases/validations_repair_helper.rb +21 -0
- data/test/cases/validations_test.rb +229 -0
- data/test/cases/view_test.rb +222 -0
- data/test/cases/yaml_serialization_test.rb +166 -0
- data/test/config.example.yml +97 -0
- data/test/config.rb +7 -0
- data/test/config.yml +220 -0
- data/test/connections/native_ibm_db/connection.rb +44 -0
- data/test/fixtures/accounts.yml +29 -0
- data/test/fixtures/admin/accounts.yml +2 -0
- data/test/fixtures/admin/randomly_named_a9.yml +7 -0
- data/test/fixtures/admin/randomly_named_b0.yml +7 -0
- data/test/fixtures/admin/users.yml +10 -0
- data/test/fixtures/all/admin +1 -0
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/namespaced/accounts.yml +2 -0
- data/test/fixtures/all/people.yml +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +11 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +17 -0
- data/test/fixtures/bad_posts.yml +9 -0
- data/test/fixtures/binaries.yml +137 -0
- data/test/fixtures/books.yml +38 -0
- data/test/fixtures/bulbs.yml +5 -0
- data/test/fixtures/cars.yml +9 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories.yml +19 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +34 -0
- data/test/fixtures/categorizations.yml +23 -0
- data/test/fixtures/citations.yml +5 -0
- data/test/fixtures/clubs.yml +8 -0
- data/test/fixtures/collections.yml +3 -0
- data/test/fixtures/colleges.yml +3 -0
- data/test/fixtures/comments.yml +72 -0
- data/test/fixtures/companies.yml +72 -0
- data/test/fixtures/computers.yml +12 -0
- data/test/fixtures/content.yml +3 -0
- data/test/fixtures/content_positions.yml +3 -0
- data/test/fixtures/courses.yml +8 -0
- data/test/fixtures/customers.yml +35 -0
- data/test/fixtures/dashboards.yml +6 -0
- data/test/fixtures/dead_parrots.yml +5 -0
- data/test/fixtures/developers.yml +22 -0
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/dog_lovers.yml +7 -0
- data/test/fixtures/dogs.yml +4 -0
- data/test/fixtures/doubloons.yml +3 -0
- data/test/fixtures/edges.yml +5 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/essays.yml +16 -0
- data/test/fixtures/faces.yml +11 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/friendships.yml +4 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/humans.yml +5 -0
- data/test/fixtures/interests.yml +33 -0
- data/test/fixtures/items.yml +3 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/live_parrots.yml +4 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/member_details.yml +8 -0
- data/test/fixtures/member_types.yml +6 -0
- data/test/fixtures/members.yml +11 -0
- data/test/fixtures/memberships.yml +41 -0
- data/test/fixtures/men.yml +5 -0
- data/test/fixtures/minimalistics.yml +5 -0
- data/test/fixtures/minivans.yml +5 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixins.yml +29 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
- data/test/fixtures/naked/yml/parrots.yml +3 -0
- data/test/fixtures/naked/yml/trees.yml +3 -0
- data/test/fixtures/nodes.yml +29 -0
- data/test/fixtures/organizations.yml +5 -0
- data/test/fixtures/other_books.yml +26 -0
- data/test/fixtures/other_comments.yml +6 -0
- data/test/fixtures/other_dogs.yml +2 -0
- data/test/fixtures/other_posts.yml +8 -0
- data/test/fixtures/other_topics.yml +42 -0
- data/test/fixtures/owners.yml +9 -0
- data/test/fixtures/parrots.yml +33 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/people.yml +24 -0
- data/test/fixtures/peoples_treasures.yml +3 -0
- data/test/fixtures/pets.yml +19 -0
- data/test/fixtures/pirates.yml +15 -0
- data/test/fixtures/posts.yml +88 -0
- data/test/fixtures/price_estimates.yml +16 -0
- data/test/fixtures/products.yml +4 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/randomly_named_a9.yml +7 -0
- data/test/fixtures/ratings.yml +14 -0
- data/test/fixtures/readers.yml +17 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distinct_select.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ships.yml +6 -0
- data/test/fixtures/speedometers.yml +8 -0
- data/test/fixtures/sponsors.yml +15 -0
- data/test/fixtures/strict_zines.yml +2 -0
- data/test/fixtures/string_key_objects.yml +7 -0
- data/test/fixtures/subscribers.yml +11 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +78 -0
- data/test/fixtures/tags.yml +11 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/teapots.yml +3 -0
- data/test/fixtures/to_be_linked/accounts.yml +2 -0
- data/test/fixtures/to_be_linked/users.yml +10 -0
- data/test/fixtures/topics.yml +49 -0
- data/test/fixtures/toys.yml +14 -0
- data/test/fixtures/traffic_lights.yml +10 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures/trees.yml +3 -0
- data/test/fixtures/uuid_children.yml +3 -0
- data/test/fixtures/uuid_parents.yml +2 -0
- data/test/fixtures/variants.yml +4 -0
- data/test/fixtures/vegetables.yml +20 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/fixtures/warehouse_things.yml +3 -0
- data/test/fixtures/zines.yml +5 -0
- data/test/ibm_db_test.rb +25 -0
- data/test/migrations/10_urban/9_add_expressions.rb +13 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +17 -0
- data/test/migrations/magic/1_currencies_have_symbols.rb +13 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +11 -0
- data/test/migrations/missing/1_people_have_last_names.rb +11 -0
- data/test/migrations/missing/3_we_need_reminders.rb +14 -0
- data/test/migrations/missing/4_innocent_jointable.rb +14 -0
- data/test/migrations/rename/1_we_need_things.rb +13 -0
- data/test/migrations/rename/2_rename_things.rb +11 -0
- data/test/migrations/to_copy/1_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy/2_people_have_descriptions.rb +11 -0
- data/test/migrations/to_copy2/1_create_articles.rb +9 -0
- data/test/migrations/to_copy2/2_create_comments.rb +9 -0
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +11 -0
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +11 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +9 -0
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +9 -0
- data/test/migrations/valid/1_valid_people_have_last_names.rb +11 -0
- data/test/migrations/valid/2_we_need_reminders.rb +14 -0
- data/test/migrations/valid/3_innocent_jointable.rb +14 -0
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +11 -0
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +14 -0
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +14 -0
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +11 -0
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +14 -0
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +14 -0
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +10 -0
- data/test/models/account.rb +46 -0
- data/test/models/admin/account.rb +5 -0
- data/test/models/admin/randomly_named_c1.rb +9 -0
- data/test/models/admin/user.rb +48 -0
- data/test/models/admin.rb +7 -0
- data/test/models/aircraft.rb +7 -0
- data/test/models/arunit2_model.rb +5 -0
- data/test/models/author.rb +260 -0
- data/test/models/auto_id.rb +6 -0
- data/test/models/autoloadable/extra_firm.rb +4 -0
- data/test/models/binary.rb +4 -0
- data/test/models/binary_field.rb +6 -0
- data/test/models/bird.rb +24 -0
- data/test/models/book.rb +33 -0
- data/test/models/book_destroy_async.rb +24 -0
- data/test/models/boolean.rb +7 -0
- data/test/models/bulb.rb +61 -0
- data/test/models/cake_designer.rb +5 -0
- data/test/models/car.rb +36 -0
- data/test/models/carrier.rb +4 -0
- data/test/models/cart.rb +5 -0
- data/test/models/cat.rb +12 -0
- data/test/models/categorization.rb +21 -0
- data/test/models/category.rb +47 -0
- data/test/models/chef.rb +10 -0
- data/test/models/citation.rb +7 -0
- data/test/models/club.rb +28 -0
- data/test/models/college.rb +12 -0
- data/test/models/column.rb +5 -0
- data/test/models/column_name.rb +5 -0
- data/test/models/comment.rb +98 -0
- data/test/models/company.rb +226 -0
- data/test/models/company_in_module.rb +99 -0
- data/test/models/computer.rb +5 -0
- data/test/models/contact.rb +43 -0
- data/test/models/content.rb +42 -0
- data/test/models/contract.rb +38 -0
- data/test/models/country.rb +5 -0
- data/test/models/course.rb +8 -0
- data/test/models/customer.rb +85 -0
- data/test/models/customer_carrier.rb +16 -0
- data/test/models/dashboard.rb +5 -0
- data/test/models/default.rb +4 -0
- data/test/models/department.rb +6 -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 +341 -0
- 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 +7 -0
- data/test/models/dog_lover.rb +7 -0
- data/test/models/doubloon.rb +14 -0
- data/test/models/drink_designer.rb +20 -0
- data/test/models/edge.rb +7 -0
- data/test/models/electron.rb +7 -0
- data/test/models/engine.rb +5 -0
- data/test/models/entrant.rb +5 -0
- data/test/models/entry.rb +5 -0
- data/test/models/essay.rb +8 -0
- data/test/models/essay_destroy_async.rb +12 -0
- data/test/models/event.rb +5 -0
- data/test/models/eye.rb +39 -0
- data/test/models/face.rb +17 -0
- data/test/models/family.rb +6 -0
- data/test/models/family_tree.rb +6 -0
- data/test/models/friendship.rb +8 -0
- data/test/models/frog.rb +8 -0
- data/test/models/guid.rb +4 -0
- data/test/models/guitar.rb +6 -0
- data/test/models/hotel.rb +13 -0
- data/test/models/human.rb +39 -0
- data/test/models/image.rb +5 -0
- data/test/models/interest.rb +16 -0
- data/test/models/invoice.rb +6 -0
- data/test/models/item.rb +9 -0
- data/test/models/job.rb +9 -0
- data/test/models/joke.rb +9 -0
- data/test/models/keyboard.rb +5 -0
- data/test/models/legacy_thing.rb +5 -0
- data/test/models/lesson.rb +13 -0
- data/test/models/line_item.rb +5 -0
- data/test/models/liquid.rb +6 -0
- data/test/models/man.rb +11 -0
- data/test/models/matey.rb +6 -0
- data/test/models/measurement.rb +4 -0
- data/test/models/member.rb +45 -0
- data/test/models/member_detail.rb +11 -0
- data/test/models/member_type.rb +5 -0
- data/test/models/membership.rb +38 -0
- data/test/models/mentor.rb +5 -0
- data/test/models/message.rb +5 -0
- data/test/models/minimalistic.rb +4 -0
- data/test/models/minivan.rb +10 -0
- data/test/models/mixed_case_monkey.rb +5 -0
- data/test/models/mocktail_designer.rb +2 -0
- data/test/models/molecule.rb +8 -0
- data/test/models/mouse.rb +6 -0
- data/test/models/movie.rb +7 -0
- data/test/models/node.rb +7 -0
- data/test/models/non_primary_key.rb +4 -0
- data/test/models/notification.rb +5 -0
- data/test/models/numeric_data.rb +12 -0
- data/test/models/order.rb +6 -0
- data/test/models/organization.rb +16 -0
- data/test/models/other_dog.rb +7 -0
- data/test/models/owner.rb +39 -0
- data/test/models/parrot.rb +36 -0
- data/test/models/person.rb +147 -0
- data/test/models/personal_legacy_thing.rb +6 -0
- data/test/models/pet.rb +20 -0
- data/test/models/pet_treasure.rb +8 -0
- data/test/models/pirate.rb +116 -0
- data/test/models/possession.rb +5 -0
- data/test/models/post.rb +371 -0
- data/test/models/price_estimate.rb +14 -0
- data/test/models/professor.rb +7 -0
- data/test/models/project.rb +42 -0
- data/test/models/publisher/article.rb +6 -0
- data/test/models/publisher/magazine.rb +5 -0
- data/test/models/publisher.rb +4 -0
- data/test/models/randomly_named_c1.rb +5 -0
- data/test/models/rating.rb +8 -0
- data/test/models/reader.rb +25 -0
- data/test/models/recipe.rb +5 -0
- data/test/models/record.rb +4 -0
- data/test/models/reference.rb +25 -0
- data/test/models/reply.rb +79 -0
- 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 +42 -0
- data/test/models/ship_part.rb +10 -0
- data/test/models/shop.rb +19 -0
- data/test/models/shop_account.rb +8 -0
- data/test/models/speedometer.rb +8 -0
- data/test/models/sponsor.rb +10 -0
- data/test/models/squeak.rb +6 -0
- data/test/models/strict_zine.rb +7 -0
- data/test/models/string_key_object.rb +5 -0
- data/test/models/student.rb +6 -0
- data/test/models/subject.rb +16 -0
- data/test/models/subscriber.rb +10 -0
- data/test/models/subscription.rb +8 -0
- data/test/models/tag.rb +16 -0
- data/test/models/tagging.rb +20 -0
- data/test/models/task.rb +7 -0
- data/test/models/topic.rb +153 -0
- data/test/models/toy.rb +10 -0
- data/test/models/traffic_light.rb +6 -0
- data/test/models/treasure.rb +16 -0
- data/test/models/treaty.rb +5 -0
- data/test/models/tree.rb +5 -0
- data/test/models/tuning_peg.rb +6 -0
- data/test/models/tyre.rb +13 -0
- data/test/models/user.rb +22 -0
- data/test/models/uuid_child.rb +5 -0
- data/test/models/uuid_item.rb +8 -0
- data/test/models/uuid_parent.rb +5 -0
- data/test/models/vegetables.rb +33 -0
- data/test/models/vehicle.rb +7 -0
- data/test/models/vertex.rb +11 -0
- data/test/models/warehouse_thing.rb +7 -0
- data/test/models/wheel.rb +5 -0
- data/test/models/without_table.rb +5 -0
- data/test/models/zine.rb +5 -0
- data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
- data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
- data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
- data/test/schema/mysql2_specific_schema.rb +82 -0
- data/test/schema/oracle_specific_schema.rb +38 -0
- data/test/schema/postgresql_specific_schema.rb +125 -0
- data/test/schema/schema.rb +1237 -0
- data/test/schema/schema.rb.original +1057 -0
- data/test/schema/sqlite_specific_schema.rb +11 -0
- data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
- data/test/support/config.rb +43 -0
- data/test/support/connection.rb +29 -0
- data/test/support/connection_helper.rb +16 -0
- data/test/support/ddl_helper.rb +10 -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 +22 -0
- data/test/support/stubs/strong_parameters.rb +40 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -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 +876 -0
@@ -0,0 +1,1285 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cases/helper"
|
4
|
+
require "models/topic"
|
5
|
+
require "models/reply"
|
6
|
+
require "models/developer"
|
7
|
+
require "models/computer"
|
8
|
+
require "models/book"
|
9
|
+
require "models/author"
|
10
|
+
require "models/post"
|
11
|
+
require "models/movie"
|
12
|
+
|
13
|
+
class TransactionTest < ActiveRecord::TestCase
|
14
|
+
self.use_transactional_tests = false
|
15
|
+
fixtures :topics, :developers, :authors, :author_addresses, :posts
|
16
|
+
|
17
|
+
def setup
|
18
|
+
@first, @second = Topic.find(1, 2).sort_by(&:id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_rollback_dirty_changes
|
22
|
+
topic = topics(:fifth)
|
23
|
+
|
24
|
+
ActiveRecord::Base.transaction do
|
25
|
+
topic.update(title: "Ruby on Rails")
|
26
|
+
raise ActiveRecord::Rollback
|
27
|
+
end
|
28
|
+
|
29
|
+
title_change = ["The Fifth Topic of the day", "Ruby on Rails"]
|
30
|
+
assert_equal title_change, topic.changes["title"]
|
31
|
+
end
|
32
|
+
|
33
|
+
if !in_memory_db?
|
34
|
+
def test_rollback_dirty_changes_even_with_raise_during_rollback_removes_from_pool
|
35
|
+
topic = topics(:fifth)
|
36
|
+
|
37
|
+
connection = Topic.connection
|
38
|
+
|
39
|
+
Topic.connection.class_eval do
|
40
|
+
alias :real_exec_rollback_db_transaction :exec_rollback_db_transaction
|
41
|
+
define_method(:exec_rollback_db_transaction) do
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveRecord::Base.transaction do
|
47
|
+
topic.update(title: "Rails is broken")
|
48
|
+
raise ActiveRecord::Rollback
|
49
|
+
end
|
50
|
+
|
51
|
+
assert_not connection.active?
|
52
|
+
assert_not Topic.connection_pool.connections.include?(connection)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_rollback_dirty_changes_even_with_raise_during_rollback_doesnt_commit_transaction
|
56
|
+
topic = topics(:fifth)
|
57
|
+
|
58
|
+
Topic.connection.class_eval do
|
59
|
+
alias :real_exec_rollback_db_transaction :exec_rollback_db_transaction
|
60
|
+
define_method(:exec_rollback_db_transaction) do
|
61
|
+
raise
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
ActiveRecord::Base.transaction do
|
66
|
+
topic.update(title: "Rails is broken")
|
67
|
+
raise ActiveRecord::Rollback
|
68
|
+
end
|
69
|
+
|
70
|
+
topic.reload
|
71
|
+
|
72
|
+
ActiveRecord::Base.transaction do
|
73
|
+
topic.update(content: "Ruby on Rails - modified")
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_equal "The Fifth Topic of the day", topic.reload.title
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_rollback_dirty_changes_multiple_saves
|
81
|
+
topic = topics(:fifth)
|
82
|
+
|
83
|
+
ActiveRecord::Base.transaction do
|
84
|
+
topic.update(title: "Ruby on Rails")
|
85
|
+
topic.update(title: "Another Title")
|
86
|
+
raise ActiveRecord::Rollback
|
87
|
+
end
|
88
|
+
|
89
|
+
title_change = ["The Fifth Topic of the day", "Another Title"]
|
90
|
+
assert_equal title_change, topic.changes["title"]
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_rollback_dirty_changes_then_retry_save
|
94
|
+
topic = topics(:fifth)
|
95
|
+
|
96
|
+
ActiveRecord::Base.transaction do
|
97
|
+
topic.update(title: "Ruby on Rails")
|
98
|
+
raise ActiveRecord::Rollback
|
99
|
+
end
|
100
|
+
|
101
|
+
title_change = ["The Fifth Topic of the day", "Ruby on Rails"]
|
102
|
+
assert_equal title_change, topic.changes["title"]
|
103
|
+
|
104
|
+
assert topic.save
|
105
|
+
|
106
|
+
assert_equal title_change, topic.saved_changes["title"]
|
107
|
+
assert_equal topic.title, topic.reload.title
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_rollback_dirty_changes_then_retry_save_on_new_record
|
111
|
+
topic = Topic.new(title: "Ruby on Rails")
|
112
|
+
|
113
|
+
ActiveRecord::Base.transaction do
|
114
|
+
topic.save
|
115
|
+
raise ActiveRecord::Rollback
|
116
|
+
end
|
117
|
+
|
118
|
+
title_change = [nil, "Ruby on Rails"]
|
119
|
+
assert_equal title_change, topic.changes["title"]
|
120
|
+
|
121
|
+
assert topic.save
|
122
|
+
|
123
|
+
assert_equal title_change, topic.saved_changes["title"]
|
124
|
+
assert_equal topic.title, topic.reload.title
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_rollback_dirty_changes_then_retry_save_on_new_record_with_autosave_association
|
128
|
+
author = Author.new(name: "DHH")
|
129
|
+
book = Book.create!
|
130
|
+
author.books << book
|
131
|
+
|
132
|
+
author.transaction do
|
133
|
+
author.save!
|
134
|
+
raise ActiveRecord::Rollback
|
135
|
+
end
|
136
|
+
|
137
|
+
author.save!
|
138
|
+
assert_equal author, book.reload.author
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_persisted_in_a_model_with_custom_primary_key_after_failed_save
|
142
|
+
movie = Movie.create
|
143
|
+
assert_not_predicate movie, :persisted?
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_raise_after_destroy
|
147
|
+
assert_not_predicate @first, :frozen?
|
148
|
+
|
149
|
+
assert_raises(RuntimeError) do
|
150
|
+
Topic.transaction do
|
151
|
+
@first.destroy
|
152
|
+
assert_predicate @first, :frozen?
|
153
|
+
raise
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
assert_not_predicate @first, :frozen?
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_successful
|
161
|
+
Topic.transaction do
|
162
|
+
@first.approved = true
|
163
|
+
@second.approved = false
|
164
|
+
@first.save
|
165
|
+
@second.save
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_predicate Topic.find(1), :approved?, "First should have been approved"
|
169
|
+
assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
|
170
|
+
end
|
171
|
+
|
172
|
+
def transaction_with_return
|
173
|
+
Topic.transaction do
|
174
|
+
@first.approved = true
|
175
|
+
@second.approved = false
|
176
|
+
@first.save
|
177
|
+
@second.save
|
178
|
+
return
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_add_to_null_transaction
|
183
|
+
topic = Topic.new
|
184
|
+
topic.send(:add_to_transaction)
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_successful_with_return
|
188
|
+
committed = false
|
189
|
+
|
190
|
+
Topic.connection.class_eval do
|
191
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
192
|
+
define_method(:commit_db_transaction) do
|
193
|
+
committed = true
|
194
|
+
real_commit_db_transaction
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
assert_deprecated do
|
199
|
+
transaction_with_return
|
200
|
+
end
|
201
|
+
assert committed
|
202
|
+
|
203
|
+
assert_predicate Topic.find(1), :approved?, "First should have been approved"
|
204
|
+
assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
|
205
|
+
ensure
|
206
|
+
Topic.connection.class_eval do
|
207
|
+
remove_method :commit_db_transaction
|
208
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_deprecation_on_ruby_timeout
|
213
|
+
assert_deprecated do
|
214
|
+
catch do |timeout|
|
215
|
+
Topic.transaction do
|
216
|
+
@first.approved = true
|
217
|
+
@first.save!
|
218
|
+
|
219
|
+
throw timeout
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_early_return_from_transaction
|
228
|
+
assert_not_deprecated do
|
229
|
+
@first.with_lock do
|
230
|
+
break
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_number_of_transactions_in_commit
|
236
|
+
num = nil
|
237
|
+
|
238
|
+
Topic.connection.class_eval do
|
239
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
240
|
+
define_method(:commit_db_transaction) do
|
241
|
+
num = transaction_manager.open_transactions
|
242
|
+
real_commit_db_transaction
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
Topic.transaction do
|
247
|
+
@first.approved = true
|
248
|
+
@first.save!
|
249
|
+
end
|
250
|
+
|
251
|
+
assert_equal 0, num
|
252
|
+
ensure
|
253
|
+
Topic.connection.class_eval do
|
254
|
+
remove_method :commit_db_transaction
|
255
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_successful_with_instance_method
|
260
|
+
@first.transaction do
|
261
|
+
@first.approved = true
|
262
|
+
@second.approved = false
|
263
|
+
@first.save
|
264
|
+
@second.save
|
265
|
+
end
|
266
|
+
|
267
|
+
assert_predicate Topic.find(1), :approved?, "First should have been approved"
|
268
|
+
assert_not_predicate Topic.find(2), :approved?, "Second should have been unapproved"
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_failing_on_exception
|
272
|
+
begin
|
273
|
+
Topic.transaction do
|
274
|
+
@first.approved = true
|
275
|
+
@second.approved = false
|
276
|
+
@first.save
|
277
|
+
@second.save
|
278
|
+
raise "Bad things!"
|
279
|
+
end
|
280
|
+
rescue
|
281
|
+
# caught it
|
282
|
+
end
|
283
|
+
|
284
|
+
assert_predicate @first, :approved?, "First should still be changed in the objects"
|
285
|
+
assert_not_predicate @second, :approved?, "Second should still be changed in the objects"
|
286
|
+
|
287
|
+
assert_not_predicate Topic.find(1), :approved?, "First shouldn't have been approved"
|
288
|
+
assert_predicate Topic.find(2), :approved?, "Second should still be approved"
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_raising_exception_in_callback_rollbacks_in_save
|
292
|
+
def @first.after_save_for_transaction
|
293
|
+
raise "Make the transaction rollback"
|
294
|
+
end
|
295
|
+
|
296
|
+
@first.approved = true
|
297
|
+
e = assert_raises(RuntimeError) { @first.save }
|
298
|
+
assert_equal "Make the transaction rollback", e.message
|
299
|
+
assert_not_predicate Topic.find(1), :approved?
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_rolling_back_in_a_callback_rollbacks_before_save
|
303
|
+
def @first.before_save_for_transaction
|
304
|
+
raise ActiveRecord::Rollback
|
305
|
+
end
|
306
|
+
assert_not_predicate @first, :approved?
|
307
|
+
|
308
|
+
assert_not_called(@first, :rolledback!) do
|
309
|
+
Topic.transaction do
|
310
|
+
@first.approved = true
|
311
|
+
@first.save!
|
312
|
+
end
|
313
|
+
end
|
314
|
+
assert_not_predicate Topic.find(@first.id), :approved?, "Should not commit the approved flag"
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_raising_exception_in_nested_transaction_restore_state_in_save
|
318
|
+
topic = Topic.new
|
319
|
+
|
320
|
+
def topic.after_save_for_transaction
|
321
|
+
raise "Make the transaction rollback"
|
322
|
+
end
|
323
|
+
|
324
|
+
assert_raises(RuntimeError) do
|
325
|
+
Topic.transaction { topic.save }
|
326
|
+
end
|
327
|
+
|
328
|
+
assert_predicate topic, :new_record?, "#{topic.inspect} should be new record"
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_transaction_state_is_cleared_when_record_is_persisted
|
332
|
+
author = Author.create! name: "foo"
|
333
|
+
author.name = nil
|
334
|
+
assert_not author.save
|
335
|
+
assert_not_predicate author, :new_record?
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_update_should_rollback_on_failure
|
339
|
+
author = Author.find(1)
|
340
|
+
posts_count = author.posts.size
|
341
|
+
assert posts_count > 0
|
342
|
+
status = author.update(name: nil, post_ids: [])
|
343
|
+
assert_not status
|
344
|
+
assert_equal posts_count, author.posts.reload.size
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_update_should_rollback_on_failure!
|
348
|
+
author = Author.find(1)
|
349
|
+
posts_count = author.posts.size
|
350
|
+
assert posts_count > 0
|
351
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
352
|
+
author.update!(name: nil, post_ids: [])
|
353
|
+
end
|
354
|
+
assert_equal posts_count, author.posts.reload.size
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_cancellation_from_before_destroy_rollbacks_in_destroy
|
358
|
+
add_cancelling_before_destroy_with_db_side_effect_to_topic @first
|
359
|
+
nbooks_before_destroy = Book.count
|
360
|
+
status = @first.destroy
|
361
|
+
assert_not status
|
362
|
+
@first.reload
|
363
|
+
assert_equal nbooks_before_destroy, Book.count
|
364
|
+
end
|
365
|
+
|
366
|
+
%w(validation save).each do |filter|
|
367
|
+
define_method("test_cancellation_from_before_filters_rollbacks_in_#{filter}") do
|
368
|
+
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic", @first)
|
369
|
+
nbooks_before_save = Book.count
|
370
|
+
original_author_name = @first.author_name
|
371
|
+
@first.author_name += "_this_should_not_end_up_in_the_db"
|
372
|
+
status = @first.save
|
373
|
+
assert_not status
|
374
|
+
assert_equal original_author_name, @first.reload.author_name
|
375
|
+
assert_equal nbooks_before_save, Book.count
|
376
|
+
end
|
377
|
+
|
378
|
+
define_method("test_cancellation_from_before_filters_rollbacks_in_#{filter}!") do
|
379
|
+
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic", @first)
|
380
|
+
nbooks_before_save = Book.count
|
381
|
+
original_author_name = @first.author_name
|
382
|
+
@first.author_name += "_this_should_not_end_up_in_the_db"
|
383
|
+
|
384
|
+
begin
|
385
|
+
@first.save!
|
386
|
+
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved
|
387
|
+
end
|
388
|
+
|
389
|
+
assert_equal original_author_name, @first.reload.author_name
|
390
|
+
assert_equal nbooks_before_save, Book.count
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def test_callback_rollback_in_create
|
395
|
+
topic = Class.new(Topic) {
|
396
|
+
def after_create_for_transaction
|
397
|
+
raise "Make the transaction rollback"
|
398
|
+
end
|
399
|
+
}
|
400
|
+
|
401
|
+
new_topic = topic.new(title: "A new topic",
|
402
|
+
author_name: "Ben",
|
403
|
+
author_email_address: "ben@example.com",
|
404
|
+
written_on: "2003-07-16t15:28:11.2233+01:00",
|
405
|
+
last_read: "2004-04-15",
|
406
|
+
bonus_time: "2005-01-30t15:28:00.00+01:00",
|
407
|
+
content: "Have a nice day",
|
408
|
+
approved: false)
|
409
|
+
|
410
|
+
new_record_snapshot = !new_topic.persisted?
|
411
|
+
id_present = new_topic.has_attribute?(Topic.primary_key)
|
412
|
+
id_snapshot = new_topic.id
|
413
|
+
|
414
|
+
# Make sure the second save gets the after_create callback called.
|
415
|
+
2.times do
|
416
|
+
new_topic.approved = true
|
417
|
+
e = assert_raises(RuntimeError) { new_topic.save }
|
418
|
+
assert_equal "Make the transaction rollback", e.message
|
419
|
+
assert_equal new_record_snapshot, !new_topic.persisted?, "The topic should have its old persisted value"
|
420
|
+
if id_snapshot.nil?
|
421
|
+
assert_nil new_topic.id, "The topic should have its old id"
|
422
|
+
else
|
423
|
+
assert_equal id_snapshot, new_topic.id, "The topic should have its old id"
|
424
|
+
end
|
425
|
+
assert_equal id_present, new_topic.has_attribute?(Topic.primary_key)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def test_callback_rollback_in_create_with_record_invalid_exception
|
430
|
+
topic = Class.new(Topic) {
|
431
|
+
def after_create_for_transaction
|
432
|
+
raise ActiveRecord::RecordInvalid.new(Author.new)
|
433
|
+
end
|
434
|
+
}
|
435
|
+
|
436
|
+
new_topic = topic.create(title: "A new topic")
|
437
|
+
assert_not new_topic.persisted?, "The topic should not be persisted"
|
438
|
+
assert_nil new_topic.id, "The topic should not have an ID"
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_callback_rollback_in_create_with_rollback_exception
|
442
|
+
topic = Class.new(Topic) {
|
443
|
+
def after_create_for_transaction
|
444
|
+
raise ActiveRecord::Rollback
|
445
|
+
end
|
446
|
+
}
|
447
|
+
|
448
|
+
new_topic = topic.create(title: "A new topic")
|
449
|
+
assert_not new_topic.persisted?, "The topic should not be persisted"
|
450
|
+
assert_nil new_topic.id, "The topic should not have an ID"
|
451
|
+
end
|
452
|
+
|
453
|
+
def test_nested_explicit_transactions
|
454
|
+
Topic.transaction do
|
455
|
+
Topic.transaction do
|
456
|
+
@first.approved = true
|
457
|
+
@second.approved = false
|
458
|
+
@first.save
|
459
|
+
@second.save
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
464
|
+
assert_not Topic.find(2).approved?, "Second should have been unapproved"
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_nested_transaction_with_new_transaction_applies_parent_state_on_rollback
|
468
|
+
topic_one = Topic.new(title: "A new topic")
|
469
|
+
topic_two = Topic.new(title: "Another new topic")
|
470
|
+
|
471
|
+
Topic.transaction do
|
472
|
+
topic_one.save
|
473
|
+
|
474
|
+
Topic.transaction(requires_new: true) do
|
475
|
+
topic_two.save
|
476
|
+
|
477
|
+
assert_predicate topic_one, :persisted?
|
478
|
+
assert_predicate topic_two, :persisted?
|
479
|
+
end
|
480
|
+
|
481
|
+
raise ActiveRecord::Rollback
|
482
|
+
end
|
483
|
+
|
484
|
+
assert_not_predicate topic_one, :persisted?
|
485
|
+
assert_not_predicate topic_two, :persisted?
|
486
|
+
end
|
487
|
+
|
488
|
+
def test_nested_transaction_without_new_transaction_applies_parent_state_on_rollback
|
489
|
+
topic_one = Topic.new(title: "A new topic")
|
490
|
+
topic_two = Topic.new(title: "Another new topic")
|
491
|
+
|
492
|
+
Topic.transaction do
|
493
|
+
topic_one.save
|
494
|
+
|
495
|
+
Topic.transaction do
|
496
|
+
topic_two.save
|
497
|
+
|
498
|
+
assert_predicate topic_one, :persisted?
|
499
|
+
assert_predicate topic_two, :persisted?
|
500
|
+
end
|
501
|
+
|
502
|
+
raise ActiveRecord::Rollback
|
503
|
+
end
|
504
|
+
|
505
|
+
assert_not_predicate topic_one, :persisted?
|
506
|
+
assert_not_predicate topic_two, :persisted?
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_double_nested_transaction_applies_parent_state_on_rollback
|
510
|
+
topic_one = Topic.new(title: "A new topic")
|
511
|
+
topic_two = Topic.new(title: "Another new topic")
|
512
|
+
topic_three = Topic.new(title: "Another new topic of course")
|
513
|
+
|
514
|
+
Topic.transaction do
|
515
|
+
topic_one.save
|
516
|
+
|
517
|
+
Topic.transaction do
|
518
|
+
topic_two.save
|
519
|
+
|
520
|
+
Topic.transaction do
|
521
|
+
topic_three.save
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
assert_predicate topic_one, :persisted?
|
526
|
+
assert_predicate topic_two, :persisted?
|
527
|
+
assert_predicate topic_three, :persisted?
|
528
|
+
|
529
|
+
raise ActiveRecord::Rollback
|
530
|
+
end
|
531
|
+
|
532
|
+
assert_not_predicate topic_one, :persisted?
|
533
|
+
assert_not_predicate topic_two, :persisted?
|
534
|
+
assert_not_predicate topic_three, :persisted?
|
535
|
+
end
|
536
|
+
|
537
|
+
def test_manually_rolling_back_a_transaction
|
538
|
+
Topic.transaction do
|
539
|
+
@first.approved = true
|
540
|
+
@second.approved = false
|
541
|
+
@first.save
|
542
|
+
@second.save
|
543
|
+
|
544
|
+
raise ActiveRecord::Rollback
|
545
|
+
end
|
546
|
+
|
547
|
+
assert @first.approved?, "First should still be changed in the objects"
|
548
|
+
assert_not @second.approved?, "Second should still be changed in the objects"
|
549
|
+
|
550
|
+
assert_not Topic.find(1).approved?, "First shouldn't have been approved"
|
551
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_invalid_keys_for_transaction
|
555
|
+
assert_raise ArgumentError do
|
556
|
+
Topic.transaction nested: true do
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
def test_force_savepoint_in_nested_transaction
|
562
|
+
Topic.transaction do
|
563
|
+
@first.approved = true
|
564
|
+
@second.approved = false
|
565
|
+
@first.save!
|
566
|
+
@second.save!
|
567
|
+
|
568
|
+
begin
|
569
|
+
Topic.transaction requires_new: true do
|
570
|
+
@first.approved = false
|
571
|
+
@first.save!
|
572
|
+
raise
|
573
|
+
end
|
574
|
+
rescue
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
assert_predicate @first.reload, :approved?
|
579
|
+
assert_not_predicate @second.reload, :approved?
|
580
|
+
end if Topic.connection.supports_savepoints?
|
581
|
+
|
582
|
+
def test_force_savepoint_on_instance
|
583
|
+
@first.transaction do
|
584
|
+
@first.approved = true
|
585
|
+
@second.approved = false
|
586
|
+
@first.save!
|
587
|
+
@second.save!
|
588
|
+
|
589
|
+
begin
|
590
|
+
@second.transaction requires_new: true do
|
591
|
+
@first.approved = false
|
592
|
+
@first.save!
|
593
|
+
raise
|
594
|
+
end
|
595
|
+
rescue
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
assert_predicate @first.reload, :approved?
|
600
|
+
assert_not_predicate @second.reload, :approved?
|
601
|
+
end if Topic.connection.supports_savepoints?
|
602
|
+
|
603
|
+
def test_no_savepoint_in_nested_transaction_without_force
|
604
|
+
Topic.transaction do
|
605
|
+
@first.approved = true
|
606
|
+
@second.approved = false
|
607
|
+
@first.save!
|
608
|
+
@second.save!
|
609
|
+
|
610
|
+
begin
|
611
|
+
Topic.transaction do
|
612
|
+
@first.approved = false
|
613
|
+
@first.save!
|
614
|
+
raise
|
615
|
+
end
|
616
|
+
rescue
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
assert_not_predicate @first.reload, :approved?
|
621
|
+
assert_not_predicate @second.reload, :approved?
|
622
|
+
end if Topic.connection.supports_savepoints?
|
623
|
+
|
624
|
+
def test_many_savepoints
|
625
|
+
Topic.transaction do
|
626
|
+
@first.content = "One"
|
627
|
+
@first.save!
|
628
|
+
|
629
|
+
begin
|
630
|
+
Topic.transaction requires_new: true do
|
631
|
+
@first.content = "Two"
|
632
|
+
@first.save!
|
633
|
+
|
634
|
+
begin
|
635
|
+
Topic.transaction requires_new: true do
|
636
|
+
@first.content = "Three"
|
637
|
+
@first.save!
|
638
|
+
|
639
|
+
begin
|
640
|
+
Topic.transaction requires_new: true do
|
641
|
+
@first.content = "Four"
|
642
|
+
@first.save!
|
643
|
+
raise
|
644
|
+
end
|
645
|
+
rescue
|
646
|
+
end
|
647
|
+
|
648
|
+
@three = @first.reload.content
|
649
|
+
raise
|
650
|
+
end
|
651
|
+
rescue
|
652
|
+
end
|
653
|
+
|
654
|
+
@two = @first.reload.content
|
655
|
+
raise
|
656
|
+
end
|
657
|
+
rescue
|
658
|
+
end
|
659
|
+
|
660
|
+
@one = @first.reload.content
|
661
|
+
end
|
662
|
+
|
663
|
+
assert_equal "One", @one
|
664
|
+
assert_equal "Two", @two
|
665
|
+
assert_equal "Three", @three
|
666
|
+
end if Topic.connection.supports_savepoints?
|
667
|
+
|
668
|
+
def test_using_named_savepoints
|
669
|
+
Topic.transaction do
|
670
|
+
@first.approved = true
|
671
|
+
@first.save!
|
672
|
+
Topic.connection.create_savepoint("first")
|
673
|
+
|
674
|
+
@first.approved = false
|
675
|
+
@first.save!
|
676
|
+
Topic.connection.rollback_to_savepoint("first")
|
677
|
+
assert_predicate @first.reload, :approved?
|
678
|
+
|
679
|
+
@first.approved = false
|
680
|
+
@first.save!
|
681
|
+
Topic.connection.release_savepoint("first")
|
682
|
+
assert_not_predicate @first.reload, :approved?
|
683
|
+
end
|
684
|
+
end if Topic.connection.supports_savepoints?
|
685
|
+
|
686
|
+
def test_releasing_named_savepoints
|
687
|
+
Topic.transaction do
|
688
|
+
Topic.connection.create_savepoint("another")
|
689
|
+
Topic.connection.release_savepoint("another")
|
690
|
+
|
691
|
+
# The savepoint is now gone and we can't remove it again.
|
692
|
+
assert_raises(ActiveRecord::StatementInvalid) do
|
693
|
+
Topic.connection.release_savepoint("another")
|
694
|
+
end
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
def test_savepoints_name
|
699
|
+
Topic.transaction do
|
700
|
+
assert_nil Topic.connection.current_savepoint_name
|
701
|
+
assert_nil Topic.connection.current_transaction.savepoint_name
|
702
|
+
|
703
|
+
Topic.transaction(requires_new: true) do
|
704
|
+
assert_equal "active_record_1", Topic.connection.current_savepoint_name
|
705
|
+
assert_equal "active_record_1", Topic.connection.current_transaction.savepoint_name
|
706
|
+
|
707
|
+
Topic.transaction(requires_new: true) do
|
708
|
+
assert_equal "active_record_2", Topic.connection.current_savepoint_name
|
709
|
+
assert_equal "active_record_2", Topic.connection.current_transaction.savepoint_name
|
710
|
+
end
|
711
|
+
|
712
|
+
assert_equal "active_record_1", Topic.connection.current_savepoint_name
|
713
|
+
assert_equal "active_record_1", Topic.connection.current_transaction.savepoint_name
|
714
|
+
end
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
def test_rollback_when_commit_raises
|
719
|
+
assert_called(Topic.connection, :begin_db_transaction) do
|
720
|
+
Topic.connection.stub(:commit_db_transaction, -> { raise("OH NOES") }) do
|
721
|
+
assert_called(Topic.connection, :rollback_db_transaction) do
|
722
|
+
e = assert_raise RuntimeError do
|
723
|
+
Topic.transaction do
|
724
|
+
Topic.connection.materialize_transactions
|
725
|
+
end
|
726
|
+
end
|
727
|
+
assert_equal "OH NOES", e.message
|
728
|
+
end
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
def test_rollback_when_saving_a_frozen_record
|
734
|
+
topic = Topic.new(title: "test")
|
735
|
+
topic.freeze
|
736
|
+
e = assert_raise(FrozenError) { topic.save }
|
737
|
+
# Not good enough, but we can't do much
|
738
|
+
# about it since there is no specific error
|
739
|
+
# for frozen objects.
|
740
|
+
assert_match(/frozen/i, e.message)
|
741
|
+
assert_not topic.persisted?, "not persisted"
|
742
|
+
assert_nil topic.id
|
743
|
+
assert topic.frozen?, "not frozen"
|
744
|
+
end
|
745
|
+
|
746
|
+
def test_rollback_when_thread_killed
|
747
|
+
return if in_memory_db?
|
748
|
+
|
749
|
+
queue = Queue.new
|
750
|
+
thread = Thread.new do
|
751
|
+
Topic.transaction do
|
752
|
+
@first.approved = true
|
753
|
+
@second.approved = false
|
754
|
+
@first.save
|
755
|
+
|
756
|
+
queue.push nil
|
757
|
+
sleep
|
758
|
+
|
759
|
+
@second.save
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
queue.pop
|
764
|
+
thread.kill
|
765
|
+
thread.join
|
766
|
+
|
767
|
+
assert @first.approved?, "First should still be changed in the objects"
|
768
|
+
assert_not @second.approved?, "Second should still be changed in the objects"
|
769
|
+
|
770
|
+
assert_not Topic.find(1).approved?, "First shouldn't have been approved"
|
771
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
772
|
+
end
|
773
|
+
|
774
|
+
def test_restore_active_record_state_for_all_records_in_a_transaction
|
775
|
+
topic_without_callbacks = Class.new(ActiveRecord::Base) do
|
776
|
+
self.table_name = "topics"
|
777
|
+
end
|
778
|
+
|
779
|
+
topic_1 = Topic.new(title: "test_1")
|
780
|
+
topic_2 = Topic.new(title: "test_2")
|
781
|
+
topic_3 = topic_without_callbacks.new(title: "test_3")
|
782
|
+
|
783
|
+
Topic.transaction do
|
784
|
+
assert topic_1.save
|
785
|
+
assert topic_2.save
|
786
|
+
assert topic_3.save
|
787
|
+
@first.save
|
788
|
+
@second.destroy
|
789
|
+
assert topic_1.persisted?, "persisted"
|
790
|
+
assert_not_nil topic_1.id
|
791
|
+
assert topic_2.persisted?, "persisted"
|
792
|
+
assert_not_nil topic_2.id
|
793
|
+
assert topic_3.persisted?, "persisted"
|
794
|
+
assert_not_nil topic_3.id
|
795
|
+
assert @first.persisted?, "persisted"
|
796
|
+
assert_not_nil @first.id
|
797
|
+
assert @second.destroyed?, "destroyed"
|
798
|
+
raise ActiveRecord::Rollback
|
799
|
+
end
|
800
|
+
|
801
|
+
assert_not topic_1.persisted?, "not persisted"
|
802
|
+
assert_nil topic_1.id
|
803
|
+
assert_not topic_2.persisted?, "not persisted"
|
804
|
+
assert_nil topic_2.id
|
805
|
+
assert_not topic_3.persisted?, "not persisted"
|
806
|
+
assert_nil topic_3.id
|
807
|
+
assert @first.persisted?, "persisted"
|
808
|
+
assert_not_nil @first.id
|
809
|
+
assert_not @second.destroyed?, "not destroyed"
|
810
|
+
end
|
811
|
+
|
812
|
+
def test_restore_frozen_state_after_double_destroy
|
813
|
+
topic = Topic.create
|
814
|
+
reply = topic.replies.create
|
815
|
+
|
816
|
+
Topic.transaction do
|
817
|
+
topic.destroy # calls #destroy on reply (since dependent: destroy)
|
818
|
+
reply.destroy
|
819
|
+
|
820
|
+
raise ActiveRecord::Rollback
|
821
|
+
end
|
822
|
+
|
823
|
+
assert_not_predicate reply, :frozen?
|
824
|
+
assert_not_predicate topic, :frozen?
|
825
|
+
end
|
826
|
+
|
827
|
+
def test_restore_new_record_after_double_save
|
828
|
+
topic = Topic.new
|
829
|
+
|
830
|
+
Topic.transaction do
|
831
|
+
topic.save!
|
832
|
+
topic.save!
|
833
|
+
raise ActiveRecord::Rollback
|
834
|
+
end
|
835
|
+
|
836
|
+
assert_nil topic.id
|
837
|
+
assert_predicate topic, :new_record?
|
838
|
+
end
|
839
|
+
|
840
|
+
def test_dont_restore_new_record_in_subsequent_transaction
|
841
|
+
topic = Topic.new
|
842
|
+
|
843
|
+
Topic.transaction do
|
844
|
+
topic.save!
|
845
|
+
topic.save!
|
846
|
+
end
|
847
|
+
|
848
|
+
Topic.transaction do
|
849
|
+
topic.save!
|
850
|
+
raise ActiveRecord::Rollback
|
851
|
+
end
|
852
|
+
|
853
|
+
assert_predicate topic, :persisted?
|
854
|
+
assert_not_predicate topic, :new_record?
|
855
|
+
end
|
856
|
+
|
857
|
+
def test_restore_previously_new_record_after_double_save
|
858
|
+
topic = Topic.create!
|
859
|
+
|
860
|
+
Topic.transaction do
|
861
|
+
topic.save!
|
862
|
+
topic.save!
|
863
|
+
raise ActiveRecord::Rollback
|
864
|
+
end
|
865
|
+
|
866
|
+
assert_predicate topic, :previously_new_record?
|
867
|
+
end
|
868
|
+
|
869
|
+
def test_restore_id_after_rollback
|
870
|
+
topic = Topic.new
|
871
|
+
|
872
|
+
Topic.transaction do
|
873
|
+
topic.save!
|
874
|
+
raise ActiveRecord::Rollback
|
875
|
+
end
|
876
|
+
|
877
|
+
assert_nil topic.id
|
878
|
+
end
|
879
|
+
|
880
|
+
def test_restore_custom_primary_key_after_rollback
|
881
|
+
movie = Movie.new(name: "foo")
|
882
|
+
|
883
|
+
Movie.transaction do
|
884
|
+
movie.save!
|
885
|
+
raise ActiveRecord::Rollback
|
886
|
+
end
|
887
|
+
|
888
|
+
assert_nil movie.movieid
|
889
|
+
end
|
890
|
+
|
891
|
+
def test_assign_id_after_rollback
|
892
|
+
topic = Topic.create!
|
893
|
+
|
894
|
+
Topic.transaction do
|
895
|
+
topic.save!
|
896
|
+
raise ActiveRecord::Rollback
|
897
|
+
end
|
898
|
+
|
899
|
+
topic.id = nil
|
900
|
+
assert_nil topic.id
|
901
|
+
end
|
902
|
+
|
903
|
+
def test_assign_custom_primary_key_after_rollback
|
904
|
+
movie = Movie.create!(name: "foo")
|
905
|
+
|
906
|
+
Movie.transaction do
|
907
|
+
movie.save!
|
908
|
+
raise ActiveRecord::Rollback
|
909
|
+
end
|
910
|
+
|
911
|
+
movie.movieid = nil
|
912
|
+
assert_nil movie.movieid
|
913
|
+
end
|
914
|
+
|
915
|
+
def test_read_attribute_after_rollback
|
916
|
+
topic = Topic.new
|
917
|
+
|
918
|
+
Topic.transaction do
|
919
|
+
topic.save!
|
920
|
+
raise ActiveRecord::Rollback
|
921
|
+
end
|
922
|
+
|
923
|
+
assert_nil topic.read_attribute(:id)
|
924
|
+
end
|
925
|
+
|
926
|
+
def test_read_attribute_with_custom_primary_key_after_rollback
|
927
|
+
movie = Movie.new(name: "foo")
|
928
|
+
|
929
|
+
Movie.transaction do
|
930
|
+
movie.save!
|
931
|
+
raise ActiveRecord::Rollback
|
932
|
+
end
|
933
|
+
|
934
|
+
assert_nil movie.read_attribute(:movieid)
|
935
|
+
end
|
936
|
+
|
937
|
+
def test_write_attribute_after_rollback
|
938
|
+
topic = Topic.create!
|
939
|
+
|
940
|
+
Topic.transaction do
|
941
|
+
topic.save!
|
942
|
+
raise ActiveRecord::Rollback
|
943
|
+
end
|
944
|
+
|
945
|
+
topic.write_attribute(:id, nil)
|
946
|
+
assert_nil topic.id
|
947
|
+
end
|
948
|
+
|
949
|
+
def test_write_attribute_with_custom_primary_key_after_rollback
|
950
|
+
movie = Movie.create!(name: "foo")
|
951
|
+
|
952
|
+
Movie.transaction do
|
953
|
+
movie.save!
|
954
|
+
raise ActiveRecord::Rollback
|
955
|
+
end
|
956
|
+
|
957
|
+
movie.write_attribute(:movieid, nil)
|
958
|
+
assert_nil movie.movieid
|
959
|
+
end
|
960
|
+
|
961
|
+
def test_rollback_of_frozen_records
|
962
|
+
topic = Topic.create.freeze
|
963
|
+
Topic.transaction do
|
964
|
+
topic.destroy
|
965
|
+
raise ActiveRecord::Rollback
|
966
|
+
end
|
967
|
+
assert topic.frozen?, "frozen"
|
968
|
+
end
|
969
|
+
|
970
|
+
def test_rollback_for_freshly_persisted_records
|
971
|
+
topic = Topic.create
|
972
|
+
Topic.transaction do
|
973
|
+
topic.destroy
|
974
|
+
raise ActiveRecord::Rollback
|
975
|
+
end
|
976
|
+
assert topic.persisted?, "persisted"
|
977
|
+
end
|
978
|
+
|
979
|
+
def test_sqlite_add_column_in_transaction
|
980
|
+
return true unless current_adapter?(:SQLite3Adapter)
|
981
|
+
|
982
|
+
# Test first if column creation/deletion works correctly when no
|
983
|
+
# transaction is in place.
|
984
|
+
#
|
985
|
+
# We go back to the connection for the column queries because
|
986
|
+
# Topic.columns is cached and won't report changes to the DB
|
987
|
+
|
988
|
+
assert_nothing_raised do
|
989
|
+
Topic.reset_column_information
|
990
|
+
Topic.connection.add_column("topics", "stuff", :string)
|
991
|
+
assert_includes Topic.column_names, "stuff"
|
992
|
+
|
993
|
+
Topic.reset_column_information
|
994
|
+
Topic.connection.remove_column("topics", "stuff")
|
995
|
+
assert_not_includes Topic.column_names, "stuff"
|
996
|
+
end
|
997
|
+
|
998
|
+
if Topic.connection.supports_ddl_transactions?
|
999
|
+
assert_nothing_raised do
|
1000
|
+
Topic.transaction { Topic.connection.add_column("topics", "stuff", :string) }
|
1001
|
+
end
|
1002
|
+
else
|
1003
|
+
Topic.transaction do
|
1004
|
+
assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column("topics", "stuff", :string) }
|
1005
|
+
raise ActiveRecord::Rollback
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
ensure
|
1009
|
+
begin
|
1010
|
+
Topic.connection.remove_column("topics", "stuff")
|
1011
|
+
rescue
|
1012
|
+
ensure
|
1013
|
+
Topic.reset_column_information
|
1014
|
+
end
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
def test_transactions_state_from_rollback
|
1018
|
+
connection = Topic.connection
|
1019
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
1020
|
+
|
1021
|
+
assert_predicate transaction, :open?
|
1022
|
+
assert_not_predicate transaction.state, :rolledback?
|
1023
|
+
assert_not_predicate transaction.state, :committed?
|
1024
|
+
|
1025
|
+
transaction.rollback
|
1026
|
+
|
1027
|
+
assert_predicate transaction.state, :rolledback?
|
1028
|
+
assert_not_predicate transaction.state, :committed?
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
def test_transactions_state_from_commit
|
1032
|
+
connection = Topic.connection
|
1033
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
1034
|
+
|
1035
|
+
assert_predicate transaction, :open?
|
1036
|
+
assert_not_predicate transaction.state, :rolledback?
|
1037
|
+
assert_not_predicate transaction.state, :committed?
|
1038
|
+
|
1039
|
+
transaction.commit
|
1040
|
+
|
1041
|
+
assert_not_predicate transaction.state, :rolledback?
|
1042
|
+
assert_predicate transaction.state, :committed?
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def test_mark_transaction_state_as_committed
|
1046
|
+
connection = Topic.connection
|
1047
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
1048
|
+
|
1049
|
+
transaction.rollback
|
1050
|
+
|
1051
|
+
assert_equal :committed, transaction.state.commit!
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
def test_mark_transaction_state_as_rolledback
|
1055
|
+
connection = Topic.connection
|
1056
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
1057
|
+
|
1058
|
+
transaction.commit
|
1059
|
+
|
1060
|
+
assert_equal :rolledback, transaction.state.rollback!
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
def test_mark_transaction_state_as_nil
|
1064
|
+
connection = Topic.connection
|
1065
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
1066
|
+
|
1067
|
+
transaction.commit
|
1068
|
+
|
1069
|
+
assert_nil transaction.state.nullify!
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
def test_transaction_rollback_with_primarykeyless_tables
|
1073
|
+
connection = ActiveRecord::Base.connection
|
1074
|
+
connection.create_table(:transaction_without_primary_keys, force: true, id: false) do |t|
|
1075
|
+
t.integer :thing_id
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
klass = Class.new(ActiveRecord::Base) do
|
1079
|
+
self.table_name = "transaction_without_primary_keys"
|
1080
|
+
after_commit { } # necessary to trigger the has_transactional_callbacks branch
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
assert_no_difference(-> { klass.count }) do
|
1084
|
+
ActiveRecord::Base.transaction do
|
1085
|
+
klass.create!
|
1086
|
+
raise ActiveRecord::Rollback
|
1087
|
+
end
|
1088
|
+
end
|
1089
|
+
ensure
|
1090
|
+
connection.drop_table "transaction_without_primary_keys", if_exists: true
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
def test_empty_transaction_is_not_materialized
|
1094
|
+
assert_no_queries do
|
1095
|
+
Topic.transaction { }
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
def test_unprepared_statement_materializes_transaction
|
1100
|
+
assert_sql(/BEGIN/i, /COMMIT/i) do
|
1101
|
+
Topic.transaction { Topic.where("1=1").first }
|
1102
|
+
end
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
if ActiveRecord::Base.connection.prepared_statements
|
1106
|
+
def test_prepared_statement_materializes_transaction
|
1107
|
+
Topic.first
|
1108
|
+
|
1109
|
+
assert_sql(/BEGIN/i, /COMMIT/i) do
|
1110
|
+
Topic.transaction { Topic.first }
|
1111
|
+
end
|
1112
|
+
end
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
def test_savepoint_does_not_materialize_transaction
|
1116
|
+
assert_no_queries do
|
1117
|
+
Topic.transaction do
|
1118
|
+
Topic.transaction(requires_new: true) { }
|
1119
|
+
end
|
1120
|
+
end
|
1121
|
+
end
|
1122
|
+
|
1123
|
+
def test_raising_does_not_materialize_transaction
|
1124
|
+
assert_raise(RuntimeError) do
|
1125
|
+
assert_no_queries do
|
1126
|
+
Topic.transaction { raise }
|
1127
|
+
end
|
1128
|
+
end
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
def test_accessing_raw_connection_materializes_transaction
|
1132
|
+
assert_sql(/BEGIN/i, /COMMIT/i) do
|
1133
|
+
Topic.transaction { Topic.connection.raw_connection }
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
def test_accessing_raw_connection_disables_lazy_transactions
|
1138
|
+
Topic.connection.raw_connection
|
1139
|
+
|
1140
|
+
assert_sql(/BEGIN/i, /COMMIT/i) do
|
1141
|
+
Topic.transaction { }
|
1142
|
+
end
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
def test_checking_in_connection_reenables_lazy_transactions
|
1146
|
+
connection = Topic.connection_pool.checkout
|
1147
|
+
connection.raw_connection
|
1148
|
+
Topic.connection_pool.checkin connection
|
1149
|
+
|
1150
|
+
assert_no_queries do
|
1151
|
+
connection.transaction { }
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
def test_transactions_can_be_manually_materialized
|
1156
|
+
assert_sql(/BEGIN/i, /COMMIT/i) do
|
1157
|
+
Topic.transaction do
|
1158
|
+
Topic.connection.materialize_transactions
|
1159
|
+
end
|
1160
|
+
end
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
private
|
1164
|
+
%w(validation save destroy).each do |filter|
|
1165
|
+
define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do |topic|
|
1166
|
+
meta = class << topic; self; end
|
1167
|
+
meta.define_method "before_#{filter}_for_transaction" do
|
1168
|
+
Book.create
|
1169
|
+
throw(:abort)
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase
|
1176
|
+
self.use_transactional_tests = true
|
1177
|
+
fixtures :topics
|
1178
|
+
|
1179
|
+
def test_automatic_savepoint_in_outer_transaction
|
1180
|
+
@first = Topic.find(1)
|
1181
|
+
|
1182
|
+
begin
|
1183
|
+
Topic.transaction do
|
1184
|
+
@first.approved = true
|
1185
|
+
@first.save!
|
1186
|
+
raise
|
1187
|
+
end
|
1188
|
+
rescue
|
1189
|
+
assert_not_predicate @first.reload, :approved?
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
def test_no_automatic_savepoint_for_inner_transaction
|
1194
|
+
@first = Topic.find(1)
|
1195
|
+
|
1196
|
+
Topic.transaction do
|
1197
|
+
@first.approved = true
|
1198
|
+
@first.save!
|
1199
|
+
|
1200
|
+
begin
|
1201
|
+
Topic.transaction do
|
1202
|
+
@first.approved = false
|
1203
|
+
@first.save!
|
1204
|
+
raise
|
1205
|
+
end
|
1206
|
+
rescue
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
assert_not_predicate @first.reload, :approved?
|
1211
|
+
end
|
1212
|
+
end if Topic.connection.supports_savepoints?
|
1213
|
+
|
1214
|
+
if ActiveRecord::Base.connection.supports_transaction_isolation? && !current_adapter?(:SQLite3Adapter)
|
1215
|
+
class ConcurrentTransactionTest < TransactionTest
|
1216
|
+
# This will cause transactions to overlap and fail unless they are performed on
|
1217
|
+
# separate database connections.
|
1218
|
+
def test_transaction_per_thread
|
1219
|
+
threads = 3.times.map do
|
1220
|
+
Thread.new do
|
1221
|
+
Topic.transaction do
|
1222
|
+
topic = Topic.find(1)
|
1223
|
+
topic.approved = !topic.approved?
|
1224
|
+
assert topic.save!
|
1225
|
+
topic.approved = !topic.approved?
|
1226
|
+
assert topic.save!
|
1227
|
+
end
|
1228
|
+
Topic.connection.close
|
1229
|
+
end
|
1230
|
+
end
|
1231
|
+
|
1232
|
+
threads.each(&:join)
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
# Test for dirty reads among simultaneous transactions.
|
1236
|
+
def test_transaction_isolation__read_committed
|
1237
|
+
# Should be invariant.
|
1238
|
+
original_salary = Developer.find(1).salary
|
1239
|
+
temporary_salary = 200000
|
1240
|
+
|
1241
|
+
assert_nothing_raised do
|
1242
|
+
threads = (1..3).map do
|
1243
|
+
Thread.new do
|
1244
|
+
Developer.transaction do
|
1245
|
+
# Expect original salary.
|
1246
|
+
dev = Developer.find(1)
|
1247
|
+
assert_equal original_salary, dev.salary
|
1248
|
+
|
1249
|
+
dev.salary = temporary_salary
|
1250
|
+
dev.save!
|
1251
|
+
|
1252
|
+
# Expect temporary salary.
|
1253
|
+
dev = Developer.find(1)
|
1254
|
+
assert_equal temporary_salary, dev.salary
|
1255
|
+
|
1256
|
+
dev.salary = original_salary
|
1257
|
+
dev.save!
|
1258
|
+
|
1259
|
+
# Expect original salary.
|
1260
|
+
dev = Developer.find(1)
|
1261
|
+
assert_equal original_salary, dev.salary
|
1262
|
+
end
|
1263
|
+
Developer.connection.close
|
1264
|
+
end
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
# Keep our eyes peeled.
|
1268
|
+
threads << Thread.new do
|
1269
|
+
10.times do
|
1270
|
+
sleep 0.05
|
1271
|
+
Developer.transaction do
|
1272
|
+
# Always expect original salary.
|
1273
|
+
assert_equal original_salary, Developer.find(1).salary
|
1274
|
+
end
|
1275
|
+
end
|
1276
|
+
Developer.connection.close
|
1277
|
+
end
|
1278
|
+
|
1279
|
+
threads.each(&:join)
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
assert_equal original_salary, Developer.find(1).salary
|
1283
|
+
end
|
1284
|
+
end
|
1285
|
+
end
|