ibm_db 3.0.5-x86-mingw32 → 4.0.0-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 +4 -0
- data/LICENSE +1 -1
- data/MANIFEST +14 -14
- data/ParameterizedQueries README +6 -6
- data/README +208 -225
- data/ext/Makefile.nt32 +181 -181
- data/ext/Makefile.nt32.191 +212 -212
- data/ext/extconf.rb +291 -291
- data/ext/ibm_db.c +11887 -11887
- data/ext/ruby_ibm_db.h +241 -241
- data/ext/ruby_ibm_db_cli.c +866 -866
- data/ext/ruby_ibm_db_cli.h +500 -500
- data/init.rb +41 -41
- data/lib/IBM_DB.rb +27 -27
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
- data/lib/mswin32/ibm_db.rb +91 -123
- data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
- data/test/assets/example.log +1 -1
- data/test/assets/test.txt +1 -1
- data/test/cases/adapter_test.rb +351 -276
- data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
- data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
- data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
- data/test/cases/adapters/mysql2/connection_test.rb +210 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
- data/test/cases/adapters/mysql2/enum_test.rb +26 -0
- data/test/cases/adapters/mysql2/explain_test.rb +21 -0
- data/test/cases/adapters/mysql2/json_test.rb +195 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
- data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
- data/test/cases/adapters/mysql2/schema_test.rb +126 -0
- data/test/cases/adapters/mysql2/sp_test.rb +36 -0
- data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
- data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
- data/test/cases/adapters/postgresql/array_test.rb +339 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
- data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
- data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
- data/test/cases/adapters/postgresql/citext_test.rb +78 -0
- data/test/cases/adapters/postgresql/collation_test.rb +53 -0
- data/test/cases/adapters/postgresql/composite_test.rb +132 -0
- data/test/cases/adapters/postgresql/connection_test.rb +257 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
- data/test/cases/adapters/postgresql/domain_test.rb +47 -0
- data/test/cases/adapters/postgresql/enum_test.rb +91 -0
- data/test/cases/adapters/postgresql/explain_test.rb +20 -0
- data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
- data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
- data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
- data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
- data/test/cases/adapters/postgresql/integer_test.rb +25 -0
- data/test/cases/adapters/postgresql/json_test.rb +237 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
- data/test/cases/adapters/postgresql/money_test.rb +96 -0
- data/test/cases/adapters/postgresql/network_test.rb +94 -0
- data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
- data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
- data/test/cases/adapters/postgresql/range_test.rb +343 -0
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
- data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
- data/test/cases/adapters/postgresql/schema_test.rb +597 -0
- data/test/cases/adapters/postgresql/serial_test.rb +154 -0
- data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
- data/test/cases/adapters/postgresql/utils_test.rb +62 -0
- data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
- data/test/cases/adapters/postgresql/xml_test.rb +54 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
- data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
- data/test/cases/aggregations_test.rb +168 -158
- data/test/cases/ar_schema_test.rb +146 -161
- data/test/cases/associations/association_scope_test.rb +16 -21
- data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
- data/test/cases/associations/callbacks_test.rb +190 -192
- data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
- data/test/cases/associations/eager_singularization_test.rb +148 -148
- data/test/cases/associations/eager_test.rb +1514 -1429
- data/test/cases/associations/extension_test.rb +87 -82
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
- data/test/cases/associations/has_many_associations_test.rb +2501 -2182
- data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
- data/test/cases/associations/has_one_associations_test.rb +707 -610
- data/test/cases/associations/has_one_through_associations_test.rb +383 -380
- data/test/cases/associations/inner_join_association_test.rb +139 -139
- data/test/cases/associations/inverse_associations_test.rb +733 -706
- data/test/cases/associations/join_model_test.rb +777 -754
- data/test/cases/associations/left_outer_join_association_test.rb +88 -0
- data/test/cases/associations/nested_through_associations_test.rb +579 -579
- data/test/cases/associations/required_test.rb +102 -82
- data/test/cases/associations_test.rb +385 -380
- data/test/cases/attribute_decorators_test.rb +125 -125
- data/test/cases/attribute_methods/read_test.rb +60 -60
- data/test/cases/attribute_methods_test.rb +1009 -952
- data/test/cases/attribute_set_test.rb +270 -210
- data/test/cases/attribute_test.rb +246 -180
- data/test/cases/attributes_test.rb +253 -136
- data/test/cases/autosave_association_test.rb +1708 -1595
- data/test/cases/base_test.rb +1713 -1664
- data/test/cases/batches_test.rb +489 -212
- data/test/cases/binary_test.rb +44 -52
- data/test/cases/bind_parameter_test.rb +110 -100
- data/test/cases/cache_key_test.rb +25 -0
- data/test/cases/calculations_test.rb +798 -646
- data/test/cases/callbacks_test.rb +636 -543
- data/test/cases/clone_test.rb +40 -40
- data/test/cases/coders/json_test.rb +15 -0
- data/test/cases/coders/yaml_column_test.rb +63 -63
- data/test/cases/collection_cache_key_test.rb +115 -0
- data/test/cases/column_alias_test.rb +17 -17
- data/test/cases/column_definition_test.rb +92 -123
- data/test/cases/comment_test.rb +143 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
- data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
- data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
- data/test/cases/connection_adapters/quoting_test.rb +13 -13
- data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
- data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
- data/test/cases/connection_management_test.rb +112 -122
- data/test/cases/connection_pool_test.rb +521 -346
- data/test/cases/connection_specification/resolver_test.rb +131 -116
- data/test/cases/core_test.rb +112 -112
- data/test/cases/counter_cache_test.rb +214 -209
- data/test/cases/custom_locking_test.rb +17 -17
- data/test/cases/database_statements_test.rb +34 -19
- data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
- data/test/cases/date_time_precision_test.rb +106 -0
- data/test/cases/date_time_test.rb +61 -61
- data/test/cases/defaults_test.rb +218 -223
- data/test/cases/dirty_test.rb +763 -785
- data/test/cases/disconnected_test.rb +30 -28
- data/test/cases/dup_test.rb +157 -157
- data/test/cases/enum_test.rb +444 -290
- data/test/cases/errors_test.rb +16 -0
- data/test/cases/explain_subscriber_test.rb +64 -64
- data/test/cases/explain_test.rb +87 -76
- data/test/cases/finder_respond_to_test.rb +60 -60
- data/test/cases/finder_test.rb +1294 -1169
- data/test/cases/fixture_set/file_test.rb +156 -138
- data/test/cases/fixtures_test.rb +988 -908
- data/test/cases/forbidden_attributes_protection_test.rb +165 -99
- data/test/cases/habtm_destroy_order_test.rb +61 -61
- data/test/cases/helper.rb +204 -210
- data/test/cases/hot_compatibility_test.rb +142 -54
- data/test/cases/i18n_test.rb +45 -45
- data/test/cases/inheritance_test.rb +606 -375
- data/test/cases/integration_test.rb +155 -139
- data/test/cases/invalid_connection_test.rb +24 -22
- data/test/cases/invertible_migration_test.rb +387 -295
- data/test/cases/json_serialization_test.rb +311 -302
- data/test/cases/locking_test.rb +493 -477
- data/test/cases/log_subscriber_test.rb +225 -136
- data/test/cases/migration/change_schema_test.rb +458 -512
- data/test/cases/migration/change_table_test.rb +256 -224
- data/test/cases/migration/column_attributes_test.rb +176 -192
- data/test/cases/migration/column_positioning_test.rb +56 -56
- data/test/cases/migration/columns_test.rb +310 -304
- data/test/cases/migration/command_recorder_test.rb +350 -305
- data/test/cases/migration/compatibility_test.rb +118 -0
- data/test/cases/migration/create_join_table_test.rb +157 -148
- data/test/cases/migration/foreign_key_test.rb +360 -328
- data/test/cases/migration/helper.rb +39 -39
- data/test/cases/migration/index_test.rb +218 -216
- data/test/cases/migration/logger_test.rb +36 -36
- data/test/cases/migration/pending_migrations_test.rb +52 -53
- data/test/cases/migration/references_foreign_key_test.rb +216 -169
- data/test/cases/migration/references_index_test.rb +101 -101
- data/test/cases/migration/references_statements_test.rb +136 -116
- data/test/cases/migration/rename_table_test.rb +93 -93
- data/test/cases/migration_test.rb +1157 -959
- data/test/cases/migrator_test.rb +470 -388
- data/test/cases/mixin_test.rb +68 -70
- data/test/cases/modules_test.rb +172 -173
- data/test/cases/multiparameter_attributes_test.rb +372 -350
- data/test/cases/multiple_db_test.rb +122 -115
- data/test/cases/nested_attributes_test.rb +1098 -1070
- data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
- data/test/cases/persistence_test.rb +1001 -909
- data/test/cases/pooled_connections_test.rb +81 -81
- data/test/cases/primary_keys_test.rb +376 -237
- data/test/cases/query_cache_test.rb +446 -326
- data/test/cases/quoting_test.rb +202 -156
- data/test/cases/readonly_test.rb +119 -118
- data/test/cases/reaper_test.rb +85 -85
- data/test/cases/reflection_test.rb +509 -463
- data/test/cases/relation/delegation_test.rb +63 -68
- data/test/cases/relation/merging_test.rb +157 -161
- data/test/cases/relation/mutation_test.rb +183 -165
- data/test/cases/relation/or_test.rb +92 -0
- data/test/cases/relation/predicate_builder_test.rb +16 -14
- data/test/cases/relation/record_fetch_warning_test.rb +40 -0
- data/test/cases/relation/where_chain_test.rb +105 -181
- data/test/cases/relation/where_clause_test.rb +182 -0
- data/test/cases/relation/where_test.rb +322 -300
- data/test/cases/relation_test.rb +328 -319
- data/test/cases/relations_test.rb +2026 -1815
- data/test/cases/reload_models_test.rb +22 -22
- data/test/cases/result_test.rb +90 -80
- data/test/cases/sanitize_test.rb +176 -83
- data/test/cases/schema_dumper_test.rb +457 -463
- data/test/cases/schema_loading_test.rb +52 -0
- data/test/cases/scoping/default_scoping_test.rb +528 -454
- data/test/cases/scoping/named_scoping_test.rb +561 -524
- data/test/cases/scoping/relation_scoping_test.rb +400 -357
- data/test/cases/secure_token_test.rb +32 -0
- data/test/cases/serialization_test.rb +104 -104
- data/test/cases/serialized_attribute_test.rb +364 -277
- data/test/cases/statement_cache_test.rb +136 -98
- data/test/cases/store_test.rb +195 -194
- data/test/cases/suppressor_test.rb +63 -0
- data/test/cases/tasks/database_tasks_test.rb +462 -398
- data/test/cases/tasks/mysql_rake_test.rb +345 -324
- data/test/cases/tasks/postgresql_rake_test.rb +304 -250
- data/test/cases/tasks/sqlite_rake_test.rb +220 -193
- data/test/cases/test_case.rb +131 -123
- data/test/cases/test_fixtures_test.rb +36 -0
- data/test/cases/time_precision_test.rb +102 -0
- data/test/cases/timestamp_test.rb +501 -467
- data/test/cases/touch_later_test.rb +121 -0
- data/test/cases/transaction_callbacks_test.rb +518 -452
- data/test/cases/transaction_isolation_test.rb +106 -106
- data/test/cases/transactions_test.rb +834 -817
- data/test/cases/type/adapter_specific_registry_test.rb +133 -0
- data/test/cases/type/date_time_test.rb +14 -0
- data/test/cases/type/integer_test.rb +27 -121
- data/test/cases/type/string_test.rb +22 -36
- data/test/cases/type/type_map_test.rb +177 -177
- data/test/cases/type_test.rb +39 -0
- data/test/cases/types_test.rb +24 -141
- data/test/cases/unconnected_test.rb +33 -33
- data/test/cases/validations/absence_validation_test.rb +73 -0
- data/test/cases/validations/association_validation_test.rb +97 -86
- data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
- data/test/cases/validations/i18n_validation_test.rb +86 -90
- data/test/cases/validations/length_validation_test.rb +79 -47
- data/test/cases/validations/presence_validation_test.rb +103 -68
- data/test/cases/validations/uniqueness_validation_test.rb +548 -457
- data/test/cases/validations_repair_helper.rb +19 -23
- data/test/cases/validations_test.rb +194 -165
- data/test/cases/view_test.rb +216 -119
- data/test/cases/yaml_serialization_test.rb +121 -126
- data/test/config.example.yml +97 -0
- data/test/config.rb +5 -5
- data/test/fixtures/accounts.yml +29 -29
- data/test/fixtures/admin/accounts.yml +2 -2
- data/test/fixtures/admin/users.yml +10 -10
- data/test/fixtures/author_addresses.original +11 -0
- data/test/fixtures/author_addresses.yml +17 -17
- data/test/fixtures/author_favorites.yml +3 -3
- data/test/fixtures/authors.original +17 -0
- data/test/fixtures/authors.yml +23 -23
- data/test/fixtures/bad_posts.yml +9 -0
- data/test/fixtures/binaries.yml +133 -133
- data/test/fixtures/books.yml +31 -11
- data/test/fixtures/bulbs.yml +5 -5
- data/test/fixtures/cars.yml +9 -9
- data/test/fixtures/categories.yml +19 -19
- data/test/fixtures/categories/special_categories.yml +9 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
- data/test/fixtures/categories_ordered.yml +7 -7
- data/test/fixtures/categories_posts.yml +31 -31
- data/test/fixtures/categorizations.yml +23 -23
- data/test/fixtures/clubs.yml +8 -8
- data/test/fixtures/collections.yml +3 -3
- data/test/fixtures/colleges.yml +3 -3
- data/test/fixtures/comments.yml +65 -65
- data/test/fixtures/companies.yml +67 -67
- data/test/fixtures/computers.yml +10 -10
- data/test/fixtures/content.yml +3 -0
- data/test/fixtures/content_positions.yml +3 -0
- data/test/fixtures/courses.yml +8 -8
- data/test/fixtures/customers.yml +25 -25
- data/test/fixtures/dashboards.yml +6 -6
- data/test/fixtures/dead_parrots.yml +5 -0
- data/test/fixtures/developers.yml +22 -22
- data/test/fixtures/developers_projects.yml +16 -16
- data/test/fixtures/dog_lovers.yml +7 -7
- data/test/fixtures/dogs.yml +4 -4
- data/test/fixtures/doubloons.yml +3 -3
- data/test/fixtures/edges.yml +5 -5
- data/test/fixtures/entrants.yml +14 -14
- data/test/fixtures/essays.yml +6 -6
- data/test/fixtures/faces.yml +11 -11
- data/test/fixtures/fk_test_has_fk.yml +3 -3
- data/test/fixtures/fk_test_has_pk.yml +1 -1
- data/test/fixtures/friendships.yml +4 -4
- data/test/fixtures/funny_jokes.yml +10 -10
- data/test/fixtures/interests.yml +33 -33
- data/test/fixtures/items.yml +3 -3
- data/test/fixtures/jobs.yml +7 -7
- data/test/fixtures/legacy_things.yml +3 -3
- data/test/fixtures/live_parrots.yml +4 -0
- data/test/fixtures/mateys.yml +4 -4
- data/test/fixtures/member_details.yml +8 -8
- data/test/fixtures/member_types.yml +6 -6
- data/test/fixtures/members.yml +11 -11
- data/test/fixtures/memberships.yml +34 -34
- data/test/fixtures/men.yml +5 -5
- data/test/fixtures/minimalistics.yml +2 -2
- data/test/fixtures/minivans.yml +5 -5
- data/test/fixtures/mixed_case_monkeys.yml +6 -6
- data/test/fixtures/mixins.yml +29 -29
- data/test/fixtures/movies.yml +7 -7
- data/test/fixtures/naked/yml/accounts.yml +1 -1
- data/test/fixtures/naked/yml/companies.yml +1 -1
- data/test/fixtures/naked/yml/courses.yml +1 -1
- data/test/fixtures/naked/yml/parrots.yml +2 -0
- data/test/fixtures/naked/yml/trees.yml +3 -0
- data/test/fixtures/nodes.yml +29 -0
- data/test/fixtures/organizations.yml +5 -5
- data/test/fixtures/other_comments.yml +6 -0
- data/test/fixtures/other_dogs.yml +2 -0
- data/test/fixtures/other_posts.yml +7 -0
- data/test/fixtures/other_topics.yml +42 -42
- data/test/fixtures/owners.yml +9 -9
- data/test/fixtures/parrots.yml +27 -27
- data/test/fixtures/parrots_pirates.yml +7 -7
- data/test/fixtures/people.yml +24 -24
- data/test/fixtures/peoples_treasures.yml +3 -3
- data/test/fixtures/pets.yml +19 -19
- data/test/fixtures/pirates.yml +15 -12
- data/test/fixtures/posts.yml +80 -80
- data/test/fixtures/price_estimates.yml +16 -7
- data/test/fixtures/products.yml +4 -4
- data/test/fixtures/projects.yml +7 -7
- data/test/fixtures/ratings.yml +14 -14
- data/test/fixtures/readers.yml +11 -11
- data/test/fixtures/references.yml +17 -17
- data/test/fixtures/reserved_words/distinct.yml +5 -5
- data/test/fixtures/reserved_words/distinct_select.yml +11 -11
- data/test/fixtures/reserved_words/group.yml +14 -14
- data/test/fixtures/reserved_words/select.yml +8 -8
- data/test/fixtures/reserved_words/values.yml +7 -7
- data/test/fixtures/ships.yml +6 -6
- data/test/fixtures/speedometers.yml +8 -8
- data/test/fixtures/sponsors.yml +12 -12
- data/test/fixtures/string_key_objects.yml +7 -7
- data/test/fixtures/subscribers.yml +10 -10
- data/test/fixtures/subscriptions.yml +12 -12
- data/test/fixtures/taggings.yml +78 -78
- data/test/fixtures/tags.yml +11 -11
- data/test/fixtures/tasks.yml +7 -7
- data/test/fixtures/teapots.yml +3 -3
- data/test/fixtures/to_be_linked/accounts.yml +2 -2
- data/test/fixtures/to_be_linked/users.yml +10 -10
- data/test/fixtures/topics.yml +49 -49
- data/test/fixtures/toys.yml +14 -14
- data/test/fixtures/traffic_lights.yml +9 -9
- data/test/fixtures/treasures.yml +10 -10
- data/test/fixtures/trees.yml +3 -0
- data/test/fixtures/uuid_children.yml +3 -3
- data/test/fixtures/uuid_parents.yml +2 -2
- data/test/fixtures/variants.yml +4 -4
- data/test/fixtures/vegetables.yml +19 -19
- data/test/fixtures/vertices.yml +3 -3
- data/test/fixtures/warehouse_things.yml +2 -2
- data/test/fixtures/zines.yml +5 -5
- data/test/migrations/10_urban/9_add_expressions.rb +11 -11
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
- data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
- data/test/migrations/missing/1_people_have_last_names.rb +9 -9
- data/test/migrations/missing/3_we_need_reminders.rb +12 -12
- data/test/migrations/missing/4_innocent_jointable.rb +12 -12
- data/test/migrations/rename/1_we_need_things.rb +11 -11
- data/test/migrations/rename/2_rename_things.rb +9 -9
- data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
- data/test/migrations/to_copy2/1_create_articles.rb +7 -7
- data/test/migrations/to_copy2/2_create_comments.rb +7 -7
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
- data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
- data/test/migrations/valid/2_we_need_reminders.rb +12 -12
- data/test/migrations/valid/3_innocent_jointable.rb +12 -12
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
- data/test/models/admin.rb +5 -5
- data/test/models/admin/account.rb +3 -3
- data/test/models/admin/randomly_named_c1.rb +6 -2
- data/test/models/admin/user.rb +40 -40
- data/test/models/aircraft.rb +5 -4
- data/test/models/arunit2_model.rb +3 -3
- data/test/models/author.rb +209 -212
- data/test/models/auto_id.rb +4 -4
- data/test/models/autoloadable/extra_firm.rb +2 -2
- data/test/models/binary.rb +2 -2
- data/test/models/bird.rb +12 -12
- data/test/models/book.rb +23 -18
- data/test/models/boolean.rb +2 -2
- data/test/models/bulb.rb +52 -51
- data/test/models/cake_designer.rb +3 -3
- data/test/models/car.rb +29 -26
- data/test/models/carrier.rb +2 -2
- data/test/models/cat.rb +10 -0
- data/test/models/categorization.rb +19 -19
- data/test/models/category.rb +35 -35
- data/test/models/chef.rb +8 -7
- data/test/models/citation.rb +3 -3
- data/test/models/club.rb +25 -23
- data/test/models/college.rb +10 -10
- data/test/models/column.rb +3 -3
- data/test/models/column_name.rb +3 -3
- data/test/models/comment.rb +76 -64
- data/test/models/company.rb +230 -228
- data/test/models/company_in_module.rb +98 -98
- data/test/models/computer.rb +3 -3
- data/test/models/contact.rb +41 -41
- data/test/models/content.rb +40 -0
- data/test/models/contract.rb +20 -20
- data/test/models/country.rb +7 -7
- data/test/models/course.rb +6 -6
- data/test/models/customer.rb +83 -77
- data/test/models/customer_carrier.rb +14 -14
- data/test/models/dashboard.rb +3 -3
- data/test/models/default.rb +2 -2
- data/test/models/department.rb +4 -4
- data/test/models/developer.rb +274 -255
- data/test/models/dog.rb +5 -5
- data/test/models/dog_lover.rb +5 -5
- data/test/models/doubloon.rb +12 -12
- data/test/models/drink_designer.rb +3 -3
- data/test/models/edge.rb +5 -5
- data/test/models/electron.rb +5 -5
- data/test/models/engine.rb +4 -4
- data/test/models/entrant.rb +3 -3
- data/test/models/essay.rb +5 -5
- data/test/models/event.rb +3 -3
- data/test/models/eye.rb +37 -37
- data/test/models/face.rb +9 -9
- data/test/models/friendship.rb +6 -6
- data/test/models/guid.rb +2 -2
- data/test/models/guitar.rb +4 -0
- data/test/models/hotel.rb +11 -9
- data/test/models/image.rb +3 -3
- data/test/models/interest.rb +5 -5
- data/test/models/invoice.rb +4 -4
- data/test/models/item.rb +7 -7
- data/test/models/job.rb +7 -7
- data/test/models/joke.rb +7 -7
- data/test/models/keyboard.rb +3 -3
- data/test/models/legacy_thing.rb +3 -3
- data/test/models/lesson.rb +11 -11
- data/test/models/line_item.rb +3 -3
- data/test/models/liquid.rb +4 -4
- data/test/models/man.rb +11 -11
- data/test/models/matey.rb +4 -4
- data/test/models/member.rb +42 -41
- data/test/models/member_detail.rb +8 -7
- data/test/models/member_type.rb +3 -3
- data/test/models/membership.rb +35 -35
- data/test/models/mentor.rb +3 -0
- data/test/models/minimalistic.rb +2 -2
- data/test/models/minivan.rb +9 -9
- data/test/models/mixed_case_monkey.rb +3 -3
- data/test/models/mocktail_designer.rb +2 -0
- data/test/models/molecule.rb +6 -6
- data/test/models/movie.rb +5 -5
- data/test/models/node.rb +5 -0
- data/test/models/non_primary_key.rb +2 -0
- data/test/models/notification.rb +3 -0
- data/test/models/order.rb +4 -4
- data/test/models/organization.rb +14 -14
- data/test/models/other_dog.rb +5 -0
- data/test/models/owner.rb +37 -34
- data/test/models/parrot.rb +28 -29
- data/test/models/person.rb +142 -143
- data/test/models/personal_legacy_thing.rb +4 -4
- data/test/models/pet.rb +18 -15
- data/test/models/pet_treasure.rb +6 -0
- data/test/models/pirate.rb +92 -92
- data/test/models/possession.rb +3 -3
- data/test/models/post.rb +273 -264
- data/test/models/price_estimate.rb +4 -4
- data/test/models/professor.rb +5 -5
- data/test/models/project.rb +40 -31
- data/test/models/publisher.rb +2 -2
- data/test/models/publisher/article.rb +4 -4
- data/test/models/publisher/magazine.rb +3 -3
- data/test/models/randomly_named_c1.rb +1 -1
- data/test/models/rating.rb +4 -4
- data/test/models/reader.rb +23 -23
- data/test/models/recipe.rb +3 -0
- data/test/models/record.rb +2 -2
- data/test/models/reference.rb +22 -22
- data/test/models/reply.rb +61 -61
- data/test/models/ship.rb +39 -33
- data/test/models/ship_part.rb +8 -8
- data/test/models/shop.rb +17 -17
- data/test/models/shop_account.rb +6 -6
- data/test/models/speedometer.rb +6 -6
- data/test/models/sponsor.rb +7 -7
- data/test/models/string_key_object.rb +3 -3
- data/test/models/student.rb +4 -4
- data/test/models/subject.rb +16 -16
- data/test/models/subscriber.rb +8 -8
- data/test/models/subscription.rb +4 -4
- data/test/models/tag.rb +13 -7
- data/test/models/tagging.rb +13 -13
- data/test/models/task.rb +5 -5
- data/test/models/topic.rb +118 -124
- data/test/models/toy.rb +6 -6
- data/test/models/traffic_light.rb +4 -4
- data/test/models/treasure.rb +14 -14
- data/test/models/treaty.rb +7 -7
- data/test/models/tree.rb +3 -0
- data/test/models/tuning_peg.rb +4 -0
- data/test/models/tyre.rb +11 -11
- data/test/models/user.rb +14 -0
- data/test/models/uuid_child.rb +3 -3
- data/test/models/uuid_item.rb +6 -0
- data/test/models/uuid_parent.rb +3 -3
- data/test/models/vegetables.rb +24 -24
- data/test/models/vehicle.rb +6 -6
- data/test/models/vertex.rb +9 -9
- data/test/models/warehouse_thing.rb +5 -5
- data/test/models/wheel.rb +3 -3
- data/test/models/without_table.rb +3 -3
- data/test/models/zine.rb +3 -3
- data/test/schema/mysql2_specific_schema.rb +68 -58
- data/test/schema/oracle_specific_schema.rb +40 -43
- data/test/schema/postgresql_specific_schema.rb +114 -202
- data/test/schema/schema.rb +1057 -952
- data/test/schema/schema.rb.original +1057 -0
- data/test/schema/sqlite_specific_schema.rb +18 -22
- data/test/support/config.rb +43 -43
- data/test/support/connection.rb +23 -22
- data/test/support/connection_helper.rb +14 -14
- data/test/support/ddl_helper.rb +8 -8
- data/test/support/schema_dumping_helper.rb +20 -20
- 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
- metadata +129 -28
- data/lib/mswin32/rb19x/ibm_db.so +0 -0
- data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
- data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
- data/test/cases/attribute_methods/serialization_test.rb +0 -29
- data/test/cases/migration/change_schema_test - Copy.rb +0 -448
- data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
- data/test/cases/migration/table_and_index_test.rb +0 -24
- data/test/cases/relation/where_test2.rb +0 -36
- data/test/cases/type/decimal_test.rb +0 -56
- data/test/cases/type/unsigned_integer_test.rb +0 -18
- data/test/cases/xml_serialization_test.rb +0 -457
- data/test/connections/native_ibm_db/connection.rb +0 -44
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
- data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
- data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
- data/test/schema/mysql_specific_schema.rb +0 -70
- data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,106 +1,106 @@
|
|
1
|
-
require 'cases/helper'
|
2
|
-
|
3
|
-
unless ActiveRecord::Base.connection.supports_transaction_isolation?
|
4
|
-
class TransactionIsolationUnsupportedTest < ActiveRecord::TestCase
|
5
|
-
self.
|
6
|
-
|
7
|
-
class Tag < ActiveRecord::Base
|
8
|
-
end
|
9
|
-
|
10
|
-
test "setting the isolation level raises an error" do
|
11
|
-
assert_raises(ActiveRecord::TransactionIsolationError) do
|
12
|
-
Tag.transaction(isolation: :serializable) { }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
if ActiveRecord::Base.connection.supports_transaction_isolation?
|
19
|
-
class TransactionIsolationTest < ActiveRecord::TestCase
|
20
|
-
self.
|
21
|
-
|
22
|
-
class Tag < ActiveRecord::Base
|
23
|
-
self.table_name = 'tags'
|
24
|
-
end
|
25
|
-
|
26
|
-
class Tag2 < ActiveRecord::Base
|
27
|
-
self.table_name = 'tags'
|
28
|
-
end
|
29
|
-
|
30
|
-
setup do
|
31
|
-
Tag.establish_connection :arunit
|
32
|
-
Tag2.establish_connection :arunit
|
33
|
-
Tag.destroy_all
|
34
|
-
end
|
35
|
-
|
36
|
-
# It is impossible to properly test read uncommitted. The SQL standard only
|
37
|
-
# specifies what must not happen at a certain level, not what must happen. At
|
38
|
-
# the read uncommitted level, there is nothing that must not happen.
|
39
|
-
if ActiveRecord::Base.connection.transaction_isolation_levels.include?(:read_uncommitted)
|
40
|
-
test "read uncommitted" do
|
41
|
-
Tag.transaction(isolation: :read_uncommitted) do
|
42
|
-
assert_equal 0, Tag.count
|
43
|
-
Tag2.create
|
44
|
-
assert_equal 1, Tag.count
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# We are testing that a dirty read does not happen
|
50
|
-
test "read committed" do
|
51
|
-
Tag.transaction(isolation: :read_committed) do
|
52
|
-
assert_equal 0, Tag.count
|
53
|
-
|
54
|
-
Tag2.transaction do
|
55
|
-
Tag2.create
|
56
|
-
assert_equal 0, Tag.count
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
assert_equal 1, Tag.count
|
61
|
-
end
|
62
|
-
|
63
|
-
# We are testing that a nonrepeatable read does not happen
|
64
|
-
if ActiveRecord::Base.connection.transaction_isolation_levels.include?(:repeatable_read)
|
65
|
-
test "repeatable read" do
|
66
|
-
tag = Tag.create(name: 'jon')
|
67
|
-
|
68
|
-
Tag.transaction(isolation: :repeatable_read) do
|
69
|
-
tag.reload
|
70
|
-
Tag2.find(tag.id).update(name: 'emily')
|
71
|
-
|
72
|
-
tag.reload
|
73
|
-
assert_equal 'jon', tag.name
|
74
|
-
end
|
75
|
-
|
76
|
-
tag.reload
|
77
|
-
assert_equal 'emily', tag.name
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# We are only testing that there are no errors because it's too hard to
|
82
|
-
# test serializable. Databases behave differently to enforce the serializability
|
83
|
-
# constraint.
|
84
|
-
test "serializable" do
|
85
|
-
Tag.transaction(isolation: :serializable) do
|
86
|
-
Tag.create
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
test "setting isolation when joining a transaction raises an error" do
|
91
|
-
Tag.transaction do
|
92
|
-
assert_raises(ActiveRecord::TransactionIsolationError) do
|
93
|
-
Tag.transaction(isolation: :serializable) { }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
test "setting isolation when starting a nested transaction raises error" do
|
99
|
-
Tag.transaction do
|
100
|
-
assert_raises(ActiveRecord::TransactionIsolationError) do
|
101
|
-
Tag.transaction(requires_new: true, isolation: :serializable) { }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
1
|
+
require 'cases/helper'
|
2
|
+
|
3
|
+
unless ActiveRecord::Base.connection.supports_transaction_isolation?
|
4
|
+
class TransactionIsolationUnsupportedTest < ActiveRecord::TestCase
|
5
|
+
self.use_transactional_tests = false
|
6
|
+
|
7
|
+
class Tag < ActiveRecord::Base
|
8
|
+
end
|
9
|
+
|
10
|
+
test "setting the isolation level raises an error" do
|
11
|
+
assert_raises(ActiveRecord::TransactionIsolationError) do
|
12
|
+
Tag.transaction(isolation: :serializable) { }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if ActiveRecord::Base.connection.supports_transaction_isolation?
|
19
|
+
class TransactionIsolationTest < ActiveRecord::TestCase
|
20
|
+
self.use_transactional_tests = false
|
21
|
+
|
22
|
+
class Tag < ActiveRecord::Base
|
23
|
+
self.table_name = 'tags'
|
24
|
+
end
|
25
|
+
|
26
|
+
class Tag2 < ActiveRecord::Base
|
27
|
+
self.table_name = 'tags'
|
28
|
+
end
|
29
|
+
|
30
|
+
setup do
|
31
|
+
Tag.establish_connection :arunit
|
32
|
+
Tag2.establish_connection :arunit
|
33
|
+
Tag.destroy_all
|
34
|
+
end
|
35
|
+
|
36
|
+
# It is impossible to properly test read uncommitted. The SQL standard only
|
37
|
+
# specifies what must not happen at a certain level, not what must happen. At
|
38
|
+
# the read uncommitted level, there is nothing that must not happen.
|
39
|
+
if ActiveRecord::Base.connection.transaction_isolation_levels.include?(:read_uncommitted)
|
40
|
+
test "read uncommitted" do
|
41
|
+
Tag.transaction(isolation: :read_uncommitted) do
|
42
|
+
assert_equal 0, Tag.count
|
43
|
+
Tag2.create
|
44
|
+
assert_equal 1, Tag.count
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# We are testing that a dirty read does not happen
|
50
|
+
test "read committed" do
|
51
|
+
Tag.transaction(isolation: :read_committed) do
|
52
|
+
assert_equal 0, Tag.count
|
53
|
+
|
54
|
+
Tag2.transaction do
|
55
|
+
Tag2.create
|
56
|
+
assert_equal 0, Tag.count
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
assert_equal 1, Tag.count
|
61
|
+
end
|
62
|
+
|
63
|
+
# We are testing that a nonrepeatable read does not happen
|
64
|
+
if ActiveRecord::Base.connection.transaction_isolation_levels.include?(:repeatable_read)
|
65
|
+
test "repeatable read" do
|
66
|
+
tag = Tag.create(name: 'jon')
|
67
|
+
|
68
|
+
Tag.transaction(isolation: :repeatable_read) do
|
69
|
+
tag.reload
|
70
|
+
Tag2.find(tag.id).update(name: 'emily')
|
71
|
+
|
72
|
+
tag.reload
|
73
|
+
assert_equal 'jon', tag.name
|
74
|
+
end
|
75
|
+
|
76
|
+
tag.reload
|
77
|
+
assert_equal 'emily', tag.name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# We are only testing that there are no errors because it's too hard to
|
82
|
+
# test serializable. Databases behave differently to enforce the serializability
|
83
|
+
# constraint.
|
84
|
+
test "serializable" do
|
85
|
+
Tag.transaction(isolation: :serializable) do
|
86
|
+
Tag.create
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
test "setting isolation when joining a transaction raises an error" do
|
91
|
+
Tag.transaction do
|
92
|
+
assert_raises(ActiveRecord::TransactionIsolationError) do
|
93
|
+
Tag.transaction(isolation: :serializable) { }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
test "setting isolation when starting a nested transaction raises error" do
|
99
|
+
Tag.transaction do
|
100
|
+
assert_raises(ActiveRecord::TransactionIsolationError) do
|
101
|
+
Tag.transaction(requires_new: true, isolation: :serializable) { }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -1,817 +1,834 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/topic'
|
3
|
-
require 'models/reply'
|
4
|
-
require 'models/developer'
|
5
|
-
require 'models/computer'
|
6
|
-
require 'models/book'
|
7
|
-
require 'models/author'
|
8
|
-
require 'models/post'
|
9
|
-
require 'models/movie'
|
10
|
-
|
11
|
-
class TransactionTest < ActiveRecord::TestCase
|
12
|
-
self.
|
13
|
-
fixtures :topics, :developers, :authors, :posts
|
14
|
-
|
15
|
-
def setup
|
16
|
-
@first, @second = Topic.find(1, 2).sort_by
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_persisted_in_a_model_with_custom_primary_key_after_failed_save
|
20
|
-
movie = Movie.create
|
21
|
-
assert !movie.persisted?
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_raise_after_destroy
|
25
|
-
assert_not @first.frozen?
|
26
|
-
|
27
|
-
assert_raises(RuntimeError) {
|
28
|
-
Topic.transaction do
|
29
|
-
@first.destroy
|
30
|
-
assert @first.frozen?
|
31
|
-
raise
|
32
|
-
end
|
33
|
-
}
|
34
|
-
|
35
|
-
assert @first.reload
|
36
|
-
assert_not @first.frozen?
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_successful
|
40
|
-
Topic.transaction do
|
41
|
-
@first.approved = true
|
42
|
-
@second.approved = false
|
43
|
-
@first.save
|
44
|
-
@second.save
|
45
|
-
end
|
46
|
-
|
47
|
-
assert Topic.find(1).approved?, "First should have been approved"
|
48
|
-
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
49
|
-
end
|
50
|
-
|
51
|
-
def transaction_with_return
|
52
|
-
Topic.transaction do
|
53
|
-
@first.approved = true
|
54
|
-
@second.approved = false
|
55
|
-
@first.save
|
56
|
-
@second.save
|
57
|
-
return
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
author
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
posts_count
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
assert_equal original_author_name, @first.reload.author_name
|
237
|
-
assert_equal nbooks_before_save, Book.count
|
238
|
-
end
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
end
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
assert !
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
assert
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
@first.
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
Topic.
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
Topic.
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
transaction.
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
connection
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
end
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
end
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
require 'models/reply'
|
4
|
+
require 'models/developer'
|
5
|
+
require 'models/computer'
|
6
|
+
require 'models/book'
|
7
|
+
require 'models/author'
|
8
|
+
require 'models/post'
|
9
|
+
require 'models/movie'
|
10
|
+
|
11
|
+
class TransactionTest < ActiveRecord::TestCase
|
12
|
+
self.use_transactional_tests = false
|
13
|
+
fixtures :topics, :developers, :authors, :posts
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@first, @second = Topic.find(1, 2).sort_by(&:id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_persisted_in_a_model_with_custom_primary_key_after_failed_save
|
20
|
+
movie = Movie.create
|
21
|
+
assert !movie.persisted?
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_raise_after_destroy
|
25
|
+
assert_not @first.frozen?
|
26
|
+
|
27
|
+
assert_raises(RuntimeError) {
|
28
|
+
Topic.transaction do
|
29
|
+
@first.destroy
|
30
|
+
assert @first.frozen?
|
31
|
+
raise
|
32
|
+
end
|
33
|
+
}
|
34
|
+
|
35
|
+
assert @first.reload
|
36
|
+
assert_not @first.frozen?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_successful
|
40
|
+
Topic.transaction do
|
41
|
+
@first.approved = true
|
42
|
+
@second.approved = false
|
43
|
+
@first.save
|
44
|
+
@second.save
|
45
|
+
end
|
46
|
+
|
47
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
48
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
49
|
+
end
|
50
|
+
|
51
|
+
def transaction_with_return
|
52
|
+
Topic.transaction do
|
53
|
+
@first.approved = true
|
54
|
+
@second.approved = false
|
55
|
+
@first.save
|
56
|
+
@second.save
|
57
|
+
return
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_add_to_null_transaction
|
62
|
+
topic = Topic.new
|
63
|
+
topic.add_to_transaction
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_successful_with_return
|
67
|
+
committed = false
|
68
|
+
|
69
|
+
Topic.connection.class_eval do
|
70
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
71
|
+
define_method(:commit_db_transaction) do
|
72
|
+
committed = true
|
73
|
+
real_commit_db_transaction
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
transaction_with_return
|
78
|
+
assert committed
|
79
|
+
|
80
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
81
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
82
|
+
ensure
|
83
|
+
Topic.connection.class_eval do
|
84
|
+
remove_method :commit_db_transaction
|
85
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_number_of_transactions_in_commit
|
90
|
+
num = nil
|
91
|
+
|
92
|
+
Topic.connection.class_eval do
|
93
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
94
|
+
define_method(:commit_db_transaction) do
|
95
|
+
num = transaction_manager.open_transactions
|
96
|
+
real_commit_db_transaction
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
Topic.transaction do
|
101
|
+
@first.approved = true
|
102
|
+
@first.save!
|
103
|
+
end
|
104
|
+
|
105
|
+
assert_equal 0, num
|
106
|
+
ensure
|
107
|
+
Topic.connection.class_eval do
|
108
|
+
remove_method :commit_db_transaction
|
109
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_successful_with_instance_method
|
114
|
+
@first.transaction do
|
115
|
+
@first.approved = true
|
116
|
+
@second.approved = false
|
117
|
+
@first.save
|
118
|
+
@second.save
|
119
|
+
end
|
120
|
+
|
121
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
122
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_failing_on_exception
|
126
|
+
begin
|
127
|
+
Topic.transaction do
|
128
|
+
@first.approved = true
|
129
|
+
@second.approved = false
|
130
|
+
@first.save
|
131
|
+
@second.save
|
132
|
+
raise "Bad things!"
|
133
|
+
end
|
134
|
+
rescue
|
135
|
+
# caught it
|
136
|
+
end
|
137
|
+
|
138
|
+
assert @first.approved?, "First should still be changed in the objects"
|
139
|
+
assert !@second.approved?, "Second should still be changed in the objects"
|
140
|
+
|
141
|
+
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
142
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_raising_exception_in_callback_rollbacks_in_save
|
146
|
+
def @first.after_save_for_transaction
|
147
|
+
raise 'Make the transaction rollback'
|
148
|
+
end
|
149
|
+
|
150
|
+
@first.approved = true
|
151
|
+
e = assert_raises(RuntimeError) { @first.save }
|
152
|
+
assert_equal "Make the transaction rollback", e.message
|
153
|
+
assert !Topic.find(1).approved?
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_rolling_back_in_a_callback_rollbacks_before_save
|
157
|
+
def @first.before_save_for_transaction
|
158
|
+
raise ActiveRecord::Rollback
|
159
|
+
end
|
160
|
+
assert !@first.approved
|
161
|
+
|
162
|
+
Topic.transaction do
|
163
|
+
@first.approved = true
|
164
|
+
@first.save!
|
165
|
+
end
|
166
|
+
assert !Topic.find(@first.id).approved?, "Should not commit the approved flag"
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_raising_exception_in_nested_transaction_restore_state_in_save
|
170
|
+
topic = Topic.new
|
171
|
+
|
172
|
+
def topic.after_save_for_transaction
|
173
|
+
raise 'Make the transaction rollback'
|
174
|
+
end
|
175
|
+
|
176
|
+
assert_raises(RuntimeError) do
|
177
|
+
Topic.transaction { topic.save }
|
178
|
+
end
|
179
|
+
|
180
|
+
assert topic.new_record?, "#{topic.inspect} should be new record"
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_transaction_state_is_cleared_when_record_is_persisted
|
184
|
+
author = Author.create! name: 'foo'
|
185
|
+
author.name = nil
|
186
|
+
assert_not author.save
|
187
|
+
assert_not author.new_record?
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_update_should_rollback_on_failure
|
191
|
+
author = Author.find(1)
|
192
|
+
posts_count = author.posts.size
|
193
|
+
assert posts_count > 0
|
194
|
+
status = author.update(name: nil, post_ids: [])
|
195
|
+
assert !status
|
196
|
+
assert_equal posts_count, author.posts.reload.size
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_update_should_rollback_on_failure!
|
200
|
+
author = Author.find(1)
|
201
|
+
posts_count = author.posts.size
|
202
|
+
assert posts_count > 0
|
203
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
204
|
+
author.update!(name: nil, post_ids: [])
|
205
|
+
end
|
206
|
+
assert_equal posts_count, author.posts.reload.size
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_cancellation_from_returning_false_in_before_filter
|
210
|
+
def @first.before_save_for_transaction
|
211
|
+
false
|
212
|
+
end
|
213
|
+
|
214
|
+
assert_deprecated do
|
215
|
+
@first.save
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_cancellation_from_before_destroy_rollbacks_in_destroy
|
220
|
+
add_cancelling_before_destroy_with_db_side_effect_to_topic @first
|
221
|
+
nbooks_before_destroy = Book.count
|
222
|
+
status = @first.destroy
|
223
|
+
assert !status
|
224
|
+
@first.reload
|
225
|
+
assert_equal nbooks_before_destroy, Book.count
|
226
|
+
end
|
227
|
+
|
228
|
+
%w(validation save).each do |filter|
|
229
|
+
define_method("test_cancellation_from_before_filters_rollbacks_in_#{filter}") do
|
230
|
+
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic", @first)
|
231
|
+
nbooks_before_save = Book.count
|
232
|
+
original_author_name = @first.author_name
|
233
|
+
@first.author_name += '_this_should_not_end_up_in_the_db'
|
234
|
+
status = @first.save
|
235
|
+
assert !status
|
236
|
+
assert_equal original_author_name, @first.reload.author_name
|
237
|
+
assert_equal nbooks_before_save, Book.count
|
238
|
+
end
|
239
|
+
|
240
|
+
define_method("test_cancellation_from_before_filters_rollbacks_in_#{filter}!") do
|
241
|
+
send("add_cancelling_before_#{filter}_with_db_side_effect_to_topic", @first)
|
242
|
+
nbooks_before_save = Book.count
|
243
|
+
original_author_name = @first.author_name
|
244
|
+
@first.author_name += '_this_should_not_end_up_in_the_db'
|
245
|
+
|
246
|
+
begin
|
247
|
+
@first.save!
|
248
|
+
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved
|
249
|
+
end
|
250
|
+
|
251
|
+
assert_equal original_author_name, @first.reload.author_name
|
252
|
+
assert_equal nbooks_before_save, Book.count
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_callback_rollback_in_create
|
257
|
+
topic = Class.new(Topic) {
|
258
|
+
def after_create_for_transaction
|
259
|
+
raise 'Make the transaction rollback'
|
260
|
+
end
|
261
|
+
}
|
262
|
+
|
263
|
+
new_topic = topic.new(:title => "A new topic",
|
264
|
+
:author_name => "Ben",
|
265
|
+
:author_email_address => "ben@example.com",
|
266
|
+
:written_on => "2003-07-16t15:28:11.2233+01:00",
|
267
|
+
:last_read => "2004-04-15",
|
268
|
+
:bonus_time => "2005-01-30t15:28:00.00+01:00",
|
269
|
+
:content => "Have a nice day",
|
270
|
+
:approved => false)
|
271
|
+
|
272
|
+
new_record_snapshot = !new_topic.persisted?
|
273
|
+
id_present = new_topic.has_attribute?(Topic.primary_key)
|
274
|
+
id_snapshot = new_topic.id
|
275
|
+
|
276
|
+
# Make sure the second save gets the after_create callback called.
|
277
|
+
2.times do
|
278
|
+
new_topic.approved = true
|
279
|
+
e = assert_raises(RuntimeError) { new_topic.save }
|
280
|
+
assert_equal "Make the transaction rollback", e.message
|
281
|
+
assert_equal new_record_snapshot, !new_topic.persisted?, "The topic should have its old persisted value"
|
282
|
+
assert_equal id_snapshot, new_topic.id, "The topic should have its old id"
|
283
|
+
assert_equal id_present, new_topic.has_attribute?(Topic.primary_key)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_callback_rollback_in_create_with_record_invalid_exception
|
288
|
+
topic = Class.new(Topic) {
|
289
|
+
def after_create_for_transaction
|
290
|
+
raise ActiveRecord::RecordInvalid.new(Author.new)
|
291
|
+
end
|
292
|
+
}
|
293
|
+
|
294
|
+
new_topic = topic.create(:title => "A new topic")
|
295
|
+
assert !new_topic.persisted?, "The topic should not be persisted"
|
296
|
+
assert_nil new_topic.id, "The topic should not have an ID"
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_nested_explicit_transactions
|
300
|
+
Topic.transaction do
|
301
|
+
Topic.transaction do
|
302
|
+
@first.approved = true
|
303
|
+
@second.approved = false
|
304
|
+
@first.save
|
305
|
+
@second.save
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
310
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_manually_rolling_back_a_transaction
|
314
|
+
Topic.transaction do
|
315
|
+
@first.approved = true
|
316
|
+
@second.approved = false
|
317
|
+
@first.save
|
318
|
+
@second.save
|
319
|
+
|
320
|
+
raise ActiveRecord::Rollback
|
321
|
+
end
|
322
|
+
|
323
|
+
assert @first.approved?, "First should still be changed in the objects"
|
324
|
+
assert !@second.approved?, "Second should still be changed in the objects"
|
325
|
+
|
326
|
+
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
327
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_invalid_keys_for_transaction
|
331
|
+
assert_raise ArgumentError do
|
332
|
+
Topic.transaction :nested => true do
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_force_savepoint_in_nested_transaction
|
338
|
+
Topic.transaction do
|
339
|
+
@first.approved = true
|
340
|
+
@second.approved = false
|
341
|
+
@first.save!
|
342
|
+
@second.save!
|
343
|
+
|
344
|
+
begin
|
345
|
+
Topic.transaction :requires_new => true do
|
346
|
+
@first.happy = false
|
347
|
+
@first.save!
|
348
|
+
raise
|
349
|
+
end
|
350
|
+
rescue
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
assert @first.reload.approved?
|
355
|
+
assert !@second.reload.approved?
|
356
|
+
end if Topic.connection.supports_savepoints?
|
357
|
+
|
358
|
+
def test_force_savepoint_on_instance
|
359
|
+
@first.transaction do
|
360
|
+
@first.approved = true
|
361
|
+
@second.approved = false
|
362
|
+
@first.save!
|
363
|
+
@second.save!
|
364
|
+
|
365
|
+
begin
|
366
|
+
@second.transaction :requires_new => true do
|
367
|
+
@first.happy = false
|
368
|
+
@first.save!
|
369
|
+
raise
|
370
|
+
end
|
371
|
+
rescue
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
assert @first.reload.approved?
|
376
|
+
assert !@second.reload.approved?
|
377
|
+
end if Topic.connection.supports_savepoints?
|
378
|
+
|
379
|
+
def test_no_savepoint_in_nested_transaction_without_force
|
380
|
+
Topic.transaction do
|
381
|
+
@first.approved = true
|
382
|
+
@second.approved = false
|
383
|
+
@first.save!
|
384
|
+
@second.save!
|
385
|
+
|
386
|
+
begin
|
387
|
+
Topic.transaction do
|
388
|
+
@first.approved = false
|
389
|
+
@first.save!
|
390
|
+
raise
|
391
|
+
end
|
392
|
+
rescue
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
assert !@first.reload.approved?
|
397
|
+
assert !@second.reload.approved?
|
398
|
+
end if Topic.connection.supports_savepoints?
|
399
|
+
|
400
|
+
def test_many_savepoints
|
401
|
+
Topic.transaction do
|
402
|
+
@first.content = "One"
|
403
|
+
@first.save!
|
404
|
+
|
405
|
+
begin
|
406
|
+
Topic.transaction :requires_new => true do
|
407
|
+
@first.content = "Two"
|
408
|
+
@first.save!
|
409
|
+
|
410
|
+
begin
|
411
|
+
Topic.transaction :requires_new => true do
|
412
|
+
@first.content = "Three"
|
413
|
+
@first.save!
|
414
|
+
|
415
|
+
begin
|
416
|
+
Topic.transaction :requires_new => true do
|
417
|
+
@first.content = "Four"
|
418
|
+
@first.save!
|
419
|
+
raise
|
420
|
+
end
|
421
|
+
rescue
|
422
|
+
end
|
423
|
+
|
424
|
+
@three = @first.reload.content
|
425
|
+
raise
|
426
|
+
end
|
427
|
+
rescue
|
428
|
+
end
|
429
|
+
|
430
|
+
@two = @first.reload.content
|
431
|
+
raise
|
432
|
+
end
|
433
|
+
rescue
|
434
|
+
end
|
435
|
+
|
436
|
+
@one = @first.reload.content
|
437
|
+
end
|
438
|
+
|
439
|
+
assert_equal "One", @one
|
440
|
+
assert_equal "Two", @two
|
441
|
+
assert_equal "Three", @three
|
442
|
+
end if Topic.connection.supports_savepoints?
|
443
|
+
|
444
|
+
def test_using_named_savepoints
|
445
|
+
Topic.transaction do
|
446
|
+
@first.approved = true
|
447
|
+
@first.save!
|
448
|
+
Topic.connection.create_savepoint("first")
|
449
|
+
|
450
|
+
@first.approved = false
|
451
|
+
@first.save!
|
452
|
+
Topic.connection.rollback_to_savepoint("first")
|
453
|
+
assert @first.reload.approved?
|
454
|
+
|
455
|
+
@first.approved = false
|
456
|
+
@first.save!
|
457
|
+
Topic.connection.release_savepoint("first")
|
458
|
+
assert_not @first.reload.approved?
|
459
|
+
end
|
460
|
+
end if Topic.connection.supports_savepoints?
|
461
|
+
|
462
|
+
def test_releasing_named_savepoints
|
463
|
+
Topic.transaction do
|
464
|
+
Topic.connection.create_savepoint("another")
|
465
|
+
Topic.connection.release_savepoint("another")
|
466
|
+
|
467
|
+
# The savepoint is now gone and we can't remove it again.
|
468
|
+
assert_raises(ActiveRecord::StatementInvalid) do
|
469
|
+
Topic.connection.release_savepoint("another")
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_savepoints_name
|
475
|
+
Topic.transaction do
|
476
|
+
assert_nil Topic.connection.current_savepoint_name
|
477
|
+
assert_nil Topic.connection.current_transaction.savepoint_name
|
478
|
+
|
479
|
+
Topic.transaction(requires_new: true) do
|
480
|
+
assert_equal "active_record_1", Topic.connection.current_savepoint_name
|
481
|
+
assert_equal "active_record_1", Topic.connection.current_transaction.savepoint_name
|
482
|
+
|
483
|
+
Topic.transaction(requires_new: true) do
|
484
|
+
assert_equal "active_record_2", Topic.connection.current_savepoint_name
|
485
|
+
assert_equal "active_record_2", Topic.connection.current_transaction.savepoint_name
|
486
|
+
end
|
487
|
+
|
488
|
+
assert_equal "active_record_1", Topic.connection.current_savepoint_name
|
489
|
+
assert_equal "active_record_1", Topic.connection.current_transaction.savepoint_name
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_rollback_when_commit_raises
|
495
|
+
assert_called(Topic.connection, :begin_db_transaction) do
|
496
|
+
Topic.connection.stub(:commit_db_transaction, ->{ raise('OH NOES') }) do
|
497
|
+
assert_called(Topic.connection, :rollback_db_transaction) do
|
498
|
+
|
499
|
+
e = assert_raise RuntimeError do
|
500
|
+
Topic.transaction do
|
501
|
+
# do nothing
|
502
|
+
end
|
503
|
+
end
|
504
|
+
assert_equal 'OH NOES', e.message
|
505
|
+
end
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def test_rollback_when_saving_a_frozen_record
|
511
|
+
topic = Topic.new(:title => 'test')
|
512
|
+
topic.freeze
|
513
|
+
e = assert_raise(frozen_error_class) { topic.save }
|
514
|
+
# Not good enough, but we can't do much
|
515
|
+
# about it since there is no specific error
|
516
|
+
# for frozen objects.
|
517
|
+
assert_match(/frozen/i, e.message)
|
518
|
+
assert !topic.persisted?, "not persisted"
|
519
|
+
assert_nil topic.id
|
520
|
+
assert topic.frozen?, 'not frozen'
|
521
|
+
end
|
522
|
+
|
523
|
+
def test_rollback_when_thread_killed
|
524
|
+
return if in_memory_db?
|
525
|
+
|
526
|
+
queue = Queue.new
|
527
|
+
thread = Thread.new do
|
528
|
+
Topic.transaction do
|
529
|
+
@first.approved = true
|
530
|
+
@second.approved = false
|
531
|
+
@first.save
|
532
|
+
|
533
|
+
queue.push nil
|
534
|
+
sleep
|
535
|
+
|
536
|
+
@second.save
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
queue.pop
|
541
|
+
thread.kill
|
542
|
+
thread.join
|
543
|
+
|
544
|
+
assert @first.approved?, "First should still be changed in the objects"
|
545
|
+
assert !@second.approved?, "Second should still be changed in the objects"
|
546
|
+
|
547
|
+
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
548
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
549
|
+
end
|
550
|
+
|
551
|
+
def test_restore_active_record_state_for_all_records_in_a_transaction
|
552
|
+
topic_without_callbacks = Class.new(ActiveRecord::Base) do
|
553
|
+
self.table_name = 'topics'
|
554
|
+
end
|
555
|
+
|
556
|
+
topic_1 = Topic.new(:title => 'test_1')
|
557
|
+
topic_2 = Topic.new(:title => 'test_2')
|
558
|
+
topic_3 = topic_without_callbacks.new(:title => 'test_3')
|
559
|
+
|
560
|
+
Topic.transaction do
|
561
|
+
assert topic_1.save
|
562
|
+
assert topic_2.save
|
563
|
+
assert topic_3.save
|
564
|
+
@first.save
|
565
|
+
@second.destroy
|
566
|
+
assert topic_1.persisted?, 'persisted'
|
567
|
+
assert_not_nil topic_1.id
|
568
|
+
assert topic_2.persisted?, 'persisted'
|
569
|
+
assert_not_nil topic_2.id
|
570
|
+
assert topic_3.persisted?, 'persisted'
|
571
|
+
assert_not_nil topic_3.id
|
572
|
+
assert @first.persisted?, 'persisted'
|
573
|
+
assert_not_nil @first.id
|
574
|
+
assert @second.destroyed?, 'destroyed'
|
575
|
+
raise ActiveRecord::Rollback
|
576
|
+
end
|
577
|
+
|
578
|
+
assert !topic_1.persisted?, 'not persisted'
|
579
|
+
assert_nil topic_1.id
|
580
|
+
assert !topic_2.persisted?, 'not persisted'
|
581
|
+
assert_nil topic_2.id
|
582
|
+
assert !topic_3.persisted?, 'not persisted'
|
583
|
+
assert_nil topic_3.id
|
584
|
+
assert @first.persisted?, 'persisted'
|
585
|
+
assert_not_nil @first.id
|
586
|
+
assert !@second.destroyed?, 'not destroyed'
|
587
|
+
end
|
588
|
+
|
589
|
+
def test_restore_frozen_state_after_double_destroy
|
590
|
+
topic = Topic.create
|
591
|
+
reply = topic.replies.create
|
592
|
+
|
593
|
+
Topic.transaction do
|
594
|
+
topic.destroy # calls #destroy on reply (since dependent: destroy)
|
595
|
+
reply.destroy
|
596
|
+
|
597
|
+
raise ActiveRecord::Rollback
|
598
|
+
end
|
599
|
+
|
600
|
+
assert_not reply.frozen?
|
601
|
+
assert_not topic.frozen?
|
602
|
+
end
|
603
|
+
|
604
|
+
def test_rollback_of_frozen_records
|
605
|
+
topic = Topic.create.freeze
|
606
|
+
Topic.transaction do
|
607
|
+
topic.destroy
|
608
|
+
raise ActiveRecord::Rollback
|
609
|
+
end
|
610
|
+
assert topic.frozen?, 'frozen'
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_rollback_for_freshly_persisted_records
|
614
|
+
topic = Topic.create
|
615
|
+
Topic.transaction do
|
616
|
+
topic.destroy
|
617
|
+
raise ActiveRecord::Rollback
|
618
|
+
end
|
619
|
+
assert topic.persisted?, 'persisted'
|
620
|
+
end
|
621
|
+
|
622
|
+
def test_sqlite_add_column_in_transaction
|
623
|
+
return true unless current_adapter?(:SQLite3Adapter)
|
624
|
+
|
625
|
+
# Test first if column creation/deletion works correctly when no
|
626
|
+
# transaction is in place.
|
627
|
+
#
|
628
|
+
# We go back to the connection for the column queries because
|
629
|
+
# Topic.columns is cached and won't report changes to the DB
|
630
|
+
|
631
|
+
assert_nothing_raised do
|
632
|
+
Topic.reset_column_information
|
633
|
+
Topic.connection.add_column('topics', 'stuff', :string)
|
634
|
+
assert Topic.column_names.include?('stuff')
|
635
|
+
|
636
|
+
Topic.reset_column_information
|
637
|
+
Topic.connection.remove_column('topics', 'stuff')
|
638
|
+
assert !Topic.column_names.include?('stuff')
|
639
|
+
end
|
640
|
+
|
641
|
+
if Topic.connection.supports_ddl_transactions?
|
642
|
+
assert_nothing_raised do
|
643
|
+
Topic.transaction { Topic.connection.add_column('topics', 'stuff', :string) }
|
644
|
+
end
|
645
|
+
else
|
646
|
+
Topic.transaction do
|
647
|
+
assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) }
|
648
|
+
raise ActiveRecord::Rollback
|
649
|
+
end
|
650
|
+
end
|
651
|
+
ensure
|
652
|
+
begin
|
653
|
+
Topic.connection.remove_column('topics', 'stuff')
|
654
|
+
rescue
|
655
|
+
ensure
|
656
|
+
Topic.reset_column_information
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
def test_transactions_state_from_rollback
|
661
|
+
connection = Topic.connection
|
662
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
663
|
+
|
664
|
+
assert transaction.open?
|
665
|
+
assert !transaction.state.rolledback?
|
666
|
+
assert !transaction.state.committed?
|
667
|
+
|
668
|
+
transaction.rollback
|
669
|
+
|
670
|
+
assert transaction.state.rolledback?
|
671
|
+
assert !transaction.state.committed?
|
672
|
+
end
|
673
|
+
|
674
|
+
def test_transactions_state_from_commit
|
675
|
+
connection = Topic.connection
|
676
|
+
transaction = ActiveRecord::ConnectionAdapters::TransactionManager.new(connection).begin_transaction
|
677
|
+
|
678
|
+
assert transaction.open?
|
679
|
+
assert !transaction.state.rolledback?
|
680
|
+
assert !transaction.state.committed?
|
681
|
+
|
682
|
+
transaction.commit
|
683
|
+
|
684
|
+
assert !transaction.state.rolledback?
|
685
|
+
assert transaction.state.committed?
|
686
|
+
end
|
687
|
+
|
688
|
+
def test_transaction_rollback_with_primarykeyless_tables
|
689
|
+
connection = ActiveRecord::Base.connection
|
690
|
+
connection.create_table(:transaction_without_primary_keys, force: true, id: false) do |t|
|
691
|
+
t.integer :thing_id
|
692
|
+
end
|
693
|
+
|
694
|
+
klass = Class.new(ActiveRecord::Base) do
|
695
|
+
self.table_name = 'transaction_without_primary_keys'
|
696
|
+
after_commit { } # necessary to trigger the has_transactional_callbacks branch
|
697
|
+
end
|
698
|
+
|
699
|
+
assert_no_difference(-> { klass.count }) do
|
700
|
+
ActiveRecord::Base.transaction do
|
701
|
+
klass.create!
|
702
|
+
raise ActiveRecord::Rollback
|
703
|
+
end
|
704
|
+
end
|
705
|
+
ensure
|
706
|
+
connection.drop_table 'transaction_without_primary_keys', if_exists: true
|
707
|
+
end
|
708
|
+
|
709
|
+
private
|
710
|
+
|
711
|
+
%w(validation save destroy).each do |filter|
|
712
|
+
define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do |topic|
|
713
|
+
meta = class << topic; self; end
|
714
|
+
meta.send("define_method", "before_#{filter}_for_transaction") do
|
715
|
+
Book.create
|
716
|
+
throw(:abort)
|
717
|
+
end
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase
|
723
|
+
self.use_transactional_tests = true
|
724
|
+
fixtures :topics
|
725
|
+
|
726
|
+
def test_automatic_savepoint_in_outer_transaction
|
727
|
+
@first = Topic.find(1)
|
728
|
+
|
729
|
+
begin
|
730
|
+
Topic.transaction do
|
731
|
+
@first.approved = true
|
732
|
+
@first.save!
|
733
|
+
raise
|
734
|
+
end
|
735
|
+
rescue
|
736
|
+
assert !@first.reload.approved?
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
740
|
+
def test_no_automatic_savepoint_for_inner_transaction
|
741
|
+
@first = Topic.find(1)
|
742
|
+
|
743
|
+
Topic.transaction do
|
744
|
+
@first.approved = true
|
745
|
+
@first.save!
|
746
|
+
|
747
|
+
begin
|
748
|
+
Topic.transaction do
|
749
|
+
@first.approved = false
|
750
|
+
@first.save!
|
751
|
+
raise
|
752
|
+
end
|
753
|
+
rescue
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
assert !@first.reload.approved?
|
758
|
+
end
|
759
|
+
end if Topic.connection.supports_savepoints?
|
760
|
+
|
761
|
+
if current_adapter?(:PostgreSQLAdapter)
|
762
|
+
class ConcurrentTransactionTest < TransactionTest
|
763
|
+
# This will cause transactions to overlap and fail unless they are performed on
|
764
|
+
# separate database connections.
|
765
|
+
unless in_memory_db?
|
766
|
+
def test_transaction_per_thread
|
767
|
+
threads = 3.times.map do
|
768
|
+
Thread.new do
|
769
|
+
Topic.transaction do
|
770
|
+
topic = Topic.find(1)
|
771
|
+
topic.approved = !topic.approved?
|
772
|
+
assert topic.save!
|
773
|
+
topic.approved = !topic.approved?
|
774
|
+
assert topic.save!
|
775
|
+
end
|
776
|
+
Topic.connection.close
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
threads.each(&:join)
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
# Test for dirty reads among simultaneous transactions.
|
785
|
+
def test_transaction_isolation__read_committed
|
786
|
+
# Should be invariant.
|
787
|
+
original_salary = Developer.find(1).salary
|
788
|
+
temporary_salary = 200000
|
789
|
+
|
790
|
+
assert_nothing_raised do
|
791
|
+
threads = (1..3).map do
|
792
|
+
Thread.new do
|
793
|
+
Developer.transaction do
|
794
|
+
# Expect original salary.
|
795
|
+
dev = Developer.find(1)
|
796
|
+
assert_equal original_salary, dev.salary
|
797
|
+
|
798
|
+
dev.salary = temporary_salary
|
799
|
+
dev.save!
|
800
|
+
|
801
|
+
# Expect temporary salary.
|
802
|
+
dev = Developer.find(1)
|
803
|
+
assert_equal temporary_salary, dev.salary
|
804
|
+
|
805
|
+
dev.salary = original_salary
|
806
|
+
dev.save!
|
807
|
+
|
808
|
+
# Expect original salary.
|
809
|
+
dev = Developer.find(1)
|
810
|
+
assert_equal original_salary, dev.salary
|
811
|
+
end
|
812
|
+
Developer.connection.close
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
# Keep our eyes peeled.
|
817
|
+
threads << Thread.new do
|
818
|
+
10.times do
|
819
|
+
sleep 0.05
|
820
|
+
Developer.transaction do
|
821
|
+
# Always expect original salary.
|
822
|
+
assert_equal original_salary, Developer.find(1).salary
|
823
|
+
end
|
824
|
+
end
|
825
|
+
Developer.connection.close
|
826
|
+
end
|
827
|
+
|
828
|
+
threads.each(&:join)
|
829
|
+
end
|
830
|
+
|
831
|
+
assert_equal original_salary, Developer.find(1).salary
|
832
|
+
end
|
833
|
+
end
|
834
|
+
end
|