ibm_db 3.0.4-x86-mingw32 → 5.0.4-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 (593) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +8 -1
  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 +269 -0
  8. data/ext/Makefile.nt32 +181 -181
  9. data/ext/Makefile.nt32.191 +212 -212
  10. data/ext/extconf.rb +322 -291
  11. data/ext/gil_release_version +3 -0
  12. data/ext/ibm_db-i386-mingw32.def +2 -0
  13. data/ext/ibm_db.c +11879 -11884
  14. data/ext/ibm_db.o +0 -0
  15. data/ext/ibm_db.so +0 -0
  16. data/ext/mkmf.log +110 -0
  17. data/ext/ruby_ibm_db.h +241 -241
  18. data/ext/ruby_ibm_db_cli.c +866 -866
  19. data/ext/ruby_ibm_db_cli.h +500 -500
  20. data/ext/ruby_ibm_db_cli.o +0 -0
  21. data/ext/unicode_support_version +3 -0
  22. data/init.rb +41 -41
  23. data/lib/IBM_DB.rb +27 -27
  24. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3561 -3177
  25. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  26. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  27. data/lib/mswin32/ibm_db.rb +91 -123
  28. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  29. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  30. data/test/assets/example.log +1 -1
  31. data/test/assets/test.txt +1 -1
  32. data/test/cases/adapter_test.rb +351 -261
  33. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  34. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  35. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  36. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  37. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  38. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  39. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  40. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  41. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  42. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  43. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  44. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  45. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  46. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  47. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  48. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  49. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  50. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  51. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  52. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  53. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  54. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  55. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  56. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  57. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  58. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  59. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  60. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  61. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  62. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  63. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  64. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  65. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  66. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  67. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  68. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  69. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  70. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  71. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  72. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  73. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  74. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  75. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  76. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  77. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  78. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  79. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  80. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  81. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  82. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  83. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  84. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  85. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  86. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  87. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  88. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  89. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  90. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  91. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  92. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  93. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  94. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  95. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  96. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  97. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  98. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  99. data/test/cases/aggregations_test.rb +168 -158
  100. data/test/cases/ar_schema_test.rb +146 -161
  101. data/test/cases/associations/association_scope_test.rb +16 -21
  102. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  103. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  104. data/test/cases/associations/callbacks_test.rb +190 -192
  105. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  106. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  107. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  108. data/test/cases/associations/eager_singularization_test.rb +148 -148
  109. data/test/cases/associations/eager_test.rb +1514 -1411
  110. data/test/cases/associations/extension_test.rb +87 -82
  111. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -932
  112. data/test/cases/associations/has_many_associations_test.rb +2501 -2162
  113. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  114. data/test/cases/associations/has_one_associations_test.rb +707 -610
  115. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  116. data/test/cases/associations/inner_join_association_test.rb +139 -139
  117. data/test/cases/associations/inverse_associations_test.rb +733 -693
  118. data/test/cases/associations/join_model_test.rb +777 -754
  119. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  120. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  121. data/test/cases/associations/required_test.rb +102 -82
  122. data/test/cases/associations_test.rb +385 -380
  123. data/test/cases/attribute_decorators_test.rb +126 -125
  124. data/test/cases/attribute_methods/read_test.rb +60 -60
  125. data/test/cases/attribute_methods_test.rb +1009 -952
  126. data/test/cases/attribute_set_test.rb +270 -200
  127. data/test/cases/attribute_test.rb +246 -180
  128. data/test/cases/attributes_test.rb +253 -136
  129. data/test/cases/autosave_association_test.rb +1708 -1595
  130. data/test/cases/base_test.rb +1713 -1638
  131. data/test/cases/batches_test.rb +489 -212
  132. data/test/cases/binary_test.rb +44 -52
  133. data/test/cases/bind_parameter_test.rb +110 -100
  134. data/test/cases/cache_key_test.rb +26 -0
  135. data/test/cases/calculations_test.rb +798 -646
  136. data/test/cases/callbacks_test.rb +636 -543
  137. data/test/cases/clone_test.rb +40 -40
  138. data/test/cases/coders/json_test.rb +15 -0
  139. data/test/cases/coders/yaml_column_test.rb +63 -63
  140. data/test/cases/collection_cache_key_test.rb +115 -0
  141. data/test/cases/column_alias_test.rb +17 -17
  142. data/test/cases/column_definition_test.rb +92 -123
  143. data/test/cases/comment_test.rb +145 -0
  144. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  145. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  146. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  147. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  148. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  149. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  150. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  151. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  152. data/test/cases/connection_management_test.rb +112 -122
  153. data/test/cases/connection_pool_test.rb +521 -346
  154. data/test/cases/connection_specification/resolver_test.rb +131 -116
  155. data/test/cases/core_test.rb +112 -112
  156. data/test/cases/counter_cache_test.rb +214 -209
  157. data/test/cases/custom_locking_test.rb +17 -17
  158. data/test/cases/database_statements_test.rb +34 -19
  159. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  160. data/test/cases/date_time_precision_test.rb +107 -0
  161. data/test/cases/date_time_test.rb +61 -61
  162. data/test/cases/defaults_test.rb +219 -223
  163. data/test/cases/dirty_test.rb +763 -775
  164. data/test/cases/disconnected_test.rb +30 -28
  165. data/test/cases/dup_test.rb +157 -157
  166. data/test/cases/enum_test.rb +444 -290
  167. data/test/cases/errors_test.rb +16 -0
  168. data/test/cases/explain_subscriber_test.rb +64 -64
  169. data/test/cases/explain_test.rb +87 -76
  170. data/test/cases/finder_respond_to_test.rb +60 -60
  171. data/test/cases/finder_test.rb +1294 -1166
  172. data/test/cases/fixture_set/file_test.rb +156 -138
  173. data/test/cases/fixtures_test.rb +988 -897
  174. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  175. data/test/cases/habtm_destroy_order_test.rb +61 -61
  176. data/test/cases/helper.rb +204 -210
  177. data/test/cases/hot_compatibility_test.rb +142 -54
  178. data/test/cases/i18n_test.rb +45 -45
  179. data/test/cases/inheritance_test.rb +606 -375
  180. data/test/cases/integration_test.rb +155 -139
  181. data/test/cases/invalid_connection_test.rb +24 -22
  182. data/test/cases/invertible_migration_test.rb +387 -295
  183. data/test/cases/json_serialization_test.rb +311 -302
  184. data/test/cases/locking_test.rb +493 -477
  185. data/test/cases/log_subscriber_test.rb +225 -136
  186. data/test/cases/migration/change_schema_test.rb +458 -472
  187. data/test/cases/migration/change_table_test.rb +256 -224
  188. data/test/cases/migration/column_attributes_test.rb +176 -192
  189. data/test/cases/migration/column_positioning_test.rb +56 -56
  190. data/test/cases/migration/columns_test.rb +310 -304
  191. data/test/cases/migration/command_recorder_test.rb +350 -305
  192. data/test/cases/migration/compatibility_test.rb +118 -0
  193. data/test/cases/migration/create_join_table_test.rb +157 -148
  194. data/test/cases/migration/foreign_key_test.rb +362 -360
  195. data/test/cases/migration/helper.rb +39 -39
  196. data/test/cases/migration/index_test.rb +218 -216
  197. data/test/cases/migration/logger_test.rb +36 -36
  198. data/test/cases/migration/pending_migrations_test.rb +52 -53
  199. data/test/cases/migration/references_foreign_key_test.rb +221 -214
  200. data/test/cases/migration/references_index_test.rb +101 -101
  201. data/test/cases/migration/references_statements_test.rb +136 -116
  202. data/test/cases/migration/rename_table_test.rb +93 -93
  203. data/test/cases/migration_test.rb +1157 -959
  204. data/test/cases/migrator_test.rb +471 -388
  205. data/test/cases/mixin_test.rb +68 -70
  206. data/test/cases/modules_test.rb +172 -173
  207. data/test/cases/multiparameter_attributes_test.rb +372 -350
  208. data/test/cases/multiple_db_test.rb +122 -115
  209. data/test/cases/nested_attributes_test.rb +1098 -1057
  210. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  211. data/test/cases/persistence_test.rb +1001 -909
  212. data/test/cases/pooled_connections_test.rb +81 -81
  213. data/test/cases/primary_keys_test.rb +376 -237
  214. data/test/cases/query_cache_test.rb +446 -326
  215. data/test/cases/quoting_test.rb +202 -156
  216. data/test/cases/readonly_test.rb +119 -118
  217. data/test/cases/reaper_test.rb +85 -85
  218. data/test/cases/reflection_test.rb +509 -454
  219. data/test/cases/relation/delegation_test.rb +63 -68
  220. data/test/cases/relation/merging_test.rb +157 -161
  221. data/test/cases/relation/mutation_test.rb +183 -165
  222. data/test/cases/relation/or_test.rb +92 -0
  223. data/test/cases/relation/predicate_builder_test.rb +16 -14
  224. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  225. data/test/cases/relation/where_chain_test.rb +105 -181
  226. data/test/cases/relation/where_clause_test.rb +182 -0
  227. data/test/cases/relation/where_test.rb +322 -300
  228. data/test/cases/relation_test.rb +328 -297
  229. data/test/cases/relations_test.rb +2026 -1815
  230. data/test/cases/reload_models_test.rb +22 -22
  231. data/test/cases/result_test.rb +90 -80
  232. data/test/cases/sanitize_test.rb +176 -83
  233. data/test/cases/schema_dumper_test.rb +457 -463
  234. data/test/cases/schema_loading_test.rb +52 -0
  235. data/test/cases/scoping/default_scoping_test.rb +528 -454
  236. data/test/cases/scoping/named_scoping_test.rb +561 -524
  237. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  238. data/test/cases/secure_token_test.rb +32 -0
  239. data/test/cases/serialization_test.rb +104 -104
  240. data/test/cases/serialized_attribute_test.rb +364 -277
  241. data/test/cases/statement_cache_test.rb +136 -98
  242. data/test/cases/store_test.rb +195 -194
  243. data/test/cases/suppressor_test.rb +63 -0
  244. data/test/cases/tasks/database_tasks_test.rb +462 -396
  245. data/test/cases/tasks/mysql_rake_test.rb +345 -311
  246. data/test/cases/tasks/postgresql_rake_test.rb +304 -245
  247. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  248. data/test/cases/test_case.rb +131 -123
  249. data/test/cases/test_fixtures_test.rb +36 -0
  250. data/test/cases/time_precision_test.rb +103 -0
  251. data/test/cases/timestamp_test.rb +501 -468
  252. data/test/cases/touch_later_test.rb +121 -0
  253. data/test/cases/transaction_callbacks_test.rb +518 -452
  254. data/test/cases/transaction_isolation_test.rb +106 -106
  255. data/test/cases/transactions_test.rb +835 -817
  256. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  257. data/test/cases/type/date_time_test.rb +14 -0
  258. data/test/cases/type/integer_test.rb +27 -121
  259. data/test/cases/type/string_test.rb +22 -36
  260. data/test/cases/type/type_map_test.rb +177 -177
  261. data/test/cases/type_test.rb +39 -0
  262. data/test/cases/types_test.rb +24 -141
  263. data/test/cases/unconnected_test.rb +33 -33
  264. data/test/cases/validations/absence_validation_test.rb +73 -0
  265. data/test/cases/validations/association_validation_test.rb +97 -86
  266. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  267. data/test/cases/validations/i18n_validation_test.rb +86 -90
  268. data/test/cases/validations/length_validation_test.rb +79 -47
  269. data/test/cases/validations/presence_validation_test.rb +103 -68
  270. data/test/cases/validations/uniqueness_validation_test.rb +548 -434
  271. data/test/cases/validations_repair_helper.rb +19 -23
  272. data/test/cases/validations_test.rb +194 -165
  273. data/test/cases/view_test.rb +216 -113
  274. data/test/cases/yaml_serialization_test.rb +121 -86
  275. data/test/config.example.yml +97 -0
  276. data/test/config.rb +5 -5
  277. data/test/config.yml +154 -154
  278. data/test/connections/native_ibm_db/connection.rb +43 -43
  279. data/test/fixtures/accounts.yml +29 -29
  280. data/test/fixtures/admin/accounts.yml +2 -2
  281. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  282. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  283. data/test/fixtures/admin/users.yml +10 -10
  284. data/test/fixtures/author_addresses.yml +17 -17
  285. data/test/fixtures/author_favorites.yml +3 -3
  286. data/test/fixtures/authors.yml +23 -23
  287. data/test/fixtures/bad_posts.yml +9 -0
  288. data/test/fixtures/binaries.yml +133 -133
  289. data/test/fixtures/books.yml +31 -11
  290. data/test/fixtures/bulbs.yml +5 -5
  291. data/test/fixtures/cars.yml +9 -9
  292. data/test/fixtures/categories.yml +19 -19
  293. data/test/fixtures/categories/special_categories.yml +9 -9
  294. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  295. data/test/fixtures/categories_ordered.yml +7 -7
  296. data/test/fixtures/categories_posts.yml +31 -31
  297. data/test/fixtures/categorizations.yml +23 -23
  298. data/test/fixtures/clubs.yml +8 -8
  299. data/test/fixtures/collections.yml +3 -3
  300. data/test/fixtures/colleges.yml +3 -3
  301. data/test/fixtures/comments.yml +65 -65
  302. data/test/fixtures/companies.yml +67 -67
  303. data/test/fixtures/computers.yml +10 -10
  304. data/test/fixtures/content.yml +3 -0
  305. data/test/fixtures/content_positions.yml +3 -0
  306. data/test/fixtures/courses.yml +8 -8
  307. data/test/fixtures/customers.yml +25 -25
  308. data/test/fixtures/dashboards.yml +6 -6
  309. data/test/fixtures/dead_parrots.yml +5 -0
  310. data/test/fixtures/developers.yml +21 -21
  311. data/test/fixtures/developers_projects.yml +16 -16
  312. data/test/fixtures/dog_lovers.yml +7 -7
  313. data/test/fixtures/dogs.yml +4 -4
  314. data/test/fixtures/doubloons.yml +3 -3
  315. data/test/fixtures/edges.yml +5 -5
  316. data/test/fixtures/entrants.yml +14 -14
  317. data/test/fixtures/essays.yml +6 -6
  318. data/test/fixtures/faces.yml +11 -11
  319. data/test/fixtures/fk_test_has_fk.yml +3 -3
  320. data/test/fixtures/fk_test_has_pk.yml +1 -1
  321. data/test/fixtures/friendships.yml +4 -4
  322. data/test/fixtures/funny_jokes.yml +10 -10
  323. data/test/fixtures/interests.yml +33 -33
  324. data/test/fixtures/items.yml +3 -3
  325. data/test/fixtures/jobs.yml +7 -7
  326. data/test/fixtures/legacy_things.yml +3 -3
  327. data/test/fixtures/live_parrots.yml +4 -0
  328. data/test/fixtures/mateys.yml +4 -4
  329. data/test/fixtures/member_details.yml +8 -8
  330. data/test/fixtures/member_types.yml +6 -6
  331. data/test/fixtures/members.yml +11 -11
  332. data/test/fixtures/memberships.yml +34 -34
  333. data/test/fixtures/men.yml +5 -5
  334. data/test/fixtures/minimalistics.yml +2 -2
  335. data/test/fixtures/minivans.yml +5 -5
  336. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  337. data/test/fixtures/mixins.yml +29 -29
  338. data/test/fixtures/movies.yml +7 -7
  339. data/test/fixtures/naked/yml/accounts.yml +1 -1
  340. data/test/fixtures/naked/yml/companies.yml +1 -1
  341. data/test/fixtures/naked/yml/courses.yml +1 -1
  342. data/test/fixtures/naked/yml/parrots.yml +2 -0
  343. data/test/fixtures/naked/yml/trees.yml +3 -0
  344. data/test/fixtures/nodes.yml +29 -0
  345. data/test/fixtures/organizations.yml +5 -5
  346. data/test/fixtures/other_comments.yml +6 -0
  347. data/test/fixtures/other_dogs.yml +2 -0
  348. data/test/fixtures/other_posts.yml +7 -0
  349. data/test/fixtures/other_topics.yml +42 -42
  350. data/test/fixtures/owners.yml +9 -9
  351. data/test/fixtures/parrots.yml +27 -27
  352. data/test/fixtures/parrots_pirates.yml +7 -7
  353. data/test/fixtures/people.yml +24 -24
  354. data/test/fixtures/peoples_treasures.yml +3 -3
  355. data/test/fixtures/pets.yml +19 -19
  356. data/test/fixtures/pirates.yml +12 -12
  357. data/test/fixtures/posts.yml +80 -80
  358. data/test/fixtures/price_estimates.yml +16 -7
  359. data/test/fixtures/products.yml +4 -4
  360. data/test/fixtures/projects.yml +7 -7
  361. data/test/fixtures/randomly_named_a9.yml +7 -7
  362. data/test/fixtures/ratings.yml +14 -14
  363. data/test/fixtures/readers.yml +11 -11
  364. data/test/fixtures/references.yml +17 -17
  365. data/test/fixtures/reserved_words/distinct.yml +5 -5
  366. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  367. data/test/fixtures/reserved_words/group.yml +14 -14
  368. data/test/fixtures/reserved_words/select.yml +8 -8
  369. data/test/fixtures/reserved_words/values.yml +7 -7
  370. data/test/fixtures/ships.yml +6 -6
  371. data/test/fixtures/speedometers.yml +8 -8
  372. data/test/fixtures/sponsors.yml +12 -12
  373. data/test/fixtures/string_key_objects.yml +7 -7
  374. data/test/fixtures/subscribers.yml +10 -10
  375. data/test/fixtures/subscriptions.yml +12 -12
  376. data/test/fixtures/taggings.yml +78 -78
  377. data/test/fixtures/tags.yml +11 -11
  378. data/test/fixtures/tasks.yml +7 -7
  379. data/test/fixtures/teapots.yml +3 -3
  380. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  381. data/test/fixtures/to_be_linked/users.yml +10 -10
  382. data/test/fixtures/topics.yml +49 -49
  383. data/test/fixtures/toys.yml +14 -14
  384. data/test/fixtures/traffic_lights.yml +9 -9
  385. data/test/fixtures/treasures.yml +10 -10
  386. data/test/fixtures/trees.yml +3 -0
  387. data/test/fixtures/uuid_children.yml +3 -3
  388. data/test/fixtures/uuid_parents.yml +2 -2
  389. data/test/fixtures/variants.yml +4 -4
  390. data/test/fixtures/vegetables.yml +19 -19
  391. data/test/fixtures/vertices.yml +3 -3
  392. data/test/fixtures/warehouse_things.yml +2 -2
  393. data/test/fixtures/zines.yml +5 -5
  394. data/test/ibm_db_test.rb +24 -24
  395. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  396. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  397. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  398. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  399. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  400. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  401. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  402. data/test/migrations/rename/1_we_need_things.rb +11 -11
  403. data/test/migrations/rename/2_rename_things.rb +9 -9
  404. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  405. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  406. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  407. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  408. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  409. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  410. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  411. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  412. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  413. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  414. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  415. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  416. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  417. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  418. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  419. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  420. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  421. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  422. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  423. data/test/models/admin.rb +4 -4
  424. data/test/models/admin/account.rb +2 -2
  425. data/test/models/admin/randomly_named_c1.rb +7 -3
  426. data/test/models/admin/user.rb +40 -40
  427. data/test/models/aircraft.rb +5 -4
  428. data/test/models/arunit2_model.rb +3 -3
  429. data/test/models/author.rb +209 -212
  430. data/test/models/auto_id.rb +4 -4
  431. data/test/models/autoloadable/extra_firm.rb +2 -2
  432. data/test/models/binary.rb +1 -1
  433. data/test/models/bird.rb +12 -12
  434. data/test/models/book.rb +23 -18
  435. data/test/models/boolean.rb +2 -2
  436. data/test/models/bulb.rb +52 -51
  437. data/test/models/cake_designer.rb +3 -3
  438. data/test/models/car.rb +29 -26
  439. data/test/models/carrier.rb +2 -2
  440. data/test/models/cat.rb +10 -0
  441. data/test/models/categorization.rb +19 -19
  442. data/test/models/category.rb +35 -35
  443. data/test/models/chef.rb +8 -3
  444. data/test/models/citation.rb +3 -3
  445. data/test/models/club.rb +25 -23
  446. data/test/models/college.rb +10 -10
  447. data/test/models/column.rb +3 -3
  448. data/test/models/column_name.rb +3 -3
  449. data/test/models/comment.rb +76 -64
  450. data/test/models/company.rb +230 -225
  451. data/test/models/company_in_module.rb +98 -98
  452. data/test/models/computer.rb +3 -3
  453. data/test/models/contact.rb +41 -41
  454. data/test/models/content.rb +40 -0
  455. data/test/models/contract.rb +20 -20
  456. data/test/models/country.rb +7 -7
  457. data/test/models/course.rb +6 -6
  458. data/test/models/customer.rb +83 -77
  459. data/test/models/customer_carrier.rb +14 -14
  460. data/test/models/dashboard.rb +3 -3
  461. data/test/models/default.rb +2 -2
  462. data/test/models/department.rb +4 -4
  463. data/test/models/developer.rb +274 -252
  464. data/test/models/dog.rb +5 -5
  465. data/test/models/dog_lover.rb +5 -5
  466. data/test/models/doubloon.rb +12 -12
  467. data/test/models/drink_designer.rb +3 -3
  468. data/test/models/edge.rb +5 -5
  469. data/test/models/electron.rb +5 -5
  470. data/test/models/engine.rb +4 -4
  471. data/test/models/entrant.rb +3 -3
  472. data/test/models/essay.rb +5 -5
  473. data/test/models/event.rb +2 -2
  474. data/test/models/eye.rb +37 -37
  475. data/test/models/face.rb +9 -9
  476. data/test/models/friendship.rb +6 -6
  477. data/test/models/guid.rb +1 -1
  478. data/test/models/guitar.rb +4 -0
  479. data/test/models/hotel.rb +11 -6
  480. data/test/models/image.rb +3 -3
  481. data/test/models/interest.rb +5 -5
  482. data/test/models/invoice.rb +4 -4
  483. data/test/models/item.rb +7 -7
  484. data/test/models/job.rb +7 -7
  485. data/test/models/joke.rb +7 -7
  486. data/test/models/keyboard.rb +3 -3
  487. data/test/models/legacy_thing.rb +3 -3
  488. data/test/models/lesson.rb +11 -11
  489. data/test/models/line_item.rb +3 -3
  490. data/test/models/liquid.rb +4 -4
  491. data/test/models/man.rb +11 -11
  492. data/test/models/matey.rb +4 -4
  493. data/test/models/member.rb +42 -41
  494. data/test/models/member_detail.rb +8 -7
  495. data/test/models/member_type.rb +3 -3
  496. data/test/models/membership.rb +35 -35
  497. data/test/models/mentor.rb +3 -0
  498. data/test/models/minimalistic.rb +2 -2
  499. data/test/models/minivan.rb +9 -9
  500. data/test/models/mixed_case_monkey.rb +3 -3
  501. data/test/models/mocktail_designer.rb +2 -0
  502. data/test/models/molecule.rb +6 -6
  503. data/test/models/movie.rb +5 -5
  504. data/test/models/node.rb +5 -0
  505. data/test/models/non_primary_key.rb +2 -0
  506. data/test/models/notification.rb +3 -0
  507. data/test/models/order.rb +4 -4
  508. data/test/models/organization.rb +14 -14
  509. data/test/models/other_dog.rb +5 -0
  510. data/test/models/owner.rb +37 -34
  511. data/test/models/parrot.rb +28 -29
  512. data/test/models/person.rb +142 -143
  513. data/test/models/personal_legacy_thing.rb +4 -4
  514. data/test/models/pet.rb +18 -15
  515. data/test/models/pet_treasure.rb +6 -0
  516. data/test/models/pirate.rb +92 -92
  517. data/test/models/possession.rb +3 -3
  518. data/test/models/post.rb +273 -264
  519. data/test/models/price_estimate.rb +4 -4
  520. data/test/models/professor.rb +5 -5
  521. data/test/models/project.rb +40 -29
  522. data/test/models/publisher.rb +2 -2
  523. data/test/models/publisher/article.rb +4 -4
  524. data/test/models/publisher/magazine.rb +3 -3
  525. data/test/models/randomly_named_c1.rb +3 -3
  526. data/test/models/rating.rb +4 -4
  527. data/test/models/reader.rb +23 -23
  528. data/test/models/recipe.rb +3 -0
  529. data/test/models/record.rb +2 -2
  530. data/test/models/reference.rb +22 -22
  531. data/test/models/reply.rb +61 -61
  532. data/test/models/ship.rb +39 -33
  533. data/test/models/ship_part.rb +7 -7
  534. data/test/models/shop.rb +17 -17
  535. data/test/models/shop_account.rb +6 -6
  536. data/test/models/speedometer.rb +6 -6
  537. data/test/models/sponsor.rb +7 -7
  538. data/test/models/string_key_object.rb +3 -3
  539. data/test/models/student.rb +4 -4
  540. data/test/models/subject.rb +16 -16
  541. data/test/models/subscriber.rb +8 -8
  542. data/test/models/subscription.rb +4 -4
  543. data/test/models/tag.rb +13 -7
  544. data/test/models/tagging.rb +13 -13
  545. data/test/models/task.rb +5 -5
  546. data/test/models/topic.rb +118 -124
  547. data/test/models/toy.rb +6 -6
  548. data/test/models/traffic_light.rb +4 -4
  549. data/test/models/treasure.rb +14 -14
  550. data/test/models/treaty.rb +7 -7
  551. data/test/models/tree.rb +3 -0
  552. data/test/models/tuning_peg.rb +4 -0
  553. data/test/models/tyre.rb +11 -11
  554. data/test/models/user.rb +14 -0
  555. data/test/models/uuid_child.rb +3 -3
  556. data/test/models/uuid_item.rb +6 -0
  557. data/test/models/uuid_parent.rb +3 -3
  558. data/test/models/vegetables.rb +24 -24
  559. data/test/models/vehicle.rb +6 -6
  560. data/test/models/vertex.rb +9 -9
  561. data/test/models/warehouse_thing.rb +5 -5
  562. data/test/models/wheel.rb +3 -3
  563. data/test/models/without_table.rb +3 -3
  564. data/test/models/zine.rb +3 -3
  565. data/test/schema/mysql2_specific_schema.rb +68 -58
  566. data/test/schema/oracle_specific_schema.rb +40 -43
  567. data/test/schema/postgresql_specific_schema.rb +114 -202
  568. data/test/schema/schema.rb +1057 -938
  569. data/test/schema/schema.rb.original +1057 -0
  570. data/test/schema/sqlite_specific_schema.rb +18 -22
  571. data/test/support/config.rb +43 -43
  572. data/test/support/connection.rb +23 -22
  573. data/test/support/connection_helper.rb +14 -14
  574. data/test/support/ddl_helper.rb +8 -8
  575. data/test/support/schema_dumping_helper.rb +20 -20
  576. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  577. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  578. metadata +146 -30
  579. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  580. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  581. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  582. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  583. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  584. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  585. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  586. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  587. data/test/cases/migration/table_and_index_test.rb +0 -24
  588. data/test/cases/relation/where_test2.rb +0 -36
  589. data/test/cases/type/decimal_test.rb +0 -51
  590. data/test/cases/type/unsigned_integer_test.rb +0 -18
  591. data/test/cases/xml_serialization_test.rb +0 -457
  592. data/test/fixtures/naked/csv/accounts.csv +0 -1
  593. data/test/schema/mysql_specific_schema.rb +0 -70
@@ -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