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,787 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thread"
4
+ require "cases/helper"
5
+ require "models/person"
6
+ require "models/job"
7
+ require "models/reader"
8
+ require "models/ship"
9
+ require "models/legacy_thing"
10
+ require "models/personal_legacy_thing"
11
+ require "models/reference"
12
+ require "models/string_key_object"
13
+ require "models/car"
14
+ require "models/bulb"
15
+ require "models/engine"
16
+ require "models/wheel"
17
+ require "models/treasure"
18
+ require "models/frog"
19
+
20
+ class LockWithoutDefault < ActiveRecord::Base; end
21
+
22
+ class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
23
+ self.table_name = :lock_without_defaults_cust
24
+ column_defaults # to test @column_defaults caching.
25
+ self.locking_column = :custom_lock_version
26
+ end
27
+
28
+ class ReadonlyNameShip < Ship
29
+ attr_readonly :name
30
+ end
31
+
32
+ class OptimisticLockingTest < ActiveRecord::TestCase
33
+ fixtures :people, :legacy_things, :references, :string_key_objects, :peoples_treasures
34
+
35
+ def test_quote_value_passed_lock_col
36
+ p1 = Person.find(1)
37
+ assert_equal 0, p1.lock_version
38
+
39
+ p1.first_name = "anika2"
40
+ p1.save!
41
+
42
+ assert_equal 1, p1.lock_version
43
+ end
44
+
45
+ def test_non_integer_lock_existing
46
+ s1 = StringKeyObject.find("record1")
47
+ s2 = StringKeyObject.find("record1")
48
+ assert_equal 0, s1.lock_version
49
+ assert_equal 0, s2.lock_version
50
+
51
+ s1.name = "updated record"
52
+ s1.save!
53
+ assert_equal 1, s1.lock_version
54
+ assert_equal 0, s2.lock_version
55
+
56
+ s2.name = "doubly updated record"
57
+ assert_raise(ActiveRecord::StaleObjectError) { s2.save! }
58
+ end
59
+
60
+ def test_non_integer_lock_destroy
61
+ s1 = StringKeyObject.find("record1")
62
+ s2 = StringKeyObject.find("record1")
63
+ assert_equal 0, s1.lock_version
64
+ assert_equal 0, s2.lock_version
65
+
66
+ s1.name = "updated record"
67
+ s1.save!
68
+ assert_equal 1, s1.lock_version
69
+ assert_equal 0, s2.lock_version
70
+ assert_raise(ActiveRecord::StaleObjectError) { s2.destroy }
71
+
72
+ assert s1.destroy
73
+ assert_predicate s1, :frozen?
74
+ assert_predicate s1, :destroyed?
75
+ assert_raises(ActiveRecord::RecordNotFound) { StringKeyObject.find("record1") }
76
+ end
77
+
78
+ def test_lock_existing
79
+ p1 = Person.find(1)
80
+ p2 = Person.find(1)
81
+ assert_equal 0, p1.lock_version
82
+ assert_equal 0, p2.lock_version
83
+
84
+ p1.first_name = "stu"
85
+ p1.save!
86
+ assert_equal 1, p1.lock_version
87
+ assert_equal 0, p2.lock_version
88
+
89
+ p2.first_name = "sue"
90
+ assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
91
+ end
92
+
93
+ # See Lighthouse ticket #1966
94
+ def test_lock_destroy
95
+ p1 = Person.find(1)
96
+ p2 = Person.find(1)
97
+ assert_equal 0, p1.lock_version
98
+ assert_equal 0, p2.lock_version
99
+
100
+ p1.first_name = "stu"
101
+ p1.save!
102
+ assert_equal 1, p1.lock_version
103
+ assert_equal 0, p2.lock_version
104
+
105
+ assert_raises(ActiveRecord::StaleObjectError) { p2.destroy }
106
+
107
+ assert p1.destroy
108
+ assert_predicate p1, :frozen?
109
+ assert_predicate p1, :destroyed?
110
+ assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) }
111
+ end
112
+
113
+ def test_lock_repeating
114
+ p1 = Person.find(1)
115
+ p2 = Person.find(1)
116
+ assert_equal 0, p1.lock_version
117
+ assert_equal 0, p2.lock_version
118
+
119
+ p1.first_name = "stu"
120
+ p1.save!
121
+ assert_equal 1, p1.lock_version
122
+ assert_equal 0, p2.lock_version
123
+
124
+ p2.first_name = "sue"
125
+ assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
126
+ p2.first_name = "sue2"
127
+ assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
128
+ end
129
+
130
+ def test_lock_new
131
+ p1 = Person.new(first_name: "anika")
132
+ assert_equal 0, p1.lock_version
133
+
134
+ p1.first_name = "anika2"
135
+ p1.save!
136
+ p2 = Person.find(p1.id)
137
+ assert_equal 0, p1.lock_version
138
+ assert_equal 0, p2.lock_version
139
+
140
+ p1.first_name = "anika3"
141
+ p1.save!
142
+ assert_equal 1, p1.lock_version
143
+ assert_equal 0, p2.lock_version
144
+
145
+ p2.first_name = "sue"
146
+ assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
147
+ end
148
+
149
+ def test_lock_exception_record
150
+ p1 = Person.new(first_name: "mira")
151
+ assert_equal 0, p1.lock_version
152
+
153
+ p1.first_name = "mira2"
154
+ p1.save!
155
+ p2 = Person.find(p1.id)
156
+ assert_equal 0, p1.lock_version
157
+ assert_equal 0, p2.lock_version
158
+
159
+ p1.first_name = "mira3"
160
+ p1.save!
161
+
162
+ p2.first_name = "sue"
163
+ error = assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
164
+ assert_same error.record, p2
165
+ end
166
+
167
+ def test_lock_new_when_explicitly_passing_nil
168
+ p1 = Person.new(first_name: "anika", lock_version: nil)
169
+ p1.save!
170
+ assert_equal 0, p1.lock_version
171
+ end
172
+
173
+ def test_lock_new_when_explicitly_passing_value
174
+ p1 = Person.new(first_name: "Douglas Adams", lock_version: 42)
175
+ p1.save!
176
+ assert_equal 42, p1.lock_version
177
+ end
178
+
179
+ def test_touch_existing_lock
180
+ p1 = Person.find(1)
181
+ assert_equal 0, p1.lock_version
182
+
183
+ p1.touch
184
+ assert_equal 1, p1.lock_version
185
+ assert_not_predicate p1, :changed?, "Changes should have been cleared"
186
+ assert_predicate p1, :saved_changes?
187
+ assert_equal ["lock_version", "updated_at"], p1.saved_changes.keys.sort
188
+ end
189
+
190
+ def test_touch_stale_object
191
+ person = Person.create!(first_name: "Mehmet Emin")
192
+ stale_person = Person.find(person.id)
193
+ person.update_attribute(:gender, "M")
194
+
195
+ assert_raises(ActiveRecord::StaleObjectError) do
196
+ stale_person.touch
197
+ end
198
+
199
+ assert_not_predicate stale_person, :saved_changes?
200
+ end
201
+
202
+ def test_update_with_dirty_primary_key
203
+ assert_raises(ActiveRecord::RecordNotUnique) do
204
+ person = Person.find(1)
205
+ person.id = 2
206
+ person.save!
207
+ end
208
+
209
+ person = Person.find(1)
210
+ person.id = 42
211
+ person.save!
212
+
213
+ assert Person.find(42)
214
+ assert_raises(ActiveRecord::RecordNotFound) do
215
+ Person.find(1)
216
+ end
217
+ end
218
+
219
+ def test_delete_with_dirty_primary_key
220
+ person = Person.find(1)
221
+ person.id = 2
222
+ person.delete
223
+
224
+ assert Person.find(2)
225
+ assert_raises(ActiveRecord::RecordNotFound) do
226
+ Person.find(1)
227
+ end
228
+ end
229
+
230
+ def test_destroy_with_dirty_primary_key
231
+ person = Person.find(1)
232
+ person.id = 2
233
+ person.destroy
234
+
235
+ assert Person.find(2)
236
+ assert_raises(ActiveRecord::RecordNotFound) do
237
+ Person.find(1)
238
+ end
239
+ end
240
+
241
+ def test_explicit_update_lock_column_raise_error
242
+ person = Person.find(1)
243
+
244
+ assert_raises(ActiveRecord::StaleObjectError) do
245
+ person.first_name = "Douglas Adams"
246
+ person.lock_version = 42
247
+
248
+ assert_predicate person, :lock_version_changed?
249
+
250
+ person.save
251
+ end
252
+ end
253
+
254
+ def test_lock_column_name_existing
255
+ t1 = LegacyThing.find(1)
256
+ t2 = LegacyThing.find(1)
257
+ assert_equal 0, t1.version
258
+ assert_equal 0, t2.version
259
+
260
+ t1.tps_report_number = 700
261
+ t1.save!
262
+ assert_equal 1, t1.version
263
+ assert_equal 0, t2.version
264
+
265
+ t2.tps_report_number = 800
266
+ assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
267
+ end
268
+
269
+ def test_lock_column_is_mass_assignable
270
+ p1 = Person.create(first_name: "bianca")
271
+ assert_equal 0, p1.lock_version
272
+ assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
273
+
274
+ p1.first_name = "bianca2"
275
+ p1.save!
276
+ assert_equal 1, p1.lock_version
277
+ assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
278
+ end
279
+
280
+ def test_lock_without_default_sets_version_to_zero
281
+ t1 = LockWithoutDefault.new
282
+
283
+ assert_equal 0, t1.lock_version
284
+ assert_nil t1.lock_version_before_type_cast
285
+
286
+ t1.save!
287
+ t1.reload
288
+
289
+ assert_equal 0, t1.lock_version
290
+ assert_equal 0, t1.lock_version_before_type_cast
291
+ end
292
+
293
+ def test_touch_existing_lock_without_default_should_work_with_null_in_the_database
294
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
295
+ t1 = LockWithoutDefault.last
296
+
297
+ assert_equal 0, t1.lock_version
298
+ assert_nil t1.lock_version_before_type_cast
299
+
300
+ t1.touch
301
+
302
+ assert_equal 1, t1.lock_version
303
+ assert_not_predicate t1, :changed?
304
+ assert_predicate t1, :saved_changes?
305
+ assert_equal ["lock_version", "updated_at"], t1.saved_changes.keys.sort
306
+ end
307
+
308
+ def test_touch_stale_object_with_lock_without_default
309
+ t1 = LockWithoutDefault.create!(title: "title1")
310
+ stale_object = LockWithoutDefault.find(t1.id)
311
+
312
+ t1.update!(title: "title2")
313
+
314
+ assert_raises(ActiveRecord::StaleObjectError) do
315
+ stale_object.touch
316
+ end
317
+
318
+ assert_not_predicate stale_object, :saved_changes?
319
+ end
320
+
321
+ def test_lock_without_default_should_work_with_null_in_the_database
322
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
323
+ t1 = LockWithoutDefault.last
324
+ t2 = LockWithoutDefault.find(t1.id)
325
+
326
+ assert_equal 0, t1.lock_version
327
+ assert_nil t1.lock_version_before_type_cast
328
+ assert_equal 0, t2.lock_version
329
+ assert_nil t2.lock_version_before_type_cast
330
+
331
+ t1.title = "new title1"
332
+ t2.title = "new title2"
333
+
334
+ assert_nothing_raised { t1.save! }
335
+ assert_equal 1, t1.lock_version
336
+ assert_equal "new title1", t1.title
337
+
338
+ assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
339
+ assert_equal 0, t2.lock_version
340
+ assert_equal "new title2", t2.title
341
+ end
342
+
343
+ def test_update_with_lock_version_without_default_should_work_on_dirty_value_before_type_cast
344
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
345
+ t1 = LockWithoutDefault.last
346
+
347
+ assert_equal 0, t1.lock_version
348
+ assert_nil t1.lock_version_before_type_cast
349
+
350
+ t1.lock_version = t1.lock_version
351
+
352
+ assert_equal 0, t1.lock_version
353
+ assert_equal 0, t1.lock_version_before_type_cast
354
+
355
+ assert_nothing_raised { t1.update!(title: "new title1") }
356
+ assert_equal 1, t1.lock_version
357
+ assert_equal "new title1", t1.title
358
+ end
359
+
360
+ def test_destroy_with_lock_version_without_default_should_work_on_dirty_value_before_type_cast
361
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
362
+ t1 = LockWithoutDefault.last
363
+
364
+ assert_equal 0, t1.lock_version
365
+ assert_nil t1.lock_version_before_type_cast
366
+
367
+ t1.lock_version = t1.lock_version
368
+
369
+ assert_equal 0, t1.lock_version
370
+ assert_equal 0, t1.lock_version_before_type_cast
371
+
372
+ assert_nothing_raised { t1.destroy! }
373
+ assert_predicate t1, :destroyed?
374
+ end
375
+
376
+ def test_lock_without_default_queries_count
377
+ t1 = LockWithoutDefault.create(title: "title1")
378
+
379
+ assert_equal "title1", t1.title
380
+ assert_equal 0, t1.lock_version
381
+
382
+ assert_queries(1) { t1.update(title: "title2") }
383
+
384
+ t1.reload
385
+ assert_equal "title2", t1.title
386
+ assert_equal 1, t1.lock_version
387
+
388
+ t2 = LockWithoutDefault.new(title: "title1")
389
+
390
+ assert_queries(1) { t2.save! }
391
+
392
+ t2.reload
393
+ assert_equal "title1", t2.title
394
+ assert_equal 0, t2.lock_version
395
+ end
396
+
397
+ def test_lock_with_custom_column_without_default_sets_version_to_zero
398
+ t1 = LockWithCustomColumnWithoutDefault.new
399
+
400
+ assert_equal 0, t1.custom_lock_version
401
+ assert_nil t1.custom_lock_version_before_type_cast
402
+
403
+ t1.save!
404
+ t1.reload
405
+
406
+ assert_equal 0, t1.custom_lock_version
407
+ assert_equal 0, t1.custom_lock_version_before_type_cast
408
+ end
409
+
410
+ def test_lock_with_custom_column_without_default_should_work_with_null_in_the_database
411
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults_cust(title) VALUES('title1')")
412
+
413
+ t1 = LockWithCustomColumnWithoutDefault.last
414
+ t2 = LockWithCustomColumnWithoutDefault.find(t1.id)
415
+
416
+ assert_equal 0, t1.custom_lock_version
417
+ assert_nil t1.custom_lock_version_before_type_cast
418
+ assert_equal 0, t2.custom_lock_version
419
+ assert_nil t2.custom_lock_version_before_type_cast
420
+
421
+ t1.title = "new title1"
422
+ t2.title = "new title2"
423
+
424
+ assert_nothing_raised { t1.save! }
425
+ assert_equal 1, t1.custom_lock_version
426
+ assert_equal "new title1", t1.title
427
+
428
+ assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
429
+ assert_equal 0, t2.custom_lock_version
430
+ assert_equal "new title2", t2.title
431
+ end
432
+
433
+ def test_lock_with_custom_column_without_default_queries_count
434
+ t1 = LockWithCustomColumnWithoutDefault.create(title: "title1")
435
+
436
+ assert_equal "title1", t1.title
437
+ assert_equal 0, t1.custom_lock_version
438
+
439
+ assert_queries(1) { t1.update(title: "title2") }
440
+
441
+ t1.reload
442
+ assert_equal "title2", t1.title
443
+ assert_equal 1, t1.custom_lock_version
444
+
445
+ t2 = LockWithCustomColumnWithoutDefault.new(title: "title1")
446
+
447
+ assert_queries(1) { t2.save! }
448
+
449
+ t2.reload
450
+ assert_equal "title1", t2.title
451
+ assert_equal 0, t2.custom_lock_version
452
+ end
453
+
454
+ def test_readonly_attributes
455
+ assert_equal Set.new([ "name" ]), ReadonlyNameShip.readonly_attributes
456
+
457
+ s = ReadonlyNameShip.create(name: "unchangeable name")
458
+ s.reload
459
+ assert_equal "unchangeable name", s.name
460
+
461
+ s.update(name: "changed name")
462
+ s.reload
463
+ assert_equal "unchangeable name", s.name
464
+ end
465
+
466
+ def test_quote_table_name
467
+ ref = references(:michael_magician)
468
+ ref.favourite = !ref.favourite
469
+ assert ref.save
470
+ end
471
+
472
+ # Useful for partial updates, don't only update the lock_version if there
473
+ # is nothing else being updated.
474
+ def test_update_without_attributes_does_not_only_update_lock_version
475
+ assert_nothing_raised do
476
+ p1 = Person.create!(first_name: "anika")
477
+ lock_version = p1.lock_version
478
+ p1.save
479
+ p1.reload
480
+ assert_equal lock_version, p1.lock_version
481
+ end
482
+ end
483
+
484
+ def test_counter_cache_with_touch_and_lock_version
485
+ car = Car.create!
486
+
487
+ assert_equal 0, car.wheels_count
488
+ assert_equal 0, car.lock_version
489
+
490
+ previously_updated_at = car.updated_at
491
+ previously_wheels_owned_at = car.wheels_owned_at
492
+ travel(1.second) do
493
+ Wheel.create!(wheelable: car)
494
+ end
495
+
496
+ assert_equal 1, car.reload.wheels_count
497
+ assert_equal 1, car.lock_version
498
+ assert_operator previously_updated_at, :<, car.updated_at
499
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
500
+
501
+ previously_updated_at = car.updated_at
502
+ previously_wheels_owned_at = car.wheels_owned_at
503
+ travel(2.second) do
504
+ car.wheels.first.update(size: 42)
505
+ end
506
+
507
+ assert_equal 1, car.reload.wheels_count
508
+ assert_equal 2, car.lock_version
509
+ assert_operator previously_updated_at, :<, car.updated_at
510
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
511
+
512
+ previously_updated_at = car.updated_at
513
+ previously_wheels_owned_at = car.wheels_owned_at
514
+ travel(3.second) do
515
+ car.wheels.first.destroy!
516
+ end
517
+
518
+ assert_equal 0, car.reload.wheels_count
519
+ assert_equal 3, car.lock_version
520
+ assert_operator previously_updated_at, :<, car.updated_at
521
+ assert_operator previously_wheels_owned_at, :<, car.wheels_owned_at
522
+
523
+ car.wheels << Wheel.create!
524
+ assert_equal 1, car.wheels_count
525
+ assert_equal 4, car.lock_version
526
+ assert_not car.lock_version_changed?
527
+ assert_nothing_raised { car.update(name: "herbie") }
528
+ end
529
+
530
+ def test_polymorphic_destroy_with_dependencies_and_lock_version
531
+ car = Car.create!
532
+
533
+ assert_difference "car.wheels.count" do
534
+ car.wheels.create
535
+ end
536
+ assert_difference "car.wheels.count", -1 do
537
+ car.reload.destroy
538
+ end
539
+ assert_predicate car, :destroyed?
540
+ end
541
+
542
+ def test_removing_has_and_belongs_to_many_associations_upon_destroy
543
+ p = RichPerson.create! first_name: "Jon"
544
+ p.treasures.create!
545
+ assert_not_empty p.treasures
546
+ p.destroy
547
+ assert_empty p.treasures
548
+ assert_empty RichPerson.connection.select_all("SELECT * FROM peoples_treasures WHERE rich_person_id = 1")
549
+ end
550
+
551
+ def test_yaml_dumping_with_lock_column
552
+ t1 = LockWithoutDefault.new
553
+ payload = YAML.dump(t1)
554
+ t2 = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(payload) : YAML.load(payload)
555
+
556
+ assert_equal t1.attributes, t2.attributes
557
+ end
558
+ end
559
+
560
+ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
561
+ fixtures :people, :legacy_things, :references
562
+
563
+ # need to disable transactional tests, because otherwise the sqlite3
564
+ # adapter (at least) chokes when we try and change the schema in the middle
565
+ # of a test (see test_increment_counter_*).
566
+ self.use_transactional_tests = false
567
+
568
+ { lock_version: Person, custom_lock_version: LegacyThing }.each do |name, model|
569
+ define_method("test_increment_counter_updates_#{name}") do
570
+ counter_test model, 1 do |id|
571
+ model.increment_counter :test_count, id
572
+ end
573
+ end
574
+
575
+ define_method("test_decrement_counter_updates_#{name}") do
576
+ counter_test model, -1 do |id|
577
+ model.decrement_counter :test_count, id
578
+ end
579
+ end
580
+
581
+ define_method("test_update_counters_updates_#{name}") do
582
+ counter_test model, 1 do |id|
583
+ model.update_counters id, test_count: 1
584
+ end
585
+ end
586
+ end
587
+
588
+ # See Lighthouse ticket #1966
589
+ def test_destroy_dependents
590
+ # Establish dependent relationship between Person and PersonalLegacyThing
591
+ add_counter_column_to(Person, "personal_legacy_things_count")
592
+ PersonalLegacyThing.reset_column_information
593
+
594
+ # Make sure that counter incrementing doesn't cause problems
595
+ p1 = Person.new(first_name: "fjord")
596
+ p1.save!
597
+ t = PersonalLegacyThing.new(person: p1)
598
+ t.save!
599
+ p1.reload
600
+ assert_equal 1, p1.personal_legacy_things_count
601
+ assert p1.destroy
602
+ assert_equal true, p1.frozen?
603
+ assert_raises(ActiveRecord::RecordNotFound) { Person.find(p1.id) }
604
+ assert_raises(ActiveRecord::RecordNotFound) { PersonalLegacyThing.find(t.id) }
605
+ ensure
606
+ remove_counter_column_from(Person, "personal_legacy_things_count")
607
+ PersonalLegacyThing.reset_column_information
608
+ end
609
+
610
+ def test_destroy_existing_object_with_locking_column_value_null_in_the_database
611
+ ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
612
+ t1 = LockWithoutDefault.last
613
+
614
+ assert_equal 0, t1.lock_version
615
+ assert_nil t1.lock_version_before_type_cast
616
+
617
+ t1.destroy
618
+
619
+ assert_predicate t1, :destroyed?
620
+ end
621
+
622
+ def test_destroy_stale_object
623
+ t1 = LockWithoutDefault.create!(title: "title1")
624
+ stale_object = LockWithoutDefault.find(t1.id)
625
+
626
+ t1.update!(title: "title2")
627
+
628
+ assert_raises(ActiveRecord::StaleObjectError) do
629
+ stale_object.destroy!
630
+ end
631
+
632
+ assert_not_predicate stale_object, :destroyed?
633
+ end
634
+
635
+ private
636
+ def add_counter_column_to(model, col = "test_count")
637
+ model.connection.add_column model.table_name, col, :integer, null: false, default: 0
638
+ model.reset_column_information
639
+ end
640
+
641
+ def remove_counter_column_from(model, col = :test_count)
642
+ model.connection.remove_column model.table_name, col
643
+ model.reset_column_information
644
+ end
645
+
646
+ def counter_test(model, expected_count)
647
+ add_counter_column_to(model)
648
+ object = model.first
649
+ assert_equal 0, object.test_count
650
+ assert_equal 0, object.public_send(model.locking_column)
651
+ yield object.id
652
+ object.reload
653
+ assert_equal expected_count, object.test_count
654
+ assert_equal 1, object.public_send(model.locking_column)
655
+ ensure
656
+ remove_counter_column_from(model)
657
+ end
658
+ end
659
+
660
+ # TODO: test against the generated SQL since testing locking behavior itself
661
+ # is so cumbersome. Will deadlock Ruby threads if the underlying db.execute
662
+ # blocks, so separate script called by Kernel#system is needed.
663
+ # (See exec vs. async_exec in the PostgreSQL adapter.)
664
+ unless in_memory_db?
665
+ class PessimisticLockingTest < ActiveRecord::TestCase
666
+ self.use_transactional_tests = false
667
+ fixtures :people, :readers
668
+
669
+ def setup
670
+ Person.connection_pool.clear_reloadable_connections!
671
+ # Avoid introspection queries during tests.
672
+ Person.columns; Reader.columns
673
+ end
674
+
675
+ # Test typical find.
676
+ def test_sane_find_with_lock
677
+ assert_nothing_raised do
678
+ Person.transaction do
679
+ Person.lock.find(1)
680
+ end
681
+ end
682
+ end
683
+
684
+ # PostgreSQL protests SELECT ... FOR UPDATE on an outer join.
685
+ unless current_adapter?(:PostgreSQLAdapter)
686
+ # Test locked eager find.
687
+ def test_eager_find_with_lock
688
+ assert_nothing_raised do
689
+ Person.transaction do
690
+ Person.includes(:readers).lock.find(1)
691
+ end
692
+ end
693
+ end
694
+ end
695
+
696
+ def test_lock_does_not_raise_when_the_object_is_not_dirty
697
+ person = Person.find 1
698
+ assert_nothing_raised do
699
+ person.lock!
700
+ end
701
+ end
702
+
703
+ def test_lock_raises_when_the_record_is_dirty
704
+ person = Person.find 1
705
+ person.first_name = "fooman"
706
+ assert_raises(RuntimeError) do
707
+ person.lock!
708
+ end
709
+ end
710
+
711
+ def test_locking_in_after_save_callback
712
+ assert_nothing_raised do
713
+ frog = ::Frog.create(name: "Old Frog")
714
+ frog.name = "New Frog"
715
+ assert_not_deprecated do
716
+ frog.save!
717
+ end
718
+ end
719
+ end
720
+
721
+ def test_with_lock_commits_transaction
722
+ puts "Inside test_with_lock_commits_transaction"
723
+ person = Person.find 1
724
+ person.with_lock do
725
+ person.first_name = "fooman"
726
+ person.save!
727
+ end
728
+ assert_equal "fooman", person.reload.first_name
729
+ end
730
+
731
+ def test_with_lock_rolls_back_transaction
732
+ person = Person.find 1
733
+ old = person.first_name
734
+ person.with_lock do
735
+ person.first_name = "fooman"
736
+ person.save!
737
+ raise "oops"
738
+ end rescue nil
739
+ assert_equal old, person.reload.first_name
740
+ end
741
+
742
+ if current_adapter?(:PostgreSQLAdapter)
743
+ def test_lock_sending_custom_lock_statement
744
+ Person.transaction do
745
+ person = Person.find(1)
746
+ assert_sql(/LIMIT \$?\d FOR SHARE NOWAIT/) do
747
+ person.lock!("FOR SHARE NOWAIT")
748
+ end
749
+ end
750
+ end
751
+ end
752
+
753
+ def test_no_locks_no_wait
754
+ first, second = duel { Person.find 1 }
755
+ assert first.end > second.end
756
+ end
757
+
758
+ private
759
+ def duel(zzz = 5)
760
+ t0, t1, t2, t3 = nil, nil, nil, nil
761
+
762
+ a = Thread.new do
763
+ t0 = Time.now
764
+ Person.transaction do
765
+ yield
766
+ sleep zzz # block thread 2 for zzz seconds
767
+ end
768
+ t1 = Time.now
769
+ end
770
+
771
+ b = Thread.new do
772
+ sleep zzz / 2.0 # ensure thread 1 tx starts first
773
+ t2 = Time.now
774
+ Person.transaction { yield }
775
+ t3 = Time.now
776
+ end
777
+
778
+ a.join
779
+ b.join
780
+
781
+ assert t1 > t0 + zzz
782
+ assert t2 > t0
783
+ assert t3 > t2
784
+ [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
785
+ end
786
+ end
787
+ end