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.
Files changed (753) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +299 -0
  3. data/LICENSE +55 -0
  4. data/MANIFEST +14 -0
  5. data/ParameterizedQueries README +39 -0
  6. data/README +210 -0
  7. data/ext/Makefile +270 -0
  8. data/ext/Makefile.nt32 +181 -0
  9. data/ext/Makefile.nt32.191 +212 -0
  10. data/ext/extconf.rb +320 -0
  11. data/ext/gil_release_version.h +3 -0
  12. data/ext/ibm_db.bundle +0 -0
  13. data/ext/ibm_db.c +11865 -0
  14. data/ext/ibm_db.o +0 -0
  15. data/ext/mkmf.log +98 -0
  16. data/ext/ruby_ibm_db.h +241 -0
  17. data/ext/ruby_ibm_db_cli.c +867 -0
  18. data/ext/ruby_ibm_db_cli.h +508 -0
  19. data/ext/ruby_ibm_db_cli.o +0 -0
  20. data/ext/unicode_support_version.h +3 -0
  21. data/init.rb +42 -0
  22. data/lib/IBM_DB.rb +27 -0
  23. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4407 -0
  24. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
  25. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -0
  26. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  27. data/lib/ibm_db.bundle +0 -0
  28. data/test/active_record/connection_adapters/fake_adapter.rb +52 -0
  29. data/test/activejob/destroy_association_async_test.rb +305 -0
  30. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  31. data/test/activejob/helper.rb +15 -0
  32. data/test/assets/example.log +1 -0
  33. data/test/assets/flowers.jpg +0 -0
  34. data/test/assets/schema_dump_5_1.yml +345 -0
  35. data/test/assets/test.txt +1 -0
  36. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  37. data/test/cases/adapter_test.rb +565 -0
  38. data/test/cases/adapters/mysql2/active_schema_test.rb +203 -0
  39. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  40. data/test/cases/adapters/mysql2/bind_parameter_test.rb +52 -0
  41. data/test/cases/adapters/mysql2/boolean_test.rb +102 -0
  42. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +65 -0
  43. data/test/cases/adapters/mysql2/charset_collation_test.rb +57 -0
  44. data/test/cases/adapters/mysql2/connection_test.rb +208 -0
  45. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  46. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +49 -0
  47. data/test/cases/adapters/mysql2/enum_test.rb +47 -0
  48. data/test/cases/adapters/mysql2/explain_test.rb +23 -0
  49. data/test/cases/adapters/mysql2/json_test.rb +24 -0
  50. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  51. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +238 -0
  52. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  53. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  54. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  55. data/test/cases/adapters/mysql2/schema_migrations_test.rb +64 -0
  56. data/test/cases/adapters/mysql2/schema_test.rb +128 -0
  57. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  58. data/test/cases/adapters/mysql2/sp_test.rb +38 -0
  59. data/test/cases/adapters/mysql2/sql_types_test.rb +16 -0
  60. data/test/cases/adapters/mysql2/table_options_test.rb +125 -0
  61. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  62. data/test/cases/adapters/mysql2/unsigned_type_test.rb +68 -0
  63. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  64. data/test/cases/adapters/postgresql/active_schema_test.rb +113 -0
  65. data/test/cases/adapters/postgresql/array_test.rb +394 -0
  66. data/test/cases/adapters/postgresql/bit_string_test.rb +84 -0
  67. data/test/cases/adapters/postgresql/bytea_test.rb +135 -0
  68. data/test/cases/adapters/postgresql/case_insensitive_test.rb +27 -0
  69. data/test/cases/adapters/postgresql/change_schema_test.rb +40 -0
  70. data/test/cases/adapters/postgresql/cidr_test.rb +27 -0
  71. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  72. data/test/cases/adapters/postgresql/collation_test.rb +55 -0
  73. data/test/cases/adapters/postgresql/composite_test.rb +134 -0
  74. data/test/cases/adapters/postgresql/connection_test.rb +245 -0
  75. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  76. data/test/cases/adapters/postgresql/datatype_test.rb +89 -0
  77. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  78. data/test/cases/adapters/postgresql/domain_test.rb +49 -0
  79. data/test/cases/adapters/postgresql/enum_test.rb +93 -0
  80. data/test/cases/adapters/postgresql/explain_test.rb +22 -0
  81. data/test/cases/adapters/postgresql/extension_migration_test.rb +64 -0
  82. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  83. data/test/cases/adapters/postgresql/full_text_test.rb +46 -0
  84. data/test/cases/adapters/postgresql/geometric_test.rb +372 -0
  85. data/test/cases/adapters/postgresql/hstore_test.rb +390 -0
  86. data/test/cases/adapters/postgresql/infinity_test.rb +108 -0
  87. data/test/cases/adapters/postgresql/integer_test.rb +27 -0
  88. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  89. data/test/cases/adapters/postgresql/json_test.rb +52 -0
  90. data/test/cases/adapters/postgresql/ltree_test.rb +51 -0
  91. data/test/cases/adapters/postgresql/money_test.rb +127 -0
  92. data/test/cases/adapters/postgresql/network_test.rb +102 -0
  93. data/test/cases/adapters/postgresql/numbers_test.rb +51 -0
  94. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  95. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  96. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  97. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +447 -0
  98. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  99. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  100. data/test/cases/adapters/postgresql/quoting_test.rb +50 -0
  101. data/test/cases/adapters/postgresql/range_test.rb +457 -0
  102. data/test/cases/adapters/postgresql/referential_integrity_test.rb +112 -0
  103. data/test/cases/adapters/postgresql/rename_table_test.rb +35 -0
  104. data/test/cases/adapters/postgresql/schema_authorization_test.rb +110 -0
  105. data/test/cases/adapters/postgresql/schema_test.rb +713 -0
  106. data/test/cases/adapters/postgresql/serial_test.rb +156 -0
  107. data/test/cases/adapters/postgresql/statement_pool_test.rb +61 -0
  108. data/test/cases/adapters/postgresql/timestamp_test.rb +92 -0
  109. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  110. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  111. data/test/cases/adapters/postgresql/type_lookup_test.rb +35 -0
  112. data/test/cases/adapters/postgresql/utils_test.rb +64 -0
  113. data/test/cases/adapters/postgresql/uuid_test.rb +411 -0
  114. data/test/cases/adapters/postgresql/xml_test.rb +50 -0
  115. data/test/cases/adapters/sqlite3/collation_test.rb +64 -0
  116. data/test/cases/adapters/sqlite3/copy_table_test.rb +101 -0
  117. data/test/cases/adapters/sqlite3/explain_test.rb +23 -0
  118. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  119. data/test/cases/adapters/sqlite3/quoting_test.rb +79 -0
  120. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  121. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +628 -0
  122. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  123. data/test/cases/adapters/sqlite3/statement_pool_test.rb +21 -0
  124. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  125. data/test/cases/aggregations_test.rb +170 -0
  126. data/test/cases/annotate_test.rb +46 -0
  127. data/test/cases/ar_schema_test.rb +213 -0
  128. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  129. data/test/cases/arel/attributes/math_test.rb +83 -0
  130. data/test/cases/arel/attributes_test.rb +27 -0
  131. data/test/cases/arel/collectors/bind_test.rb +40 -0
  132. data/test/cases/arel/collectors/composite_test.rb +47 -0
  133. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  134. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  135. data/test/cases/arel/crud_test.rb +65 -0
  136. data/test/cases/arel/delete_manager_test.rb +53 -0
  137. data/test/cases/arel/factory_methods_test.rb +46 -0
  138. data/test/cases/arel/helper.rb +45 -0
  139. data/test/cases/arel/insert_manager_test.rb +241 -0
  140. data/test/cases/arel/nodes/and_test.rb +30 -0
  141. data/test/cases/arel/nodes/as_test.rb +36 -0
  142. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  143. data/test/cases/arel/nodes/bin_test.rb +35 -0
  144. data/test/cases/arel/nodes/binary_test.rb +29 -0
  145. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  146. data/test/cases/arel/nodes/case_test.rb +96 -0
  147. data/test/cases/arel/nodes/casted_test.rb +18 -0
  148. data/test/cases/arel/nodes/comment_test.rb +22 -0
  149. data/test/cases/arel/nodes/count_test.rb +35 -0
  150. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  151. data/test/cases/arel/nodes/descending_test.rb +46 -0
  152. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  153. data/test/cases/arel/nodes/equality_test.rb +62 -0
  154. data/test/cases/arel/nodes/extract_test.rb +43 -0
  155. data/test/cases/arel/nodes/false_test.rb +21 -0
  156. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  157. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  158. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  159. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  160. data/test/cases/arel/nodes/node_test.rb +22 -0
  161. data/test/cases/arel/nodes/not_test.rb +31 -0
  162. data/test/cases/arel/nodes/or_test.rb +36 -0
  163. data/test/cases/arel/nodes/over_test.rb +69 -0
  164. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  165. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  166. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  167. data/test/cases/arel/nodes/sum_test.rb +35 -0
  168. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  169. data/test/cases/arel/nodes/true_test.rb +21 -0
  170. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  171. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  172. data/test/cases/arel/nodes/window_test.rb +81 -0
  173. data/test/cases/arel/nodes_test.rb +34 -0
  174. data/test/cases/arel/select_manager_test.rb +1238 -0
  175. data/test/cases/arel/support/fake_record.rb +135 -0
  176. data/test/cases/arel/table_test.rb +216 -0
  177. data/test/cases/arel/update_manager_test.rb +126 -0
  178. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  179. data/test/cases/arel/visitors/dot_test.rb +90 -0
  180. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  181. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  182. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  183. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  184. data/test/cases/associations/association_scope_test.rb +16 -0
  185. data/test/cases/associations/belongs_to_associations_test.rb +1493 -0
  186. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +43 -0
  187. data/test/cases/associations/callbacks_test.rb +208 -0
  188. data/test/cases/associations/cascaded_eager_loading_test.rb +245 -0
  189. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +156 -0
  190. data/test/cases/associations/eager_load_nested_include_test.rb +127 -0
  191. data/test/cases/associations/eager_singularization_test.rb +148 -0
  192. data/test/cases/associations/eager_test.rb +1658 -0
  193. data/test/cases/associations/extension_test.rb +93 -0
  194. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1025 -0
  195. data/test/cases/associations/has_many_associations_test.rb +3074 -0
  196. data/test/cases/associations/has_many_through_associations_test.rb +1580 -0
  197. data/test/cases/associations/has_one_associations_test.rb +872 -0
  198. data/test/cases/associations/has_one_through_associations_test.rb +429 -0
  199. data/test/cases/associations/inner_join_association_test.rb +215 -0
  200. data/test/cases/associations/inverse_associations_test.rb +941 -0
  201. data/test/cases/associations/join_model_test.rb +787 -0
  202. data/test/cases/associations/left_outer_join_association_test.rb +123 -0
  203. data/test/cases/associations/nested_through_associations_test.rb +636 -0
  204. data/test/cases/associations/required_test.rb +127 -0
  205. data/test/cases/associations_test.rb +516 -0
  206. data/test/cases/attribute_decorators_test.rb +126 -0
  207. data/test/cases/attribute_methods/read_test.rb +60 -0
  208. data/test/cases/attribute_methods_test.rb +1124 -0
  209. data/test/cases/attribute_set_test.rb +270 -0
  210. data/test/cases/attribute_test.rb +246 -0
  211. data/test/cases/attributes_test.rb +371 -0
  212. data/test/cases/autosave_association_test.rb +1953 -0
  213. data/test/cases/base_prevent_writes_test.rb +229 -0
  214. data/test/cases/base_test.rb +1770 -0
  215. data/test/cases/batches_test.rb +695 -0
  216. data/test/cases/binary_test.rb +39 -0
  217. data/test/cases/bind_parameter_test.rb +283 -0
  218. data/test/cases/boolean_test.rb +52 -0
  219. data/test/cases/cache_key_test.rb +131 -0
  220. data/test/cases/calculations_test.rb +1361 -0
  221. data/test/cases/callbacks_test.rb +503 -0
  222. data/test/cases/clone_test.rb +45 -0
  223. data/test/cases/coders/json_test.rb +17 -0
  224. data/test/cases/coders/yaml_column_test.rb +66 -0
  225. data/test/cases/collection_cache_key_test.rb +272 -0
  226. data/test/cases/column_alias_test.rb +19 -0
  227. data/test/cases/column_definition_test.rb +34 -0
  228. data/test/cases/comment_test.rb +204 -0
  229. data/test/cases/connection_adapters/adapter_leasing_test.rb +60 -0
  230. data/test/cases/connection_adapters/connection_handler_test.rb +467 -0
  231. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  232. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  233. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  234. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  235. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  236. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  237. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  238. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +436 -0
  239. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +81 -0
  240. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  241. data/test/cases/connection_adapters/schema_cache_test.rb +294 -0
  242. data/test/cases/connection_adapters/type_lookup_test.rb +119 -0
  243. data/test/cases/connection_management_test.rb +114 -0
  244. data/test/cases/connection_pool_test.rb +754 -0
  245. data/test/cases/connection_specification/resolver_test.rb +131 -0
  246. data/test/cases/core_test.rb +136 -0
  247. data/test/cases/counter_cache_test.rb +368 -0
  248. data/test/cases/custom_locking_test.rb +19 -0
  249. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  250. data/test/cases/database_configurations/resolver_test.rb +150 -0
  251. data/test/cases/database_configurations_test.rb +145 -0
  252. data/test/cases/database_selector_test.rb +296 -0
  253. data/test/cases/database_statements_test.rb +36 -0
  254. data/test/cases/date_test.rb +36 -0
  255. data/test/cases/date_time_precision_test.rb +129 -0
  256. data/test/cases/date_time_test.rb +76 -0
  257. data/test/cases/defaults_test.rb +254 -0
  258. data/test/cases/delegated_type_test.rb +57 -0
  259. data/test/cases/dirty_test.rb +959 -0
  260. data/test/cases/disconnected_test.rb +30 -0
  261. data/test/cases/dup_test.rb +184 -0
  262. data/test/cases/enum_test.rb +823 -0
  263. data/test/cases/errors_test.rb +16 -0
  264. data/test/cases/explain_subscriber_test.rb +66 -0
  265. data/test/cases/explain_test.rb +79 -0
  266. data/test/cases/filter_attributes_test.rb +153 -0
  267. data/test/cases/finder_respond_to_test.rb +60 -0
  268. data/test/cases/finder_test.rb +1676 -0
  269. data/test/cases/fixture_set/file_test.rb +152 -0
  270. data/test/cases/fixtures_test.rb +1645 -0
  271. data/test/cases/forbidden_attributes_protection_test.rb +130 -0
  272. data/test/cases/habtm_destroy_order_test.rb +61 -0
  273. data/test/cases/helper.rb +233 -0
  274. data/test/cases/hot_compatibility_test.rb +143 -0
  275. data/test/cases/i18n_test.rb +46 -0
  276. data/test/cases/inheritance_test.rb +671 -0
  277. data/test/cases/insert_all_test.rb +489 -0
  278. data/test/cases/instrumentation_test.rb +101 -0
  279. data/test/cases/integration_test.rb +243 -0
  280. data/test/cases/invalid_connection_test.rb +26 -0
  281. data/test/cases/invertible_migration_test.rb +527 -0
  282. data/test/cases/json_attribute_test.rb +35 -0
  283. data/test/cases/json_serialization_test.rb +310 -0
  284. data/test/cases/json_shared_test_cases.rb +290 -0
  285. data/test/cases/locking_test.rb +787 -0
  286. data/test/cases/log_subscriber_test.rb +267 -0
  287. data/test/cases/marshal_serialization_test.rb +39 -0
  288. data/test/cases/migration/change_schema_test.rb +504 -0
  289. data/test/cases/migration/change_table_test.rb +364 -0
  290. data/test/cases/migration/check_constraint_test.rb +162 -0
  291. data/test/cases/migration/column_attributes_test.rb +186 -0
  292. data/test/cases/migration/column_positioning_test.rb +68 -0
  293. data/test/cases/migration/columns_test.rb +326 -0
  294. data/test/cases/migration/command_recorder_test.rb +437 -0
  295. data/test/cases/migration/compatibility_test.rb +673 -0
  296. data/test/cases/migration/create_join_table_test.rb +167 -0
  297. data/test/cases/migration/foreign_key_test.rb +581 -0
  298. data/test/cases/migration/helper.rb +40 -0
  299. data/test/cases/migration/index_test.rb +267 -0
  300. data/test/cases/migration/logger_test.rb +39 -0
  301. data/test/cases/migration/pending_migrations_test.rb +106 -0
  302. data/test/cases/migration/references_foreign_key_test.rb +235 -0
  303. data/test/cases/migration/references_index_test.rb +120 -0
  304. data/test/cases/migration/references_statements_test.rb +137 -0
  305. data/test/cases/migration/rename_table_test.rb +116 -0
  306. data/test/cases/migration_test.rb +1525 -0
  307. data/test/cases/migrator_test.rb +527 -0
  308. data/test/cases/mixin_test.rb +64 -0
  309. data/test/cases/modules_test.rb +174 -0
  310. data/test/cases/multi_db_migrator_test.rb +223 -0
  311. data/test/cases/multiparameter_attributes_test.rb +399 -0
  312. data/test/cases/multiple_db_test.rb +116 -0
  313. data/test/cases/nested_attributes_test.rb +1119 -0
  314. data/test/cases/nested_attributes_with_callbacks_test.rb +146 -0
  315. data/test/cases/null_relation_test.rb +84 -0
  316. data/test/cases/numeric_data_test.rb +93 -0
  317. data/test/cases/persistence_test.rb +1093 -0
  318. data/test/cases/pooled_connections_test.rb +73 -0
  319. data/test/cases/prepared_statement_status_test.rb +48 -0
  320. data/test/cases/primary_keys_test.rb +482 -0
  321. data/test/cases/query_cache_test.rb +915 -0
  322. data/test/cases/quoting_test.rb +303 -0
  323. data/test/cases/readonly_test.rb +120 -0
  324. data/test/cases/reaper_test.rb +199 -0
  325. data/test/cases/reflection_test.rb +520 -0
  326. data/test/cases/relation/delegation_test.rb +76 -0
  327. data/test/cases/relation/delete_all_test.rb +117 -0
  328. data/test/cases/relation/merging_test.rb +434 -0
  329. data/test/cases/relation/mutation_test.rb +145 -0
  330. data/test/cases/relation/or_test.rb +192 -0
  331. data/test/cases/relation/predicate_builder_test.rb +31 -0
  332. data/test/cases/relation/record_fetch_warning_test.rb +42 -0
  333. data/test/cases/relation/select_test.rb +67 -0
  334. data/test/cases/relation/update_all_test.rb +317 -0
  335. data/test/cases/relation/where_chain_test.rb +141 -0
  336. data/test/cases/relation/where_clause_test.rb +257 -0
  337. data/test/cases/relation/where_test.rb +429 -0
  338. data/test/cases/relation_test.rb +482 -0
  339. data/test/cases/relations_test.rb +2251 -0
  340. data/test/cases/reload_models_test.rb +26 -0
  341. data/test/cases/reserved_word_test.rb +141 -0
  342. data/test/cases/result_test.rb +141 -0
  343. data/test/cases/sanitize_test.rb +192 -0
  344. data/test/cases/schema_dumper_test.rb +550 -0
  345. data/test/cases/schema_loading_test.rb +53 -0
  346. data/test/cases/scoping/default_scoping_test.rb +569 -0
  347. data/test/cases/scoping/named_scoping_test.rb +649 -0
  348. data/test/cases/scoping/relation_scoping_test.rb +522 -0
  349. data/test/cases/secure_token_test.rb +47 -0
  350. data/test/cases/serialization_test.rb +106 -0
  351. data/test/cases/serialized_attribute_test.rb +455 -0
  352. data/test/cases/signed_id_test.rb +168 -0
  353. data/test/cases/statement_cache_test.rb +153 -0
  354. data/test/cases/statement_invalid_test.rb +42 -0
  355. data/test/cases/store_test.rb +320 -0
  356. data/test/cases/strict_loading_test.rb +473 -0
  357. data/test/cases/suppressor_test.rb +77 -0
  358. data/test/cases/tasks/database_tasks_test.rb +1526 -0
  359. data/test/cases/tasks/mysql_rake_test.rb +417 -0
  360. data/test/cases/tasks/postgresql_rake_test.rb +534 -0
  361. data/test/cases/tasks/sqlite_rake_test.rb +267 -0
  362. data/test/cases/test_case.rb +142 -0
  363. data/test/cases/test_databases_test.rb +79 -0
  364. data/test/cases/test_fixtures_test.rb +96 -0
  365. data/test/cases/time_precision_test.rb +125 -0
  366. data/test/cases/timestamp_test.rb +504 -0
  367. data/test/cases/touch_later_test.rb +123 -0
  368. data/test/cases/transaction_callbacks_test.rb +772 -0
  369. data/test/cases/transaction_isolation_test.rb +106 -0
  370. data/test/cases/transactions_test.rb +1285 -0
  371. data/test/cases/type/adapter_specific_registry_test.rb +145 -0
  372. data/test/cases/type/date_time_test.rb +16 -0
  373. data/test/cases/type/integer_test.rb +29 -0
  374. data/test/cases/type/string_test.rb +24 -0
  375. data/test/cases/type/time_test.rb +28 -0
  376. data/test/cases/type/type_map_test.rb +178 -0
  377. data/test/cases/type/unsigned_integer_test.rb +19 -0
  378. data/test/cases/type_test.rb +41 -0
  379. data/test/cases/types_test.rb +26 -0
  380. data/test/cases/unconnected_test.rb +46 -0
  381. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  382. data/test/cases/validations/absence_validation_test.rb +75 -0
  383. data/test/cases/validations/association_validation_test.rb +99 -0
  384. data/test/cases/validations/i18n_generate_message_validation_test.rb +102 -0
  385. data/test/cases/validations/i18n_validation_test.rb +87 -0
  386. data/test/cases/validations/length_validation_test.rb +80 -0
  387. data/test/cases/validations/numericality_validation_test.rb +181 -0
  388. data/test/cases/validations/presence_validation_test.rb +105 -0
  389. data/test/cases/validations/uniqueness_validation_test.rb +618 -0
  390. data/test/cases/validations_repair_helper.rb +21 -0
  391. data/test/cases/validations_test.rb +229 -0
  392. data/test/cases/view_test.rb +222 -0
  393. data/test/cases/yaml_serialization_test.rb +166 -0
  394. data/test/config.example.yml +97 -0
  395. data/test/config.rb +7 -0
  396. data/test/config.yml +220 -0
  397. data/test/connections/native_ibm_db/connection.rb +44 -0
  398. data/test/fixtures/accounts.yml +29 -0
  399. data/test/fixtures/admin/accounts.yml +2 -0
  400. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  401. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  402. data/test/fixtures/admin/users.yml +10 -0
  403. data/test/fixtures/all/admin +1 -0
  404. data/test/fixtures/all/developers.yml +0 -0
  405. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  406. data/test/fixtures/all/people.yml +0 -0
  407. data/test/fixtures/all/tasks.yml +0 -0
  408. data/test/fixtures/author_addresses.yml +11 -0
  409. data/test/fixtures/author_favorites.yml +4 -0
  410. data/test/fixtures/authors.yml +17 -0
  411. data/test/fixtures/bad_posts.yml +9 -0
  412. data/test/fixtures/binaries.yml +137 -0
  413. data/test/fixtures/books.yml +38 -0
  414. data/test/fixtures/bulbs.yml +5 -0
  415. data/test/fixtures/cars.yml +9 -0
  416. data/test/fixtures/categories/special_categories.yml +9 -0
  417. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  418. data/test/fixtures/categories.yml +19 -0
  419. data/test/fixtures/categories_ordered.yml +7 -0
  420. data/test/fixtures/categories_posts.yml +34 -0
  421. data/test/fixtures/categorizations.yml +23 -0
  422. data/test/fixtures/citations.yml +5 -0
  423. data/test/fixtures/clubs.yml +8 -0
  424. data/test/fixtures/collections.yml +3 -0
  425. data/test/fixtures/colleges.yml +3 -0
  426. data/test/fixtures/comments.yml +72 -0
  427. data/test/fixtures/companies.yml +72 -0
  428. data/test/fixtures/computers.yml +12 -0
  429. data/test/fixtures/content.yml +3 -0
  430. data/test/fixtures/content_positions.yml +3 -0
  431. data/test/fixtures/courses.yml +8 -0
  432. data/test/fixtures/customers.yml +35 -0
  433. data/test/fixtures/dashboards.yml +6 -0
  434. data/test/fixtures/dead_parrots.yml +5 -0
  435. data/test/fixtures/developers.yml +22 -0
  436. data/test/fixtures/developers_projects.yml +17 -0
  437. data/test/fixtures/dog_lovers.yml +7 -0
  438. data/test/fixtures/dogs.yml +4 -0
  439. data/test/fixtures/doubloons.yml +3 -0
  440. data/test/fixtures/edges.yml +5 -0
  441. data/test/fixtures/entrants.yml +14 -0
  442. data/test/fixtures/essays.yml +16 -0
  443. data/test/fixtures/faces.yml +11 -0
  444. data/test/fixtures/fk_test_has_fk.yml +3 -0
  445. data/test/fixtures/fk_test_has_pk.yml +2 -0
  446. data/test/fixtures/friendships.yml +4 -0
  447. data/test/fixtures/funny_jokes.yml +10 -0
  448. data/test/fixtures/humans.yml +5 -0
  449. data/test/fixtures/interests.yml +33 -0
  450. data/test/fixtures/items.yml +3 -0
  451. data/test/fixtures/jobs.yml +7 -0
  452. data/test/fixtures/legacy_things.yml +3 -0
  453. data/test/fixtures/live_parrots.yml +4 -0
  454. data/test/fixtures/mateys.yml +4 -0
  455. data/test/fixtures/member_details.yml +8 -0
  456. data/test/fixtures/member_types.yml +6 -0
  457. data/test/fixtures/members.yml +11 -0
  458. data/test/fixtures/memberships.yml +41 -0
  459. data/test/fixtures/men.yml +5 -0
  460. data/test/fixtures/minimalistics.yml +5 -0
  461. data/test/fixtures/minivans.yml +5 -0
  462. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  463. data/test/fixtures/mixins.yml +29 -0
  464. data/test/fixtures/movies.yml +7 -0
  465. data/test/fixtures/naked/yml/accounts.yml +1 -0
  466. data/test/fixtures/naked/yml/companies.yml +1 -0
  467. data/test/fixtures/naked/yml/courses.yml +1 -0
  468. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  469. data/test/fixtures/naked/yml/parrots.yml +3 -0
  470. data/test/fixtures/naked/yml/trees.yml +3 -0
  471. data/test/fixtures/nodes.yml +29 -0
  472. data/test/fixtures/organizations.yml +5 -0
  473. data/test/fixtures/other_books.yml +26 -0
  474. data/test/fixtures/other_comments.yml +6 -0
  475. data/test/fixtures/other_dogs.yml +2 -0
  476. data/test/fixtures/other_posts.yml +8 -0
  477. data/test/fixtures/other_topics.yml +42 -0
  478. data/test/fixtures/owners.yml +9 -0
  479. data/test/fixtures/parrots.yml +33 -0
  480. data/test/fixtures/parrots_pirates.yml +7 -0
  481. data/test/fixtures/people.yml +24 -0
  482. data/test/fixtures/peoples_treasures.yml +3 -0
  483. data/test/fixtures/pets.yml +19 -0
  484. data/test/fixtures/pirates.yml +15 -0
  485. data/test/fixtures/posts.yml +88 -0
  486. data/test/fixtures/price_estimates.yml +16 -0
  487. data/test/fixtures/products.yml +4 -0
  488. data/test/fixtures/projects.yml +7 -0
  489. data/test/fixtures/randomly_named_a9.yml +7 -0
  490. data/test/fixtures/ratings.yml +14 -0
  491. data/test/fixtures/readers.yml +17 -0
  492. data/test/fixtures/references.yml +17 -0
  493. data/test/fixtures/reserved_words/distinct.yml +5 -0
  494. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  495. data/test/fixtures/reserved_words/group.yml +14 -0
  496. data/test/fixtures/reserved_words/select.yml +8 -0
  497. data/test/fixtures/reserved_words/values.yml +7 -0
  498. data/test/fixtures/ships.yml +6 -0
  499. data/test/fixtures/speedometers.yml +8 -0
  500. data/test/fixtures/sponsors.yml +15 -0
  501. data/test/fixtures/strict_zines.yml +2 -0
  502. data/test/fixtures/string_key_objects.yml +7 -0
  503. data/test/fixtures/subscribers.yml +11 -0
  504. data/test/fixtures/subscriptions.yml +12 -0
  505. data/test/fixtures/taggings.yml +78 -0
  506. data/test/fixtures/tags.yml +11 -0
  507. data/test/fixtures/tasks.yml +7 -0
  508. data/test/fixtures/teapots.yml +3 -0
  509. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  510. data/test/fixtures/to_be_linked/users.yml +10 -0
  511. data/test/fixtures/topics.yml +49 -0
  512. data/test/fixtures/toys.yml +14 -0
  513. data/test/fixtures/traffic_lights.yml +10 -0
  514. data/test/fixtures/treasures.yml +10 -0
  515. data/test/fixtures/trees.yml +3 -0
  516. data/test/fixtures/uuid_children.yml +3 -0
  517. data/test/fixtures/uuid_parents.yml +2 -0
  518. data/test/fixtures/variants.yml +4 -0
  519. data/test/fixtures/vegetables.yml +20 -0
  520. data/test/fixtures/vertices.yml +4 -0
  521. data/test/fixtures/warehouse-things.yml +3 -0
  522. data/test/fixtures/warehouse_things.yml +3 -0
  523. data/test/fixtures/zines.yml +5 -0
  524. data/test/ibm_db_test.rb +25 -0
  525. data/test/migrations/10_urban/9_add_expressions.rb +13 -0
  526. data/test/migrations/decimal/1_give_me_big_numbers.rb +17 -0
  527. data/test/migrations/magic/1_currencies_have_symbols.rb +13 -0
  528. data/test/migrations/missing/1000_people_have_middle_names.rb +11 -0
  529. data/test/migrations/missing/1_people_have_last_names.rb +11 -0
  530. data/test/migrations/missing/3_we_need_reminders.rb +14 -0
  531. data/test/migrations/missing/4_innocent_jointable.rb +14 -0
  532. data/test/migrations/rename/1_we_need_things.rb +13 -0
  533. data/test/migrations/rename/2_rename_things.rb +11 -0
  534. data/test/migrations/to_copy/1_people_have_hobbies.rb +11 -0
  535. data/test/migrations/to_copy/2_people_have_descriptions.rb +11 -0
  536. data/test/migrations/to_copy2/1_create_articles.rb +9 -0
  537. data/test/migrations/to_copy2/2_create_comments.rb +9 -0
  538. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +11 -0
  539. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +11 -0
  540. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +11 -0
  541. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +9 -0
  542. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +9 -0
  543. data/test/migrations/valid/1_valid_people_have_last_names.rb +11 -0
  544. data/test/migrations/valid/2_we_need_reminders.rb +14 -0
  545. data/test/migrations/valid/3_innocent_jointable.rb +14 -0
  546. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +11 -0
  547. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +14 -0
  548. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +14 -0
  549. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +11 -0
  550. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +14 -0
  551. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +14 -0
  552. data/test/migrations/version_check/20131219224947_migration_version_check.rb +10 -0
  553. data/test/models/account.rb +46 -0
  554. data/test/models/admin/account.rb +5 -0
  555. data/test/models/admin/randomly_named_c1.rb +9 -0
  556. data/test/models/admin/user.rb +48 -0
  557. data/test/models/admin.rb +7 -0
  558. data/test/models/aircraft.rb +7 -0
  559. data/test/models/arunit2_model.rb +5 -0
  560. data/test/models/author.rb +260 -0
  561. data/test/models/auto_id.rb +6 -0
  562. data/test/models/autoloadable/extra_firm.rb +4 -0
  563. data/test/models/binary.rb +4 -0
  564. data/test/models/binary_field.rb +6 -0
  565. data/test/models/bird.rb +24 -0
  566. data/test/models/book.rb +33 -0
  567. data/test/models/book_destroy_async.rb +24 -0
  568. data/test/models/boolean.rb +7 -0
  569. data/test/models/bulb.rb +61 -0
  570. data/test/models/cake_designer.rb +5 -0
  571. data/test/models/car.rb +36 -0
  572. data/test/models/carrier.rb +4 -0
  573. data/test/models/cart.rb +5 -0
  574. data/test/models/cat.rb +12 -0
  575. data/test/models/categorization.rb +21 -0
  576. data/test/models/category.rb +47 -0
  577. data/test/models/chef.rb +10 -0
  578. data/test/models/citation.rb +7 -0
  579. data/test/models/club.rb +28 -0
  580. data/test/models/college.rb +12 -0
  581. data/test/models/column.rb +5 -0
  582. data/test/models/column_name.rb +5 -0
  583. data/test/models/comment.rb +98 -0
  584. data/test/models/company.rb +226 -0
  585. data/test/models/company_in_module.rb +99 -0
  586. data/test/models/computer.rb +5 -0
  587. data/test/models/contact.rb +43 -0
  588. data/test/models/content.rb +42 -0
  589. data/test/models/contract.rb +38 -0
  590. data/test/models/country.rb +5 -0
  591. data/test/models/course.rb +8 -0
  592. data/test/models/customer.rb +85 -0
  593. data/test/models/customer_carrier.rb +16 -0
  594. data/test/models/dashboard.rb +5 -0
  595. data/test/models/default.rb +4 -0
  596. data/test/models/department.rb +6 -0
  597. data/test/models/destroy_async_parent.rb +15 -0
  598. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  599. data/test/models/developer.rb +341 -0
  600. data/test/models/dl_keyed_belongs_to.rb +13 -0
  601. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  602. data/test/models/dl_keyed_has_many.rb +5 -0
  603. data/test/models/dl_keyed_has_many_through.rb +5 -0
  604. data/test/models/dl_keyed_has_one.rb +5 -0
  605. data/test/models/dl_keyed_join.rb +10 -0
  606. data/test/models/dog.rb +7 -0
  607. data/test/models/dog_lover.rb +7 -0
  608. data/test/models/doubloon.rb +14 -0
  609. data/test/models/drink_designer.rb +20 -0
  610. data/test/models/edge.rb +7 -0
  611. data/test/models/electron.rb +7 -0
  612. data/test/models/engine.rb +5 -0
  613. data/test/models/entrant.rb +5 -0
  614. data/test/models/entry.rb +5 -0
  615. data/test/models/essay.rb +8 -0
  616. data/test/models/essay_destroy_async.rb +12 -0
  617. data/test/models/event.rb +5 -0
  618. data/test/models/eye.rb +39 -0
  619. data/test/models/face.rb +17 -0
  620. data/test/models/family.rb +6 -0
  621. data/test/models/family_tree.rb +6 -0
  622. data/test/models/friendship.rb +8 -0
  623. data/test/models/frog.rb +8 -0
  624. data/test/models/guid.rb +4 -0
  625. data/test/models/guitar.rb +6 -0
  626. data/test/models/hotel.rb +13 -0
  627. data/test/models/human.rb +39 -0
  628. data/test/models/image.rb +5 -0
  629. data/test/models/interest.rb +16 -0
  630. data/test/models/invoice.rb +6 -0
  631. data/test/models/item.rb +9 -0
  632. data/test/models/job.rb +9 -0
  633. data/test/models/joke.rb +9 -0
  634. data/test/models/keyboard.rb +5 -0
  635. data/test/models/legacy_thing.rb +5 -0
  636. data/test/models/lesson.rb +13 -0
  637. data/test/models/line_item.rb +5 -0
  638. data/test/models/liquid.rb +6 -0
  639. data/test/models/man.rb +11 -0
  640. data/test/models/matey.rb +6 -0
  641. data/test/models/measurement.rb +4 -0
  642. data/test/models/member.rb +45 -0
  643. data/test/models/member_detail.rb +11 -0
  644. data/test/models/member_type.rb +5 -0
  645. data/test/models/membership.rb +38 -0
  646. data/test/models/mentor.rb +5 -0
  647. data/test/models/message.rb +5 -0
  648. data/test/models/minimalistic.rb +4 -0
  649. data/test/models/minivan.rb +10 -0
  650. data/test/models/mixed_case_monkey.rb +5 -0
  651. data/test/models/mocktail_designer.rb +2 -0
  652. data/test/models/molecule.rb +8 -0
  653. data/test/models/mouse.rb +6 -0
  654. data/test/models/movie.rb +7 -0
  655. data/test/models/node.rb +7 -0
  656. data/test/models/non_primary_key.rb +4 -0
  657. data/test/models/notification.rb +5 -0
  658. data/test/models/numeric_data.rb +12 -0
  659. data/test/models/order.rb +6 -0
  660. data/test/models/organization.rb +16 -0
  661. data/test/models/other_dog.rb +7 -0
  662. data/test/models/owner.rb +39 -0
  663. data/test/models/parrot.rb +36 -0
  664. data/test/models/person.rb +147 -0
  665. data/test/models/personal_legacy_thing.rb +6 -0
  666. data/test/models/pet.rb +20 -0
  667. data/test/models/pet_treasure.rb +8 -0
  668. data/test/models/pirate.rb +116 -0
  669. data/test/models/possession.rb +5 -0
  670. data/test/models/post.rb +371 -0
  671. data/test/models/price_estimate.rb +14 -0
  672. data/test/models/professor.rb +7 -0
  673. data/test/models/project.rb +42 -0
  674. data/test/models/publisher/article.rb +6 -0
  675. data/test/models/publisher/magazine.rb +5 -0
  676. data/test/models/publisher.rb +4 -0
  677. data/test/models/randomly_named_c1.rb +5 -0
  678. data/test/models/rating.rb +8 -0
  679. data/test/models/reader.rb +25 -0
  680. data/test/models/recipe.rb +5 -0
  681. data/test/models/record.rb +4 -0
  682. data/test/models/reference.rb +25 -0
  683. data/test/models/reply.rb +79 -0
  684. data/test/models/room.rb +6 -0
  685. data/test/models/section.rb +6 -0
  686. data/test/models/seminar.rb +6 -0
  687. data/test/models/session.rb +6 -0
  688. data/test/models/ship.rb +42 -0
  689. data/test/models/ship_part.rb +10 -0
  690. data/test/models/shop.rb +19 -0
  691. data/test/models/shop_account.rb +8 -0
  692. data/test/models/speedometer.rb +8 -0
  693. data/test/models/sponsor.rb +10 -0
  694. data/test/models/squeak.rb +6 -0
  695. data/test/models/strict_zine.rb +7 -0
  696. data/test/models/string_key_object.rb +5 -0
  697. data/test/models/student.rb +6 -0
  698. data/test/models/subject.rb +16 -0
  699. data/test/models/subscriber.rb +10 -0
  700. data/test/models/subscription.rb +8 -0
  701. data/test/models/tag.rb +16 -0
  702. data/test/models/tagging.rb +20 -0
  703. data/test/models/task.rb +7 -0
  704. data/test/models/topic.rb +153 -0
  705. data/test/models/toy.rb +10 -0
  706. data/test/models/traffic_light.rb +6 -0
  707. data/test/models/treasure.rb +16 -0
  708. data/test/models/treaty.rb +5 -0
  709. data/test/models/tree.rb +5 -0
  710. data/test/models/tuning_peg.rb +6 -0
  711. data/test/models/tyre.rb +13 -0
  712. data/test/models/user.rb +22 -0
  713. data/test/models/uuid_child.rb +5 -0
  714. data/test/models/uuid_item.rb +8 -0
  715. data/test/models/uuid_parent.rb +5 -0
  716. data/test/models/vegetables.rb +33 -0
  717. data/test/models/vehicle.rb +7 -0
  718. data/test/models/vertex.rb +11 -0
  719. data/test/models/warehouse_thing.rb +7 -0
  720. data/test/models/wheel.rb +5 -0
  721. data/test/models/without_table.rb +5 -0
  722. data/test/models/zine.rb +5 -0
  723. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  724. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  725. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  726. data/test/schema/mysql2_specific_schema.rb +82 -0
  727. data/test/schema/oracle_specific_schema.rb +38 -0
  728. data/test/schema/postgresql_specific_schema.rb +125 -0
  729. data/test/schema/schema.rb +1237 -0
  730. data/test/schema/schema.rb.original +1057 -0
  731. data/test/schema/sqlite_specific_schema.rb +11 -0
  732. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  733. data/test/support/config.rb +43 -0
  734. data/test/support/connection.rb +29 -0
  735. data/test/support/connection_helper.rb +16 -0
  736. data/test/support/ddl_helper.rb +10 -0
  737. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  738. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  739. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  740. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  741. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  742. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  743. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  744. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  745. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  746. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  747. data/test/support/schema_dumping_helper.rb +22 -0
  748. data/test/support/stubs/strong_parameters.rb +40 -0
  749. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  750. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  751. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  752. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  753. 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