ibm_db 3.0.5-x86-mingw32 → 4.0.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -0
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -0
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -0
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,122 +1,112 @@
1
- require "cases/helper"
2
- require "rack"
3
-
4
- module ActiveRecord
5
- module ConnectionAdapters
6
- class ConnectionManagementTest < ActiveRecord::TestCase
7
- class App
8
- attr_reader :calls
9
- def initialize
10
- @calls = []
11
- end
12
-
13
- def call(env)
14
- @calls << env
15
- [200, {}, ['hi mom']]
16
- end
17
- end
18
-
19
- def setup
20
- @env = {}
21
- @app = App.new
22
- @management = ConnectionManagement.new(@app)
23
-
24
- # make sure we have an active connection
25
- assert ActiveRecord::Base.connection
26
- assert ActiveRecord::Base.connection_handler.active_connections?
27
- end
28
-
29
- if Process.respond_to?(:fork)
30
- def test_connection_pool_per_pid
31
- object_id = ActiveRecord::Base.connection.object_id
32
-
33
- rd, wr = IO.pipe
34
- rd.binmode
35
- wr.binmode
36
-
37
- pid = fork {
38
- rd.close
39
- wr.write Marshal.dump ActiveRecord::Base.connection.object_id
40
- wr.close
41
- exit!
42
- }
43
-
44
- wr.close
45
-
46
- Process.waitpid pid
47
- assert_not_equal object_id, Marshal.load(rd.read)
48
- rd.close
49
- end
50
- end
51
-
52
- def test_app_delegation
53
- manager = ConnectionManagement.new(@app)
54
-
55
- manager.call @env
56
- assert_equal [@env], @app.calls
57
- end
58
-
59
- def test_connections_are_active_after_call
60
- @management.call(@env)
61
- assert ActiveRecord::Base.connection_handler.active_connections?
62
- end
63
-
64
- def test_body_responds_to_each
65
- _, _, body = @management.call(@env)
66
- bits = []
67
- body.each { |bit| bits << bit }
68
- assert_equal ['hi mom'], bits
69
- end
70
-
71
- def test_connections_are_cleared_after_body_close
72
- _, _, body = @management.call(@env)
73
- body.close
74
- assert !ActiveRecord::Base.connection_handler.active_connections?
75
- end
76
-
77
- def test_active_connections_are_not_cleared_on_body_close_during_test
78
- @env['rack.test'] = true
79
- _, _, body = @management.call(@env)
80
- body.close
81
- assert ActiveRecord::Base.connection_handler.active_connections?
82
- end
83
-
84
- def test_connections_closed_if_exception
85
- app = Class.new(App) { def call(env); raise NotImplementedError; end }.new
86
- explosive = ConnectionManagement.new(app)
87
- assert_raises(NotImplementedError) { explosive.call(@env) }
88
- assert !ActiveRecord::Base.connection_handler.active_connections?
89
- end
90
-
91
- def test_connections_not_closed_if_exception_and_test
92
- @env['rack.test'] = true
93
- app = Class.new(App) { def call(env); raise; end }.new
94
- explosive = ConnectionManagement.new(app)
95
- assert_raises(RuntimeError) { explosive.call(@env) }
96
- assert ActiveRecord::Base.connection_handler.active_connections?
97
- end
98
-
99
- def test_connections_closed_if_exception_and_explicitly_not_test
100
- @env['rack.test'] = false
101
- app = Class.new(App) { def call(env); raise NotImplementedError; end }.new
102
- explosive = ConnectionManagement.new(app)
103
- assert_raises(NotImplementedError) { explosive.call(@env) }
104
- assert !ActiveRecord::Base.connection_handler.active_connections?
105
- end
106
-
107
- test "doesn't clear active connections when running in a test case" do
108
- @env['rack.test'] = true
109
- @management.call(@env)
110
- assert ActiveRecord::Base.connection_handler.active_connections?
111
- end
112
-
113
- test "proxy is polite to it's body and responds to it" do
114
- body = Class.new(String) { def to_path; "/path"; end }.new
115
- app = lambda { |_| [200, {}, body] }
116
- response_body = ConnectionManagement.new(app).call(@env)[2]
117
- assert response_body.respond_to?(:to_path)
118
- assert_equal response_body.to_path, "/path"
119
- end
120
- end
121
- end
122
- end
1
+ require "cases/helper"
2
+ require "rack"
3
+
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ class ConnectionManagementTest < ActiveRecord::TestCase
7
+ self.use_transactional_tests = false
8
+
9
+ class App
10
+ attr_reader :calls
11
+ def initialize
12
+ @calls = []
13
+ end
14
+
15
+ def call(env)
16
+ @calls << env
17
+ [200, {}, ['hi mom']]
18
+ end
19
+ end
20
+
21
+ def setup
22
+ @env = {}
23
+ @app = App.new
24
+ @management = middleware(@app)
25
+
26
+ # make sure we have an active connection
27
+ assert ActiveRecord::Base.connection
28
+ assert ActiveRecord::Base.connection_handler.active_connections?
29
+ end
30
+
31
+ def test_app_delegation
32
+ manager = middleware(@app)
33
+
34
+ manager.call @env
35
+ assert_equal [@env], @app.calls
36
+ end
37
+
38
+ def test_body_responds_to_each
39
+ _, _, body = @management.call(@env)
40
+ bits = []
41
+ body.each { |bit| bits << bit }
42
+ assert_equal ['hi mom'], bits
43
+ end
44
+
45
+ def test_connections_are_cleared_after_body_close
46
+ _, _, body = @management.call(@env)
47
+ body.close
48
+ assert !ActiveRecord::Base.connection_handler.active_connections?
49
+ end
50
+
51
+ def test_active_connections_are_not_cleared_on_body_close_during_transaction
52
+ ActiveRecord::Base.transaction do
53
+ _, _, body = @management.call(@env)
54
+ body.close
55
+ assert ActiveRecord::Base.connection_handler.active_connections?
56
+ end
57
+ end
58
+
59
+ def test_connections_closed_if_exception
60
+ app = Class.new(App) { def call(env); raise NotImplementedError; end }.new
61
+ explosive = middleware(app)
62
+ assert_raises(NotImplementedError) { explosive.call(@env) }
63
+ assert !ActiveRecord::Base.connection_handler.active_connections?
64
+ end
65
+
66
+ def test_connections_not_closed_if_exception_inside_transaction
67
+ ActiveRecord::Base.transaction do
68
+ app = Class.new(App) { def call(env); raise RuntimeError; end }.new
69
+ explosive = middleware(app)
70
+ assert_raises(RuntimeError) { explosive.call(@env) }
71
+ assert ActiveRecord::Base.connection_handler.active_connections?
72
+ end
73
+ end
74
+
75
+ test "doesn't clear active connections when running in a test case" do
76
+ executor.wrap do
77
+ @management.call(@env)
78
+ assert ActiveRecord::Base.connection_handler.active_connections?
79
+ end
80
+ end
81
+
82
+ test "proxy is polite to its body and responds to it" do
83
+ body = Class.new(String) { def to_path; "/path"; end }.new
84
+ app = lambda { |_| [200, {}, body] }
85
+ response_body = middleware(app).call(@env)[2]
86
+ assert response_body.respond_to?(:to_path)
87
+ assert_equal "/path", response_body.to_path
88
+ end
89
+
90
+ test "doesn't mutate the original response" do
91
+ original_response = [200, {}, 'hi']
92
+ app = lambda { |_| original_response }
93
+ middleware(app).call(@env)[2]
94
+ assert_equal 'hi', original_response.last
95
+ end
96
+
97
+ private
98
+ def executor
99
+ @executor ||= Class.new(ActiveSupport::Executor).tap do |exe|
100
+ ActiveRecord::QueryCache.install_executor_hooks(exe)
101
+ end
102
+ end
103
+
104
+ def middleware(app)
105
+ lambda do |env|
106
+ a, b, c = executor.wrap { app.call(env) }
107
+ [a, b, Rack::BodyProxy.new(c) { }]
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -1,346 +1,521 @@
1
- require "cases/helper"
2
- require 'active_support/concurrency/latch'
3
-
4
- module ActiveRecord
5
- module ConnectionAdapters
6
- class ConnectionPoolTest < ActiveRecord::TestCase
7
- attr_reader :pool
8
-
9
- def setup
10
- super
11
-
12
- # Keep a duplicate pool so we do not bother others
13
- @pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
14
-
15
- if in_memory_db?
16
- # Separate connections to an in-memory database create an entirely new database,
17
- # with an empty schema etc, so we just stub out this schema on the fly.
18
- @pool.with_connection do |connection|
19
- connection.create_table :posts do |t|
20
- t.integer :cololumn
21
- end
22
- end
23
- end
24
- end
25
-
26
- teardown do
27
- @pool.disconnect!
28
- end
29
-
30
- def active_connections(pool)
31
- pool.connections.find_all(&:in_use?)
32
- end
33
-
34
- def test_checkout_after_close
35
- connection = pool.connection
36
- assert connection.in_use?
37
-
38
- connection.close
39
- assert !connection.in_use?
40
-
41
- assert pool.connection.in_use?
42
- end
43
-
44
- def test_released_connection_moves_between_threads
45
- thread_conn = nil
46
-
47
- Thread.new {
48
- pool.with_connection do |conn|
49
- thread_conn = conn
50
- end
51
- }.join
52
-
53
- assert thread_conn
54
-
55
- Thread.new {
56
- pool.with_connection do |conn|
57
- assert_equal thread_conn, conn
58
- end
59
- }.join
60
- end
61
-
62
- def test_with_connection
63
- assert_equal 0, active_connections(pool).size
64
-
65
- main_thread = pool.connection
66
- assert_equal 1, active_connections(pool).size
67
-
68
- Thread.new {
69
- pool.with_connection do |conn|
70
- assert conn
71
- assert_equal 2, active_connections(pool).size
72
- end
73
- assert_equal 1, active_connections(pool).size
74
- }.join
75
-
76
- main_thread.close
77
- assert_equal 0, active_connections(pool).size
78
- end
79
-
80
- def test_active_connection_in_use
81
- assert !pool.active_connection?
82
- main_thread = pool.connection
83
-
84
- assert pool.active_connection?
85
-
86
- main_thread.close
87
-
88
- assert !pool.active_connection?
89
- end
90
-
91
- def test_full_pool_exception
92
- @pool.size.times { @pool.checkout }
93
- assert_raises(ConnectionTimeoutError) do
94
- @pool.checkout
95
- end
96
- end
97
-
98
- def test_full_pool_blocks
99
- cs = @pool.size.times.map { @pool.checkout }
100
- t = Thread.new { @pool.checkout }
101
-
102
- # make sure our thread is in the timeout section
103
- Thread.pass until t.status == "sleep"
104
-
105
- connection = cs.first
106
- connection.close
107
- assert_equal connection, t.join.value
108
- end
109
-
110
- def test_removing_releases_latch
111
- cs = @pool.size.times.map { @pool.checkout }
112
- t = Thread.new { @pool.checkout }
113
-
114
- # make sure our thread is in the timeout section
115
- Thread.pass until t.status == "sleep"
116
-
117
- connection = cs.first
118
- @pool.remove connection
119
- assert_respond_to t.join.value, :execute
120
- connection.close
121
- end
122
-
123
- def test_reap_and_active
124
- @pool.checkout
125
- @pool.checkout
126
- @pool.checkout
127
-
128
- connections = @pool.connections.dup
129
-
130
- @pool.reap
131
-
132
- assert_equal connections.length, @pool.connections.length
133
- end
134
-
135
- def test_reap_inactive
136
- ready = ActiveSupport::Concurrency::Latch.new
137
- @pool.checkout
138
- child = Thread.new do
139
- @pool.checkout
140
- @pool.checkout
141
- ready.release
142
- Thread.stop
143
- end
144
- ready.await
145
-
146
- assert_equal 3, active_connections(@pool).size
147
-
148
- child.terminate
149
- child.join
150
- @pool.reap
151
-
152
- assert_equal 1, active_connections(@pool).size
153
- ensure
154
- @pool.connections.each(&:close)
155
- end
156
-
157
- def test_remove_connection
158
- conn = @pool.checkout
159
- assert conn.in_use?
160
-
161
- length = @pool.connections.length
162
- @pool.remove conn
163
- assert conn.in_use?
164
- assert_equal(length - 1, @pool.connections.length)
165
- ensure
166
- conn.close
167
- end
168
-
169
- def test_remove_connection_for_thread
170
- conn = @pool.connection
171
- @pool.remove conn
172
- assert_not_equal(conn, @pool.connection)
173
- ensure
174
- conn.close if conn
175
- end
176
-
177
- def test_active_connection?
178
- assert !@pool.active_connection?
179
- assert @pool.connection
180
- assert @pool.active_connection?
181
- @pool.release_connection
182
- assert !@pool.active_connection?
183
- end
184
-
185
- def test_checkout_behaviour
186
- pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
187
- connection = pool.connection
188
- assert_not_nil connection
189
- threads = []
190
- 4.times do |i|
191
- threads << Thread.new(i) do
192
- connection = pool.connection
193
- assert_not_nil connection
194
- connection.close
195
- end
196
- end
197
-
198
- threads.each(&:join)
199
-
200
- Thread.new do
201
- assert pool.connection
202
- pool.connection.close
203
- end.join
204
- end
205
-
206
- # The connection pool is "fair" if threads waiting for
207
- # connections receive them the order in which they began
208
- # waiting. This ensures that we don't timeout one HTTP request
209
- # even while well under capacity in a multi-threaded environment
210
- # such as a Java servlet container.
211
- #
212
- # We don't need strict fairness: if two connections become
213
- # available at the same time, it's fine of two threads that were
214
- # waiting acquire the connections out of order.
215
- #
216
- # Thus this test prepares waiting threads and then trickles in
217
- # available connections slowly, ensuring the wakeup order is
218
- # correct in this case.
219
- def test_checkout_fairness
220
- @pool.instance_variable_set(:@size, 10)
221
- expected = (1..@pool.size).to_a.freeze
222
- # check out all connections so our threads start out waiting
223
- conns = expected.map { @pool.checkout }
224
- mutex = Mutex.new
225
- order = []
226
- errors = []
227
-
228
- threads = expected.map do |i|
229
- t = Thread.new {
230
- begin
231
- @pool.checkout # never checked back in
232
- mutex.synchronize { order << i }
233
- rescue => e
234
- mutex.synchronize { errors << e }
235
- end
236
- }
237
- Thread.pass until t.status == "sleep"
238
- t
239
- end
240
-
241
- # this should wake up the waiting threads one by one in order
242
- conns.each { |conn| @pool.checkin(conn); sleep 0.1 }
243
-
244
- threads.each(&:join)
245
-
246
- raise errors.first if errors.any?
247
-
248
- assert_equal(expected, order)
249
- end
250
-
251
- # As mentioned in #test_checkout_fairness, we don't care about
252
- # strict fairness. This test creates two groups of threads:
253
- # group1 whose members all start waiting before any thread in
254
- # group2. Enough connections are checked in to wakeup all
255
- # group1 threads, and the fact that only group1 and no group2
256
- # threads acquired a connection is enforced.
257
- def test_checkout_fairness_by_group
258
- @pool.instance_variable_set(:@size, 10)
259
- # take all the connections
260
- conns = (1..10).map { @pool.checkout }
261
- mutex = Mutex.new
262
- successes = [] # threads that successfully got a connection
263
- errors = []
264
-
265
- make_thread = proc do |i|
266
- t = Thread.new {
267
- begin
268
- @pool.checkout # never checked back in
269
- mutex.synchronize { successes << i }
270
- rescue => e
271
- mutex.synchronize { errors << e }
272
- end
273
- }
274
- Thread.pass until t.status == "sleep"
275
- t
276
- end
277
-
278
- # all group1 threads start waiting before any in group2
279
- group1 = (1..5).map(&make_thread)
280
- group2 = (6..10).map(&make_thread)
281
-
282
- # checkin n connections back to the pool
283
- checkin = proc do |n|
284
- n.times do
285
- c = conns.pop
286
- @pool.checkin(c)
287
- end
288
- end
289
-
290
- checkin.call(group1.size) # should wake up all group1
291
-
292
- loop do
293
- sleep 0.1
294
- break if mutex.synchronize { (successes.size + errors.size) == group1.size }
295
- end
296
-
297
- winners = mutex.synchronize { successes.dup }
298
- checkin.call(group2.size) # should wake up everyone remaining
299
-
300
- group1.each(&:join)
301
- group2.each(&:join)
302
-
303
- assert_equal((1..group1.size).to_a, winners.sort)
304
-
305
- if errors.any?
306
- raise errors.first
307
- end
308
- end
309
-
310
- def test_automatic_reconnect=
311
- pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
312
- assert pool.automatic_reconnect
313
- assert pool.connection
314
-
315
- pool.disconnect!
316
- assert pool.connection
317
-
318
- pool.disconnect!
319
- pool.automatic_reconnect = false
320
-
321
- assert_raises(ConnectionNotEstablished) do
322
- pool.connection
323
- end
324
-
325
- assert_raises(ConnectionNotEstablished) do
326
- pool.with_connection
327
- end
328
- end
329
-
330
- def test_pool_sets_connection_visitor
331
- assert @pool.connection.visitor.is_a?(Arel::Visitors::ToSql)
332
- end
333
-
334
- # make sure exceptions are thrown when establish_connection
335
- # is called with an anonymous class
336
- def test_anonymous_class_exception
337
- anonymous = Class.new(ActiveRecord::Base)
338
- handler = ActiveRecord::Base.connection_handler
339
-
340
- assert_raises(RuntimeError) {
341
- handler.establish_connection anonymous, nil
342
- }
343
- end
344
- end
345
- end
346
- end
1
+ require "cases/helper"
2
+ require 'concurrent/atomic/count_down_latch'
3
+
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ class ConnectionPoolTest < ActiveRecord::TestCase
7
+ attr_reader :pool
8
+
9
+ def setup
10
+ super
11
+
12
+ # Keep a duplicate pool so we do not bother others
13
+ @pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
14
+
15
+ if in_memory_db?
16
+ # Separate connections to an in-memory database create an entirely new database,
17
+ # with an empty schema etc, so we just stub out this schema on the fly.
18
+ @pool.with_connection do |connection|
19
+ connection.create_table :posts do |t|
20
+ t.integer :cololumn
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ teardown do
27
+ @pool.disconnect!
28
+ end
29
+
30
+ def active_connections(pool)
31
+ pool.connections.find_all(&:in_use?)
32
+ end
33
+
34
+ def test_checkout_after_close
35
+ connection = pool.connection
36
+ assert connection.in_use?
37
+
38
+ connection.close
39
+ assert !connection.in_use?
40
+
41
+ assert pool.connection.in_use?
42
+ end
43
+
44
+ def test_released_connection_moves_between_threads
45
+ thread_conn = nil
46
+
47
+ Thread.new {
48
+ pool.with_connection do |conn|
49
+ thread_conn = conn
50
+ end
51
+ }.join
52
+
53
+ assert thread_conn
54
+
55
+ Thread.new {
56
+ pool.with_connection do |conn|
57
+ assert_equal thread_conn, conn
58
+ end
59
+ }.join
60
+ end
61
+
62
+ def test_with_connection
63
+ assert_equal 0, active_connections(pool).size
64
+
65
+ main_thread = pool.connection
66
+ assert_equal 1, active_connections(pool).size
67
+
68
+ Thread.new {
69
+ pool.with_connection do |conn|
70
+ assert conn
71
+ assert_equal 2, active_connections(pool).size
72
+ end
73
+ assert_equal 1, active_connections(pool).size
74
+ }.join
75
+
76
+ main_thread.close
77
+ assert_equal 0, active_connections(pool).size
78
+ end
79
+
80
+ def test_active_connection_in_use
81
+ assert !pool.active_connection?
82
+ main_thread = pool.connection
83
+
84
+ assert pool.active_connection?
85
+
86
+ main_thread.close
87
+
88
+ assert !pool.active_connection?
89
+ end
90
+
91
+ def test_full_pool_exception
92
+ @pool.size.times { @pool.checkout }
93
+ assert_raises(ConnectionTimeoutError) do
94
+ @pool.checkout
95
+ end
96
+ end
97
+
98
+ def test_full_pool_blocks
99
+ cs = @pool.size.times.map { @pool.checkout }
100
+ t = Thread.new { @pool.checkout }
101
+
102
+ # make sure our thread is in the timeout section
103
+ Thread.pass until @pool.num_waiting_in_queue == 1
104
+
105
+ connection = cs.first
106
+ connection.close
107
+ assert_equal connection, t.join.value
108
+ end
109
+
110
+ def test_removing_releases_latch
111
+ cs = @pool.size.times.map { @pool.checkout }
112
+ t = Thread.new { @pool.checkout }
113
+
114
+ # make sure our thread is in the timeout section
115
+ Thread.pass until @pool.num_waiting_in_queue == 1
116
+
117
+ connection = cs.first
118
+ @pool.remove connection
119
+ assert_respond_to t.join.value, :execute
120
+ connection.close
121
+ end
122
+
123
+ def test_reap_and_active
124
+ @pool.checkout
125
+ @pool.checkout
126
+ @pool.checkout
127
+
128
+ connections = @pool.connections.dup
129
+
130
+ @pool.reap
131
+
132
+ assert_equal connections.length, @pool.connections.length
133
+ end
134
+
135
+ def test_reap_inactive
136
+ ready = Concurrent::CountDownLatch.new
137
+ @pool.checkout
138
+ child = Thread.new do
139
+ @pool.checkout
140
+ @pool.checkout
141
+ ready.count_down
142
+ Thread.stop
143
+ end
144
+ ready.wait
145
+
146
+ assert_equal 3, active_connections(@pool).size
147
+
148
+ child.terminate
149
+ child.join
150
+ @pool.reap
151
+
152
+ assert_equal 1, active_connections(@pool).size
153
+ ensure
154
+ @pool.connections.each { |conn| conn.close if conn.in_use? }
155
+ end
156
+
157
+ def test_remove_connection
158
+ conn = @pool.checkout
159
+ assert conn.in_use?
160
+
161
+ length = @pool.connections.length
162
+ @pool.remove conn
163
+ assert conn.in_use?
164
+ assert_equal(length - 1, @pool.connections.length)
165
+ ensure
166
+ conn.close
167
+ end
168
+
169
+ def test_remove_connection_for_thread
170
+ conn = @pool.connection
171
+ @pool.remove conn
172
+ assert_not_equal(conn, @pool.connection)
173
+ ensure
174
+ conn.close if conn
175
+ end
176
+
177
+ def test_active_connection?
178
+ assert !@pool.active_connection?
179
+ assert @pool.connection
180
+ assert @pool.active_connection?
181
+ @pool.release_connection
182
+ assert !@pool.active_connection?
183
+ end
184
+
185
+ def test_checkout_behaviour
186
+ pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
187
+ main_connection = pool.connection
188
+ assert_not_nil main_connection
189
+ threads = []
190
+ 4.times do |i|
191
+ threads << Thread.new(i) do
192
+ thread_connection = pool.connection
193
+ assert_not_nil thread_connection
194
+ thread_connection.close
195
+ end
196
+ end
197
+
198
+ threads.each(&:join)
199
+
200
+ Thread.new do
201
+ assert pool.connection
202
+ pool.connection.close
203
+ end.join
204
+ end
205
+
206
+ # The connection pool is "fair" if threads waiting for
207
+ # connections receive them in the order in which they began
208
+ # waiting. This ensures that we don't timeout one HTTP request
209
+ # even while well under capacity in a multi-threaded environment
210
+ # such as a Java servlet container.
211
+ #
212
+ # We don't need strict fairness: if two connections become
213
+ # available at the same time, it's fine if two threads that were
214
+ # waiting acquire the connections out of order.
215
+ #
216
+ # Thus this test prepares waiting threads and then trickles in
217
+ # available connections slowly, ensuring the wakeup order is
218
+ # correct in this case.
219
+ def test_checkout_fairness
220
+ @pool.instance_variable_set(:@size, 10)
221
+ expected = (1..@pool.size).to_a.freeze
222
+ # check out all connections so our threads start out waiting
223
+ conns = expected.map { @pool.checkout }
224
+ mutex = Mutex.new
225
+ order = []
226
+ errors = []
227
+
228
+ threads = expected.map do |i|
229
+ t = Thread.new {
230
+ begin
231
+ @pool.checkout # never checked back in
232
+ mutex.synchronize { order << i }
233
+ rescue => e
234
+ mutex.synchronize { errors << e }
235
+ end
236
+ }
237
+ Thread.pass until @pool.num_waiting_in_queue == i
238
+ t
239
+ end
240
+
241
+ # this should wake up the waiting threads one by one in order
242
+ conns.each { |conn| @pool.checkin(conn); sleep 0.1 }
243
+
244
+ threads.each(&:join)
245
+
246
+ raise errors.first if errors.any?
247
+
248
+ assert_equal(expected, order)
249
+ end
250
+
251
+ # As mentioned in #test_checkout_fairness, we don't care about
252
+ # strict fairness. This test creates two groups of threads:
253
+ # group1 whose members all start waiting before any thread in
254
+ # group2. Enough connections are checked in to wakeup all
255
+ # group1 threads, and the fact that only group1 and no group2
256
+ # threads acquired a connection is enforced.
257
+ def test_checkout_fairness_by_group
258
+ @pool.instance_variable_set(:@size, 10)
259
+ # take all the connections
260
+ conns = (1..10).map { @pool.checkout }
261
+ mutex = Mutex.new
262
+ successes = [] # threads that successfully got a connection
263
+ errors = []
264
+
265
+ make_thread = proc do |i|
266
+ t = Thread.new {
267
+ begin
268
+ @pool.checkout # never checked back in
269
+ mutex.synchronize { successes << i }
270
+ rescue => e
271
+ mutex.synchronize { errors << e }
272
+ end
273
+ }
274
+ Thread.pass until @pool.num_waiting_in_queue == i
275
+ t
276
+ end
277
+
278
+ # all group1 threads start waiting before any in group2
279
+ group1 = (1..5).map(&make_thread)
280
+ group2 = (6..10).map(&make_thread)
281
+
282
+ # checkin n connections back to the pool
283
+ checkin = proc do |n|
284
+ n.times do
285
+ c = conns.pop
286
+ @pool.checkin(c)
287
+ end
288
+ end
289
+
290
+ checkin.call(group1.size) # should wake up all group1
291
+
292
+ loop do
293
+ sleep 0.1
294
+ break if mutex.synchronize { (successes.size + errors.size) == group1.size }
295
+ end
296
+
297
+ winners = mutex.synchronize { successes.dup }
298
+ checkin.call(group2.size) # should wake up everyone remaining
299
+
300
+ group1.each(&:join)
301
+ group2.each(&:join)
302
+
303
+ assert_equal((1..group1.size).to_a, winners.sort)
304
+
305
+ if errors.any?
306
+ raise errors.first
307
+ end
308
+ end
309
+
310
+ def test_automatic_reconnect=
311
+ pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
312
+ assert pool.automatic_reconnect
313
+ assert pool.connection
314
+
315
+ pool.disconnect!
316
+ assert pool.connection
317
+
318
+ pool.disconnect!
319
+ pool.automatic_reconnect = false
320
+
321
+ assert_raises(ConnectionNotEstablished) do
322
+ pool.connection
323
+ end
324
+
325
+ assert_raises(ConnectionNotEstablished) do
326
+ pool.with_connection
327
+ end
328
+ end
329
+
330
+ def test_pool_sets_connection_visitor
331
+ assert @pool.connection.visitor.is_a?(Arel::Visitors::ToSql)
332
+ end
333
+
334
+ # make sure exceptions are thrown when establish_connection
335
+ # is called with an anonymous class
336
+ def test_anonymous_class_exception
337
+ anonymous = Class.new(ActiveRecord::Base)
338
+
339
+ assert_raises(RuntimeError) do
340
+ anonymous.establish_connection
341
+ end
342
+ end
343
+
344
+ def test_pool_sets_connection_schema_cache
345
+ connection = pool.checkout
346
+ schema_cache = SchemaCache.new connection
347
+ schema_cache.add(:posts)
348
+ pool.schema_cache = schema_cache
349
+
350
+ pool.with_connection do |conn|
351
+ assert_not_same pool.schema_cache, conn.schema_cache
352
+ assert_equal pool.schema_cache.size, conn.schema_cache.size
353
+ assert_same pool.schema_cache.columns(:posts), conn.schema_cache.columns(:posts)
354
+ end
355
+
356
+ pool.checkin connection
357
+ end
358
+
359
+ def test_concurrent_connection_establishment
360
+ assert_operator @pool.connections.size, :<=, 1
361
+
362
+ all_threads_in_new_connection = Concurrent::CountDownLatch.new(@pool.size - @pool.connections.size)
363
+ all_go = Concurrent::CountDownLatch.new
364
+
365
+ @pool.singleton_class.class_eval do
366
+ define_method(:new_connection) do
367
+ all_threads_in_new_connection.count_down
368
+ all_go.wait
369
+ super()
370
+ end
371
+ end
372
+
373
+ connecting_threads = []
374
+ @pool.size.times do
375
+ connecting_threads << Thread.new { @pool.checkout }
376
+ end
377
+
378
+ begin
379
+ Timeout.timeout(5) do
380
+ # the kernel of the whole test is here, everything else is just scaffolding,
381
+ # this latch will not be released unless conn. pool allows for concurrent
382
+ # connection creation
383
+ all_threads_in_new_connection.wait
384
+ end
385
+ 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'
388
+ ensure
389
+ # clean up the threads
390
+ all_go.count_down
391
+ connecting_threads.map(&:join)
392
+ end
393
+ end
394
+
395
+ def test_non_bang_disconnect_and_clear_reloadable_connections_throw_exception_if_threads_dont_return_their_conns
396
+ @pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
397
+ [:disconnect, :clear_reloadable_connections].each do |group_action_method|
398
+ @pool.with_connection do |connection|
399
+ assert_raises(ExclusiveConnectionTimeoutError) do
400
+ Thread.new { @pool.send(group_action_method) }.join
401
+ end
402
+ end
403
+ end
404
+ end
405
+
406
+ def test_disconnect_and_clear_reloadable_connections_attempt_to_wait_for_threads_to_return_their_conns
407
+ [: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
424
+ end
425
+ end
426
+ end
427
+
428
+ def test_bang_versions_of_disconnect_and_clear_reloadable_connections_if_unable_to_aquire_all_connections_proceed_anyway
429
+ @pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
430
+ [:disconnect!, :clear_reloadable_connections!].each do |group_action_method|
431
+ @pool.with_connection do |connection|
432
+ Thread.new { @pool.send(group_action_method) }.join
433
+ # assert connection has been forcefully taken away from us
434
+ assert_not @pool.active_connection?
435
+
436
+ # make a new connection for with_connection to clean up
437
+ @pool.connection
438
+ end
439
+ end
440
+ end
441
+
442
+ def test_disconnect_and_clear_reloadable_connections_are_able_to_preempt_other_waiting_threads
443
+ with_single_connection_pool do |pool|
444
+ [:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method|
445
+ 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
455
+
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
462
+ 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
+ end
484
+ end
485
+ end
486
+
487
+ def test_clear_reloadable_connections_creates_new_connections_for_waiting_threads_if_necessary
488
+ with_single_connection_pool do |pool|
489
+ conn = pool.connection # drain the only available connection
490
+ def conn.requires_reloading? # make sure it gets removed from the pool by clear_reloadable_connections
491
+ true
492
+ end
493
+
494
+ stuck_thread = Thread.new do
495
+ pool.with_connection {}
496
+ end
497
+
498
+ # wait for stuck_thread to get in queue
499
+ Thread.pass until pool.num_waiting_in_queue == 1
500
+
501
+ pool.clear_reloadable_connections
502
+
503
+ unless stuck_thread.join(2)
504
+ flunk 'clear_reloadable_connections must not let other connection waiting threads get stuck in queue'
505
+ end
506
+
507
+ assert_equal 0, pool.num_waiting_in_queue
508
+ end
509
+ end
510
+
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
518
+ end
519
+ end
520
+ end
521
+ end