ibm_db 5.2.0-x86-mingw32 → 5.4.0-x86-mingw32

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