sequel 5.20.0 → 5.49.0

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 (511) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +398 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +80 -16
  7. data/doc/cheat_sheet.rdoc +6 -5
  8. data/doc/code_order.rdoc +10 -12
  9. data/doc/dataset_filtering.rdoc +17 -2
  10. data/doc/fork_safety.rdoc +84 -0
  11. data/doc/migration.rdoc +11 -5
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +10 -2
  15. data/doc/postgresql.rdoc +82 -3
  16. data/doc/querying.rdoc +4 -4
  17. data/doc/release_notes/5.21.0.txt +87 -0
  18. data/doc/release_notes/5.22.0.txt +48 -0
  19. data/doc/release_notes/5.23.0.txt +56 -0
  20. data/doc/release_notes/5.24.0.txt +56 -0
  21. data/doc/release_notes/5.25.0.txt +32 -0
  22. data/doc/release_notes/5.26.0.txt +35 -0
  23. data/doc/release_notes/5.27.0.txt +21 -0
  24. data/doc/release_notes/5.28.0.txt +16 -0
  25. data/doc/release_notes/5.29.0.txt +22 -0
  26. data/doc/release_notes/5.30.0.txt +20 -0
  27. data/doc/release_notes/5.31.0.txt +148 -0
  28. data/doc/release_notes/5.32.0.txt +46 -0
  29. data/doc/release_notes/5.33.0.txt +24 -0
  30. data/doc/release_notes/5.34.0.txt +40 -0
  31. data/doc/release_notes/5.35.0.txt +56 -0
  32. data/doc/release_notes/5.36.0.txt +60 -0
  33. data/doc/release_notes/5.37.0.txt +30 -0
  34. data/doc/release_notes/5.38.0.txt +28 -0
  35. data/doc/release_notes/5.39.0.txt +19 -0
  36. data/doc/release_notes/5.40.0.txt +40 -0
  37. data/doc/release_notes/5.41.0.txt +25 -0
  38. data/doc/release_notes/5.42.0.txt +136 -0
  39. data/doc/release_notes/5.43.0.txt +98 -0
  40. data/doc/release_notes/5.44.0.txt +32 -0
  41. data/doc/release_notes/5.45.0.txt +34 -0
  42. data/doc/release_notes/5.46.0.txt +87 -0
  43. data/doc/release_notes/5.47.0.txt +59 -0
  44. data/doc/release_notes/5.48.0.txt +14 -0
  45. data/doc/release_notes/5.49.0.txt +59 -0
  46. data/doc/sharding.rdoc +2 -0
  47. data/doc/sql.rdoc +13 -1
  48. data/doc/testing.rdoc +20 -7
  49. data/doc/transactions.rdoc +0 -8
  50. data/doc/validations.rdoc +1 -1
  51. data/doc/virtual_rows.rdoc +1 -1
  52. data/lib/sequel/adapters/ado/access.rb +1 -1
  53. data/lib/sequel/adapters/ado.rb +43 -35
  54. data/lib/sequel/adapters/ibmdb.rb +2 -2
  55. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  56. data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
  57. data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
  58. data/lib/sequel/adapters/jdbc.rb +24 -6
  59. data/lib/sequel/adapters/mysql.rb +1 -1
  60. data/lib/sequel/adapters/mysql2.rb +2 -3
  61. data/lib/sequel/adapters/odbc.rb +8 -6
  62. data/lib/sequel/adapters/oracle.rb +5 -4
  63. data/lib/sequel/adapters/postgres.rb +15 -9
  64. data/lib/sequel/adapters/shared/access.rb +6 -6
  65. data/lib/sequel/adapters/shared/mssql.rb +66 -21
  66. data/lib/sequel/adapters/shared/mysql.rb +27 -10
  67. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  68. data/lib/sequel/adapters/shared/postgres.rb +271 -32
  69. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  70. data/lib/sequel/adapters/shared/sqlite.rb +161 -19
  71. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  72. data/lib/sequel/adapters/sqlite.rb +1 -1
  73. data/lib/sequel/adapters/tinytds.rb +15 -2
  74. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
  75. data/lib/sequel/ast_transformer.rb +6 -0
  76. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  77. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  78. data/lib/sequel/connection_pool/single.rb +1 -1
  79. data/lib/sequel/connection_pool/threaded.rb +2 -2
  80. data/lib/sequel/core.rb +333 -319
  81. data/lib/sequel/database/connecting.rb +3 -4
  82. data/lib/sequel/database/logging.rb +7 -1
  83. data/lib/sequel/database/misc.rb +31 -12
  84. data/lib/sequel/database/query.rb +3 -1
  85. data/lib/sequel/database/schema_generator.rb +53 -51
  86. data/lib/sequel/database/schema_methods.rb +38 -23
  87. data/lib/sequel/database/transactions.rb +17 -18
  88. data/lib/sequel/dataset/actions.rb +14 -9
  89. data/lib/sequel/dataset/features.rb +16 -0
  90. data/lib/sequel/dataset/misc.rb +2 -2
  91. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  92. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  93. data/lib/sequel/dataset/query.rb +26 -9
  94. data/lib/sequel/dataset/sql.rb +76 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/deprecated.rb +3 -1
  97. data/lib/sequel/exceptions.rb +2 -0
  98. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  99. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  100. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  101. data/lib/sequel/extensions/blank.rb +8 -0
  102. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  103. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  104. data/lib/sequel/extensions/connection_validator.rb +2 -2
  105. data/lib/sequel/extensions/core_refinements.rb +2 -0
  106. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  107. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  108. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  109. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  110. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  111. data/lib/sequel/extensions/index_caching.rb +9 -7
  112. data/lib/sequel/extensions/inflector.rb +9 -1
  113. data/lib/sequel/extensions/integer64.rb +2 -0
  114. data/lib/sequel/extensions/migration.rb +11 -3
  115. data/lib/sequel/extensions/named_timezones.rb +56 -8
  116. data/lib/sequel/extensions/pagination.rb +1 -1
  117. data/lib/sequel/extensions/pg_array.rb +5 -0
  118. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  119. data/lib/sequel/extensions/pg_enum.rb +11 -3
  120. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  121. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  122. data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
  123. data/lib/sequel/extensions/pg_inet.rb +15 -5
  124. data/lib/sequel/extensions/pg_interval.rb +36 -8
  125. data/lib/sequel/extensions/pg_json.rb +387 -123
  126. data/lib/sequel/extensions/pg_json_ops.rb +238 -0
  127. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  128. data/lib/sequel/extensions/pg_range.rb +17 -9
  129. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  130. data/lib/sequel/extensions/pg_row.rb +4 -2
  131. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  132. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  133. data/lib/sequel/extensions/query.rb +3 -0
  134. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  135. data/lib/sequel/extensions/s.rb +2 -0
  136. data/lib/sequel/extensions/schema_dumper.rb +24 -7
  137. data/lib/sequel/extensions/server_block.rb +18 -7
  138. data/lib/sequel/extensions/sql_comments.rb +2 -2
  139. data/lib/sequel/extensions/string_agg.rb +1 -1
  140. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  141. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  142. data/lib/sequel/extensions/to_dot.rb +9 -3
  143. data/lib/sequel/model/associations.rb +356 -117
  144. data/lib/sequel/model/base.rb +107 -68
  145. data/lib/sequel/model/errors.rb +10 -1
  146. data/lib/sequel/model/inflections.rb +1 -1
  147. data/lib/sequel/model/plugins.rb +9 -3
  148. data/lib/sequel/model.rb +3 -1
  149. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  150. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  151. data/lib/sequel/plugins/association_pks.rb +60 -18
  152. data/lib/sequel/plugins/association_proxies.rb +8 -2
  153. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  154. data/lib/sequel/plugins/auto_validations.rb +39 -5
  155. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  156. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  157. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  158. data/lib/sequel/plugins/caching.rb +3 -0
  159. data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
  160. data/lib/sequel/plugins/column_encryption.rb +728 -0
  161. data/lib/sequel/plugins/composition.rb +7 -2
  162. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  163. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  164. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  165. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  166. data/lib/sequel/plugins/dirty.rb +60 -22
  167. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  168. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  169. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  170. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  171. data/lib/sequel/plugins/json_serializer.rb +57 -35
  172. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  173. data/lib/sequel/plugins/many_through_many.rb +108 -9
  174. data/lib/sequel/plugins/nested_attributes.rb +15 -3
  175. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  176. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
  177. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  178. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  179. data/lib/sequel/plugins/rcte_tree.rb +43 -35
  180. data/lib/sequel/plugins/serialization.rb +8 -3
  181. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  182. data/lib/sequel/plugins/sharding.rb +11 -5
  183. data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
  184. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  185. data/lib/sequel/plugins/static_cache.rb +9 -4
  186. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  187. data/lib/sequel/plugins/string_stripper.rb +1 -1
  188. data/lib/sequel/plugins/subclasses.rb +2 -0
  189. data/lib/sequel/plugins/throw_failures.rb +1 -1
  190. data/lib/sequel/plugins/timestamps.rb +1 -1
  191. data/lib/sequel/plugins/tree.rb +9 -4
  192. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  193. data/lib/sequel/plugins/unused_associations.rb +521 -0
  194. data/lib/sequel/plugins/update_or_create.rb +1 -1
  195. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  196. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  197. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  198. data/lib/sequel/sql.rb +20 -5
  199. data/lib/sequel/timezones.rb +63 -17
  200. data/lib/sequel/version.rb +1 -1
  201. metadata +113 -381
  202. data/Rakefile +0 -151
  203. data/doc/release_notes/4.0.0.txt +0 -262
  204. data/doc/release_notes/4.1.0.txt +0 -85
  205. data/doc/release_notes/4.10.0.txt +0 -226
  206. data/doc/release_notes/4.11.0.txt +0 -147
  207. data/doc/release_notes/4.12.0.txt +0 -105
  208. data/doc/release_notes/4.13.0.txt +0 -169
  209. data/doc/release_notes/4.14.0.txt +0 -68
  210. data/doc/release_notes/4.15.0.txt +0 -56
  211. data/doc/release_notes/4.16.0.txt +0 -36
  212. data/doc/release_notes/4.17.0.txt +0 -38
  213. data/doc/release_notes/4.18.0.txt +0 -36
  214. data/doc/release_notes/4.19.0.txt +0 -45
  215. data/doc/release_notes/4.2.0.txt +0 -129
  216. data/doc/release_notes/4.20.0.txt +0 -79
  217. data/doc/release_notes/4.21.0.txt +0 -94
  218. data/doc/release_notes/4.22.0.txt +0 -72
  219. data/doc/release_notes/4.23.0.txt +0 -65
  220. data/doc/release_notes/4.24.0.txt +0 -99
  221. data/doc/release_notes/4.25.0.txt +0 -181
  222. data/doc/release_notes/4.26.0.txt +0 -44
  223. data/doc/release_notes/4.27.0.txt +0 -78
  224. data/doc/release_notes/4.28.0.txt +0 -57
  225. data/doc/release_notes/4.29.0.txt +0 -41
  226. data/doc/release_notes/4.3.0.txt +0 -40
  227. data/doc/release_notes/4.30.0.txt +0 -37
  228. data/doc/release_notes/4.31.0.txt +0 -57
  229. data/doc/release_notes/4.32.0.txt +0 -132
  230. data/doc/release_notes/4.33.0.txt +0 -88
  231. data/doc/release_notes/4.34.0.txt +0 -86
  232. data/doc/release_notes/4.35.0.txt +0 -130
  233. data/doc/release_notes/4.36.0.txt +0 -116
  234. data/doc/release_notes/4.37.0.txt +0 -50
  235. data/doc/release_notes/4.38.0.txt +0 -67
  236. data/doc/release_notes/4.39.0.txt +0 -127
  237. data/doc/release_notes/4.4.0.txt +0 -92
  238. data/doc/release_notes/4.40.0.txt +0 -179
  239. data/doc/release_notes/4.41.0.txt +0 -77
  240. data/doc/release_notes/4.42.0.txt +0 -221
  241. data/doc/release_notes/4.43.0.txt +0 -87
  242. data/doc/release_notes/4.44.0.txt +0 -125
  243. data/doc/release_notes/4.45.0.txt +0 -370
  244. data/doc/release_notes/4.46.0.txt +0 -404
  245. data/doc/release_notes/4.47.0.txt +0 -56
  246. data/doc/release_notes/4.48.0.txt +0 -293
  247. data/doc/release_notes/4.49.0.txt +0 -222
  248. data/doc/release_notes/4.5.0.txt +0 -34
  249. data/doc/release_notes/4.6.0.txt +0 -30
  250. data/doc/release_notes/4.7.0.txt +0 -103
  251. data/doc/release_notes/4.8.0.txt +0 -175
  252. data/doc/release_notes/4.9.0.txt +0 -190
  253. data/spec/adapter_spec.rb +0 -4
  254. data/spec/adapters/db2_spec.rb +0 -170
  255. data/spec/adapters/mssql_spec.rb +0 -804
  256. data/spec/adapters/mysql_spec.rb +0 -1065
  257. data/spec/adapters/oracle_spec.rb +0 -371
  258. data/spec/adapters/postgres_spec.rb +0 -4125
  259. data/spec/adapters/spec_helper.rb +0 -44
  260. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  261. data/spec/adapters/sqlite_spec.rb +0 -652
  262. data/spec/bin_spec.rb +0 -278
  263. data/spec/core/connection_pool_spec.rb +0 -1250
  264. data/spec/core/database_spec.rb +0 -2865
  265. data/spec/core/dataset_spec.rb +0 -5515
  266. data/spec/core/deprecated_spec.rb +0 -70
  267. data/spec/core/expression_filters_spec.rb +0 -1455
  268. data/spec/core/mock_adapter_spec.rb +0 -722
  269. data/spec/core/object_graph_spec.rb +0 -336
  270. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  271. data/spec/core/schema_generator_spec.rb +0 -214
  272. data/spec/core/schema_spec.rb +0 -1826
  273. data/spec/core/spec_helper.rb +0 -24
  274. data/spec/core/version_spec.rb +0 -14
  275. data/spec/core_extensions_spec.rb +0 -763
  276. data/spec/core_model_spec.rb +0 -2
  277. data/spec/core_spec.rb +0 -1
  278. data/spec/deprecation_helper.rb +0 -30
  279. data/spec/extensions/accessed_columns_spec.rb +0 -51
  280. data/spec/extensions/active_model_spec.rb +0 -99
  281. data/spec/extensions/after_initialize_spec.rb +0 -28
  282. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  283. data/spec/extensions/association_dependencies_spec.rb +0 -125
  284. data/spec/extensions/association_pks_spec.rb +0 -423
  285. data/spec/extensions/association_proxies_spec.rb +0 -100
  286. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  287. data/spec/extensions/auto_validations_spec.rb +0 -229
  288. data/spec/extensions/blacklist_security_spec.rb +0 -95
  289. data/spec/extensions/blank_spec.rb +0 -69
  290. data/spec/extensions/boolean_readers_spec.rb +0 -93
  291. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  292. data/spec/extensions/caching_spec.rb +0 -273
  293. data/spec/extensions/caller_logging_spec.rb +0 -52
  294. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  295. data/spec/extensions/column_conflicts_spec.rb +0 -75
  296. data/spec/extensions/column_select_spec.rb +0 -129
  297. data/spec/extensions/columns_introspection_spec.rb +0 -90
  298. data/spec/extensions/columns_updated_spec.rb +0 -35
  299. data/spec/extensions/composition_spec.rb +0 -248
  300. data/spec/extensions/connection_expiration_spec.rb +0 -151
  301. data/spec/extensions/connection_validator_spec.rb +0 -144
  302. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  303. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  304. data/spec/extensions/constraint_validations_spec.rb +0 -439
  305. data/spec/extensions/core_refinements_spec.rb +0 -528
  306. data/spec/extensions/csv_serializer_spec.rb +0 -183
  307. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  308. data/spec/extensions/dataset_associations_spec.rb +0 -365
  309. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  310. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  311. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  312. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  313. data/spec/extensions/defaults_setter_spec.rb +0 -150
  314. data/spec/extensions/delay_add_association_spec.rb +0 -73
  315. data/spec/extensions/dirty_spec.rb +0 -189
  316. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  317. data/spec/extensions/eager_each_spec.rb +0 -62
  318. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  319. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  320. data/spec/extensions/error_splitter_spec.rb +0 -18
  321. data/spec/extensions/error_sql_spec.rb +0 -20
  322. data/spec/extensions/escaped_like_spec.rb +0 -40
  323. data/spec/extensions/eval_inspect_spec.rb +0 -81
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -291
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -864
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -111
  348. data/spec/extensions/nested_attributes_spec.rb +0 -767
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
  356. data/spec/extensions/pg_enum_spec.rb +0 -118
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -519
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -177
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -870
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -63
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -471
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/throw_failures_spec.rb +0 -74
  411. data/spec/extensions/timestamps_spec.rb +0 -209
  412. data/spec/extensions/to_dot_spec.rb +0 -153
  413. data/spec/extensions/touch_spec.rb +0 -226
  414. data/spec/extensions/tree_spec.rb +0 -334
  415. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  416. data/spec/extensions/unlimited_update_spec.rb +0 -21
  417. data/spec/extensions/update_or_create_spec.rb +0 -83
  418. data/spec/extensions/update_primary_key_spec.rb +0 -105
  419. data/spec/extensions/update_refresh_spec.rb +0 -59
  420. data/spec/extensions/uuid_spec.rb +0 -101
  421. data/spec/extensions/validate_associated_spec.rb +0 -52
  422. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  423. data/spec/extensions/validation_contexts_spec.rb +0 -31
  424. data/spec/extensions/validation_helpers_spec.rb +0 -525
  425. data/spec/extensions/whitelist_security_spec.rb +0 -157
  426. data/spec/extensions/xml_serializer_spec.rb +0 -213
  427. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  428. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  429. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  431. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  432. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  433. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  434. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  436. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  437. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  438. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  439. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  440. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  441. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  443. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  444. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  446. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  447. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  448. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  449. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  450. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  451. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  452. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  453. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  457. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  458. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  459. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  460. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  461. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  462. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  466. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  468. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  469. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  471. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  473. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  474. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  475. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  476. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  478. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  479. data/spec/guards_helper.rb +0 -59
  480. data/spec/integration/associations_test.rb +0 -2597
  481. data/spec/integration/database_test.rb +0 -113
  482. data/spec/integration/dataset_test.rb +0 -1981
  483. data/spec/integration/eager_loader_test.rb +0 -687
  484. data/spec/integration/migrator_test.rb +0 -262
  485. data/spec/integration/model_test.rb +0 -203
  486. data/spec/integration/plugin_test.rb +0 -2396
  487. data/spec/integration/prepared_statement_test.rb +0 -405
  488. data/spec/integration/schema_test.rb +0 -889
  489. data/spec/integration/spec_helper.rb +0 -65
  490. data/spec/integration/timezone_test.rb +0 -86
  491. data/spec/integration/transaction_test.rb +0 -603
  492. data/spec/integration/type_test.rb +0 -127
  493. data/spec/model/association_reflection_spec.rb +0 -803
  494. data/spec/model/associations_spec.rb +0 -4738
  495. data/spec/model/base_spec.rb +0 -875
  496. data/spec/model/class_dataset_methods_spec.rb +0 -146
  497. data/spec/model/dataset_methods_spec.rb +0 -198
  498. data/spec/model/eager_loading_spec.rb +0 -2377
  499. data/spec/model/hooks_spec.rb +0 -370
  500. data/spec/model/inflector_spec.rb +0 -26
  501. data/spec/model/model_spec.rb +0 -956
  502. data/spec/model/plugins_spec.rb +0 -429
  503. data/spec/model/record_spec.rb +0 -2118
  504. data/spec/model/spec_helper.rb +0 -46
  505. data/spec/model/validations_spec.rb +0 -220
  506. data/spec/model_no_assoc_spec.rb +0 -1
  507. data/spec/model_spec.rb +0 -1
  508. data/spec/plugin_spec.rb +0 -1
  509. data/spec/sequel_coverage.rb +0 -15
  510. data/spec/sequel_warning.rb +0 -4
  511. data/spec/spec_config.rb +0 -12
@@ -1,1250 +0,0 @@
1
- require_relative "spec_helper"
2
- require_relative '../../lib/sequel/connection_pool/sharded_threaded'
3
-
4
- connection_pool_defaults = {:pool_timeout=>5, :max_connections=>4}
5
- st_connection_pool_defaults = connection_pool_defaults.merge(:single_threaded=>true)
6
-
7
- mock_db = lambda do |*a, &b|
8
- db = Sequel.mock
9
- db.define_singleton_method(:connect){|c| b.arity == 1 ? b.call(c) : b.call} if b
10
- if b2 = a.shift
11
- db.define_singleton_method(:disconnect_connection){|c| b2.arity == 1 ? b2.call(c) : b2.call}
12
- end
13
- # Work around JRuby Issue #3854
14
- db.singleton_class.send(:public, :connect, :disconnect_connection)
15
- db
16
- end
17
-
18
- describe "An empty ConnectionPool" do
19
- before do
20
- @cpool = Sequel::ConnectionPool.get_pool(mock_db.call, connection_pool_defaults)
21
- end
22
-
23
- it "should have no available connections" do
24
- @cpool.available_connections.must_equal []
25
- end
26
-
27
- it "should have no allocated connections" do
28
- @cpool.allocated.must_equal({})
29
- end
30
-
31
- it "should have a size of zero" do
32
- @cpool.size.must_equal 0
33
- end
34
-
35
- it "should raise Error for bad pool class" do
36
- proc{Sequel::ConnectionPool.get_pool(mock_db.call, :pool_class=>:foo)}.must_raise Sequel::Error
37
- end
38
- end
39
-
40
- describe "ConnectionPool options" do
41
- it "should support string option values" do
42
- cpool = Sequel::ConnectionPool.get_pool(mock_db.call, {:max_connections=>'5', :pool_timeout=>'3'})
43
- cpool.max_size.must_equal 5
44
- cpool.instance_variable_get(:@timeout).must_equal 3
45
- end
46
-
47
- it "should raise an error unless size is positive" do
48
- lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>0)}.must_raise(Sequel::Error)
49
- lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>-10)}.must_raise(Sequel::Error)
50
- lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'-10')}.must_raise(Sequel::Error)
51
- lambda{Sequel::ConnectionPool.get_pool(mock_db.call{1}, :max_connections=>'0')}.must_raise(Sequel::Error)
52
- end
53
- end
54
-
55
- describe "A connection pool handling connections" do
56
- before do
57
- @max_size = 2
58
- msp = proc{@max_size=3}
59
- @cpool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){:got_connection}, connection_pool_defaults.merge(:max_connections=>@max_size))
60
- end
61
-
62
- it "#hold should increment #size" do
63
- @cpool.hold do
64
- @cpool.size.must_equal 1
65
- @cpool.hold {@cpool.hold {@cpool.size.must_equal 1}}
66
- Thread.new{@cpool.hold {_(@cpool.size).must_equal 2}}.join
67
- end
68
- end
69
-
70
- it "#hold should add the connection to the #allocated array" do
71
- @cpool.hold do
72
- @cpool.allocated.size.must_equal 1
73
-
74
- @cpool.allocated.must_equal(Thread.current=>:got_connection)
75
- end
76
- end
77
-
78
- it "#hold should yield a new connection" do
79
- @cpool.hold {|conn| conn.must_equal :got_connection}
80
- end
81
-
82
- it "a connection should be de-allocated after it has been used in #hold" do
83
- @cpool.hold {}
84
- @cpool.allocated.size.must_equal 0
85
- end
86
-
87
- it "#hold should return the value of its block" do
88
- @cpool.hold {:block_return}.must_equal :block_return
89
- end
90
-
91
- it "#make_new should not make more than max_size connections" do
92
- q = Queue.new
93
- 50.times{Thread.new{@cpool.hold{q.pop}}}
94
- 50.times{q.push nil}
95
- @cpool.size.must_be :<=, @max_size
96
- end
97
-
98
- it "database's disconnect connection method should be called when a disconnect is detected" do
99
- @max_size.must_equal 2
100
- proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
101
- @max_size.must_equal 3
102
- end
103
-
104
- it "#hold should remove the connection if a DatabaseDisconnectError is raised" do
105
- @cpool.size.must_equal 0
106
- q, q1 = Queue.new, Queue.new
107
- @cpool.hold{Thread.new{@cpool.hold{q1.pop; q.push nil}; q1.pop; q.push nil}; q1.push nil; q.pop; q1.push nil; q.pop}
108
- @cpool.size.must_equal 2
109
- proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
110
- @cpool.size.must_equal 1
111
- proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
112
- @cpool.size.must_equal 0
113
- proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
114
- @cpool.size.must_equal 0
115
- end
116
- end
117
-
118
- describe "A connection pool handling connection errors" do
119
- it "#hold should raise a Sequel::DatabaseConnectionError if an exception is raised by the connection_proc" do
120
- cpool = Sequel::ConnectionPool.get_pool(mock_db.call{raise Interrupt}, connection_pool_defaults)
121
- proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
122
- cpool.size.must_equal 0
123
- end
124
-
125
- it "#hold should raise a Sequel::DatabaseConnectionError if nil is returned by the connection_proc" do
126
- cpool = Sequel::ConnectionPool.get_pool(mock_db.call{nil}, connection_pool_defaults)
127
- proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
128
- cpool.size.must_equal 0
129
- end
130
- end
131
-
132
- describe "ConnectionPool#hold" do
133
- before do
134
- value = 0
135
- c = @c = Class.new do
136
- define_method(:initialize){value += 1}
137
- define_method(:value){value}
138
- end
139
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{c.new}, connection_pool_defaults)
140
- end
141
-
142
- it "shoulda use the database's connect method to get new connections" do
143
- res = nil
144
- @pool.hold {|c| res = c}
145
- res.must_be_kind_of(@c)
146
- res.value.must_equal 1
147
- @pool.hold {|c| res = c}
148
- res.must_be_kind_of(@c)
149
- res.value.must_equal 1 # the connection maker is invoked only once
150
- end
151
-
152
- it "should be re-entrant by the same thread" do
153
- cc = nil
154
- @pool.hold {|c| @pool.hold {|c1| @pool.hold {|c2| cc = c2}}}
155
- cc.must_be_kind_of(@c)
156
- end
157
-
158
- it "should catch exceptions and reraise them" do
159
- proc {@pool.hold {|c| c.foobar}}.must_raise(NoMethodError)
160
- end
161
- end
162
-
163
- describe "A connection pool with a max size of 1" do
164
- before do
165
- @invoked_count = 0
166
- icp = proc{@invoked_count += 1}
167
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{icp.call; 'herro'.dup}, connection_pool_defaults.merge(:max_connections=>1))
168
- end
169
-
170
- it "should let only one thread access the connection at any time" do
171
- cc,c1, c2 = nil
172
- q, q1 = Queue.new, Queue.new
173
-
174
- t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; q1.push nil; q.pop}}
175
- q1.pop
176
- cc.must_equal 'herro'
177
- c1.must_equal 'herro'
178
-
179
- t2 = Thread.new {@pool.hold {|c| c2 = c.dup; q1.push nil; q.pop;}}
180
-
181
- # connection held by t1
182
- t1.must_be :alive?
183
- t2.must_be :alive?
184
-
185
- cc.must_equal 'herro'
186
- c1.must_equal 'herro'
187
- c2.must_be_nil
188
-
189
- @pool.available_connections.must_be :empty?
190
- @pool.allocated.must_equal(t1=>cc)
191
-
192
- cc.gsub!('rr', 'll')
193
- q.push nil
194
- q1.pop
195
-
196
- t1.join
197
- t2.must_be :alive?
198
-
199
- c2.must_equal 'hello'
200
-
201
- @pool.available_connections.must_be :empty?
202
- @pool.allocated.must_equal(t2=>cc)
203
-
204
- #connection released
205
- q.push nil
206
- t2.join
207
-
208
- @invoked_count.must_equal 1
209
- @pool.size.must_equal 1
210
- @pool.available_connections.must_equal [cc]
211
- @pool.allocated.must_be :empty?
212
- end
213
-
214
- it "should let the same thread reenter #hold" do
215
- c1, c2, c3 = nil
216
- @pool.hold do |c|
217
- c1 = c
218
- @pool.hold do |cc2|
219
- c2 = cc2
220
- @pool.hold do |cc3|
221
- c3 = cc3
222
- end
223
- end
224
- end
225
- c1.must_equal 'herro'
226
- c2.must_equal 'herro'
227
- c3.must_equal 'herro'
228
-
229
- @invoked_count.must_equal 1
230
- @pool.size.must_equal 1
231
- @pool.available_connections.size.must_equal 1
232
- @pool.allocated.must_be :empty?
233
- end
234
- end
235
-
236
- ThreadedConnectionPoolSpecs = shared_description do
237
- it "should not have all_connections yield connections allocated to other threads" do
238
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
239
- q, q1 = Queue.new, Queue.new
240
- t = Thread.new do
241
- pool.hold do |c1|
242
- q1.push nil
243
- q.pop
244
- end
245
- end
246
- pool.hold do |c1|
247
- q1.pop
248
- pool.all_connections{|c| c.must_equal c1}
249
- q.push nil
250
- end
251
- t.join
252
- end
253
-
254
- it "should work when acquire fails and then succeeds" do
255
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
256
- def pool._acquire(*)
257
- if @called
258
- super
259
- else
260
- @called = true
261
- nil
262
- end
263
- end
264
- c = nil
265
- pool.hold do |c1|
266
- c = c1
267
- end
268
- c.wont_be_nil
269
- end
270
-
271
- it "should wait until a connection is available if all are checked out" do
272
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0.1))
273
- q, q1 = Queue.new, Queue.new
274
- t = Thread.new do
275
- pool.hold do |c|
276
- q1.push nil
277
- 3.times{Thread.pass}
278
- q.pop
279
- end
280
- end
281
- q1.pop
282
- proc{pool.hold{}}.must_raise(Sequel::PoolTimeout)
283
- q.push nil
284
- t.join
285
- end
286
-
287
- it "should not have all_connections yield all available connections" do
288
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>2, :pool_timeout=>0))
289
- q, q1 = Queue.new, Queue.new
290
- b = []
291
- t = Thread.new do
292
- pool.hold do |c1|
293
- @m.synchronize{b << c1}
294
- q1.push nil
295
- q.pop
296
- end
297
- end
298
- pool.hold do |c1|
299
- q1.pop
300
- @m.synchronize{b << c1}
301
- q.push nil
302
- end
303
- t.join
304
- a = []
305
- pool.all_connections{|c| a << c}
306
- a.sort.must_equal b.sort
307
- end
308
-
309
- it "should raise a PoolTimeout error if a connection couldn't be acquired before timeout" do
310
- q, q1 = Queue.new, Queue.new
311
- db = mock_db.call(&@icpp)
312
- db.opts[:name] = 'testing'
313
- pool = Sequel::ConnectionPool.get_pool(db, @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
314
- t = Thread.new{pool.hold{|c| q1.push nil; q.pop}}
315
- q1.pop
316
- e = proc{pool.hold{|c|}}.must_raise(Sequel::PoolTimeout)
317
- e.message.must_include "name: testing"
318
- e.message.must_include "server: default" if pool.is_a?(Sequel::ShardedThreadedConnectionPool)
319
- q.push nil
320
- t.join
321
- end
322
-
323
- it "should not add a disconnected connection back to the pool if the disconnection_proc raises an error" do
324
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| raise Sequel::Error}, &@icpp), @cp_opts.merge(:max_connections=>1, :pool_timeout=>0))
325
- proc{pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::Error)
326
- pool.available_connections.length.must_equal 0
327
- end
328
-
329
- it "should let five threads simultaneously access separate connections" do
330
- cc = {}
331
- threads = []
332
- q, q1, q2 = Queue.new, Queue.new, Queue.new
333
-
334
- 5.times{|i| threads << Thread.new{@pool.hold{|c| q.pop; @m.synchronize{cc[i] = c}; q1.push nil; q2.pop}}; q.push nil; q1.pop}
335
- threads.each {|t| t.must_be :alive?}
336
- cc.size.must_equal 5
337
- @invoked_count.must_equal 5
338
- @pool.size.must_equal 5
339
- @pool.available_connections.must_be :empty?
340
-
341
- h = {}
342
- i = 0
343
- threads.each{|t| h[t] = (i+=1)}
344
- @pool.allocated.must_equal h
345
- @pool.available_connections.must_equal []
346
- 5.times{q2.push nil}
347
- threads.each{|t| t.join}
348
-
349
- @pool.available_connections.size.must_equal 5
350
- @pool.allocated.must_be :empty?
351
- end
352
-
353
- it "should allow simultaneous connections without preconnecting" do
354
- @pool.disconnect
355
- b = @icpp
356
-
357
- time = Time.now
358
- cc = {}
359
- threads = []
360
- results = []
361
- j = 0
362
- q, q1, q2, q3, q4 = Queue.new, Queue.new, Queue.new, Queue.new, Queue.new
363
- m = @m
364
- @pool.db.define_singleton_method(:connect) do |server|
365
- q1.pop
366
- m.synchronize{q3.push(j += 1)}
367
- q4.pop
368
- b.call
369
- end
370
- 5.times{|i| threads << Thread.new{@pool.hold{|c| m.synchronize{i -= 1; cc[i] = c}; q2.pop; q.push nil}}}
371
- 5.times{|i| q1.push nil}
372
- 5.times{|i| results << q3.pop}
373
- 5.times{|i| q4.push nil}
374
- 5.times{|i| q2.push nil}
375
- 5.times{|i| q.pop}
376
- results.sort.must_equal (1..5).to_a
377
- threads.each(&:join)
378
- (Time.now - time).must_be :<, 0.75
379
-
380
- threads.each{|t| t.wont_be :alive?}
381
- cc.size.must_equal 5
382
- @invoked_count.must_equal 5
383
- @pool.size.must_equal 5
384
- @pool.available_connections.sort.must_equal (1..5).to_a
385
- end
386
-
387
- it "should block threads until a connection becomes available" do
388
- cc = {}
389
- threads = []
390
- q, q1 = Queue.new, Queue.new
391
-
392
- 5.times{|i| threads << Thread.new{@pool.hold{|c| @m.synchronize{cc[i] = c}; q1.push nil; q.pop}}}
393
- 5.times{q1.pop}
394
- threads.each {|t| t.must_be :alive?}
395
- @pool.available_connections.must_be :empty?
396
-
397
- 3.times {|i| threads << Thread.new {@pool.hold {|c| @m.synchronize{cc[i + 5] = c}; q1.push nil}}}
398
-
399
- threads[5].must_be :alive?
400
- threads[6].must_be :alive?
401
- threads[7].must_be :alive?
402
- cc.size.must_equal 5
403
- cc[5].must_be_nil
404
- cc[6].must_be_nil
405
- cc[7].must_be_nil
406
-
407
- 5.times{q.push nil}
408
- 5.times{|i| threads[i].join}
409
- 3.times{q1.pop}
410
- 3.times{|i| threads[i+5].join}
411
-
412
- threads.each {|t| t.wont_be :alive?}
413
- cc.values.uniq.length.must_equal 5
414
-
415
- @pool.size.must_equal 5
416
- @invoked_count.must_equal 5
417
- @pool.available_connections.size.must_equal 5
418
- @pool.allocated.must_be :empty?
419
- end
420
-
421
- it "should block threads until a connection becomes available, when assign connection returns nil" do
422
- # Shorten pool timeout, as making assign_connection return nil when there are
423
- # connections in the pool can make the pool later block until the timeout expires,
424
- # since then the pool will not be signalled correctly.
425
- # This spec is only added for coverage purposes, to ensure that fallback code is tested.
426
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:pool_timeout=>0.25))
427
-
428
- cc = {}
429
- threads = []
430
- q, q1 = Queue.new, Queue.new
431
-
432
- 5.times{|i| threads << Thread.new{@pool.hold{|c| @m.synchronize{cc[i] = c}; q1.push nil; q.pop}}}
433
- 5.times{q1.pop}
434
- threads.each {|t| t.must_be :alive?}
435
- @pool.available_connections.must_be :empty?
436
-
437
- def @pool.assign_connection(*) nil end
438
- 3.times {|i| threads << Thread.new {@pool.hold {|c| @m.synchronize{cc[i + 5] = c}; q1.push nil}}}
439
-
440
- threads[5].must_be :alive?
441
- threads[6].must_be :alive?
442
- threads[7].must_be :alive?
443
- cc.size.must_equal 5
444
- cc[5].must_be_nil
445
- cc[6].must_be_nil
446
- cc[7].must_be_nil
447
-
448
- 5.times{q.push nil}
449
- 5.times{|i| threads[i].join}
450
- 3.times{q1.pop}
451
- 3.times{|i| threads[i+5].join}
452
-
453
- threads.each {|t| t.wont_be :alive?}
454
- cc.values.uniq.length.must_equal 5
455
-
456
- @pool.size.must_equal 5
457
- @invoked_count.must_equal 5
458
- @pool.available_connections.size.must_equal 5
459
- @pool.allocated.must_be :empty?
460
- end
461
-
462
- it "should block threads until a connection becomes available, and reconnect on disconnection" do
463
- cc = {}
464
- threads = []
465
- exceptions = []
466
- q, q1, q2, q3 = Queue.new, Queue.new, Queue.new, Queue.new
467
- b = @icpp
468
- @pool.db.define_singleton_method(:connect) do |server|
469
- b.call
470
- Object.new
471
- end
472
- 5.times{|i| threads << Thread.new{@pool.hold{|c| @m.synchronize{cc[i] = c}; q1.push nil; q.pop; raise Sequel::DatabaseDisconnectError} rescue q2.push($!)}}
473
- 5.times{q1.pop}
474
- threads.each {|t| t.must_be :alive?}
475
- @pool.available_connections.must_be :empty?
476
-
477
- 3.times {|i| threads << Thread.new {@pool.hold {|c| @m.synchronize{cc[i + 5] = c}; q1.push nil; q3.pop}}}
478
-
479
- threads[5].must_be :alive?
480
- threads[6].must_be :alive?
481
- threads[7].must_be :alive?
482
- cc.size.must_equal 5
483
- cc[5].must_be_nil
484
- cc[6].must_be_nil
485
- cc[7].must_be_nil
486
-
487
- 5.times{q.push nil}
488
- 5.times{|i| threads[i].join}
489
- 5.times{exceptions << q2.pop}
490
- 3.times{q1.pop}
491
- 3.times{q3.push nil}
492
- 3.times{|i| threads[i+5].join}
493
-
494
- threads.each {|t| t.wont_be :alive?}
495
- exceptions.length.must_equal 5
496
- cc.values.uniq.length.must_equal 8
497
-
498
- @pool.size.must_equal 3
499
- @invoked_count.must_equal 8
500
- @pool.available_connections.size.must_equal 3
501
- @pool.allocated.must_be :empty?
502
- end
503
-
504
- it "should store connections in a stack if :connection_handling=>:stack" do
505
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:stack))
506
- c2 = nil
507
- c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
508
- @pool.size.must_equal 2
509
- @pool.hold{|cc| cc.must_equal c}
510
- @pool.hold{|cc| cc.must_equal c}
511
- @pool.hold do |cc|
512
- cc.must_equal c
513
- Thread.new{@pool.hold{|cc2| _(cc2).must_equal c2}}.join
514
- end
515
- end
516
-
517
- it "should store connections in a queue if :connection_handling=>:queue" do
518
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:queue))
519
- c2 = nil
520
- c = @pool.hold{|cc| Thread.new{@pool.hold{|cc2| c2 = cc2}}.join; cc}
521
- @pool.size.must_equal 2
522
- @pool.hold{|cc| cc.must_equal c2}
523
- @pool.hold{|cc| cc.must_equal c}
524
- @pool.hold do |cc|
525
- cc.must_equal c2
526
- Thread.new{@pool.hold{|cc2| _(cc2).must_equal c}}.join
527
- end
528
- end
529
-
530
- it "should not store connections if :connection_handling=>:disconnect" do
531
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:connection_handling=>:disconnect))
532
- d = []
533
- m = @m
534
- @pool.db.define_singleton_method(:disconnect_connection){|c| m.synchronize{d << c}}
535
- @pool.hold do |cc|
536
- cc.must_equal 1
537
- Thread.new{@pool.hold{|cc2| _(cc2).must_equal 2}}.join
538
- d.must_equal [2]
539
- @pool.hold{|cc3| cc3.must_equal 1}
540
- end
541
- @pool.size.must_equal 0
542
- d.must_equal [2, 1]
543
-
544
- @pool.hold{|cc| cc.must_equal 3}
545
- @pool.size.must_equal 0
546
- d.must_equal [2, 1, 3]
547
-
548
- @pool.hold{|cc| cc.must_equal 4}
549
- @pool.size.must_equal 0
550
- d.must_equal [2, 1, 3, 4]
551
- end
552
-
553
-
554
- it "should handle dead threads with checked out connections" do
555
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1))
556
-
557
- skip = true
558
- # Leave allocated connection to emulate dead thread with checked out connection
559
- pool.define_singleton_method(:release){|*a| return if skip; super(*a)}
560
- Thread.new{pool.hold{Thread.current.kill}}.join
561
- skip = false
562
-
563
- pool.allocated.wont_be :empty?
564
- pool.available_connections.must_be :empty?
565
-
566
- pool.hold{|c1| c1}
567
- pool.allocated.must_be :empty?
568
- pool.available_connections.wont_be :empty?
569
-
570
- pool.disconnect
571
- pool.allocated.must_be :empty?
572
- pool.available_connections.must_be :empty?
573
- end
574
- end
575
-
576
- describe "Threaded Unsharded Connection Pool" do
577
- before do
578
- @m = Mutex.new
579
- @invoked_count = 0
580
- @icpp = proc{@m.synchronize{@invoked_count += 1}}
581
- @cp_opts = connection_pool_defaults.merge(:max_connections=>5)
582
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
583
- end
584
-
585
- include ThreadedConnectionPoolSpecs
586
- end
587
-
588
- describe "Threaded Sharded Connection Pool" do
589
- before do
590
- @m = Mutex.new
591
- @invoked_count = 0
592
- @icpp = proc{@m.synchronize{@invoked_count += 1}}
593
- @cp_opts = connection_pool_defaults.merge(:max_connections=>5, :servers=>{})
594
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts)
595
- end
596
-
597
- include ThreadedConnectionPoolSpecs
598
- end
599
-
600
- describe "ConnectionPool#disconnect" do
601
- before do
602
- @count = 0
603
- cp = proc{@count += 1}
604
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{{:id => cp.call}}, connection_pool_defaults.merge(:max_connections=>5, :servers=>{}))
605
- threads = []
606
- q, q1 = Queue.new, Queue.new
607
- 5.times {|i| threads << Thread.new {@pool.hold {|c| q1.push nil; q.pop}}}
608
- 5.times{q1.pop}
609
- 5.times{q.push nil}
610
- threads.each {|t| t.join}
611
- end
612
-
613
- it "should invoke the given block for each available connection" do
614
- @pool.size.must_equal 5
615
- @pool.available_connections.size.must_equal 5
616
- @pool.available_connections.each {|c| c[:id].wont_equal nil}
617
- conns = []
618
- @pool.db.define_singleton_method(:disconnect_connection){|c| conns << c}
619
- @pool.disconnect
620
- conns.size.must_equal 5
621
- end
622
-
623
- it "should remove all available connections" do
624
- @pool.size.must_equal 5
625
- @pool.disconnect
626
- @pool.size.must_equal 0
627
- end
628
-
629
- it "should disconnect connections in use as soon as they are no longer in use" do
630
- @pool.size.must_equal 5
631
- @pool.hold do |conn|
632
- @pool.available_connections.size.must_equal 4
633
- @pool.available_connections.each {|c| c.wont_be_same_as(conn)}
634
- conns = []
635
- @pool.db.define_singleton_method(:disconnect_connection){|c| conns << c}
636
- @pool.disconnect
637
- conns.size.must_equal 4
638
- @pool.size.must_equal 1
639
- end
640
- @pool.size.must_equal 0
641
- end
642
- end
643
-
644
- describe "A connection pool with multiple servers" do
645
- before do
646
- ic = @invoked_counts = Hash.new(0)
647
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, connection_pool_defaults.merge(:servers=>{:read_only=>{}}))
648
- end
649
-
650
- it "should support preconnect method that immediately creates the maximum number of connections" do
651
- @pool.send(:preconnect)
652
- i = 0
653
- @pool.all_connections{|c1| i+=1}
654
- i.must_equal(@pool.max_size * 2)
655
- end
656
-
657
- it "should support preconnect method that immediately creates the maximum number of connections concurrently" do
658
- @pool.send(:preconnect, true)
659
- i = 0
660
- @pool.all_connections{|c1| i+=1}
661
- i.must_equal(@pool.max_size * 2)
662
- end
663
-
664
- it "#all_connections should return connections for all servers" do
665
- @pool.hold{}
666
- @pool.all_connections{|c1| c1.must_equal "default1"}
667
- a = []
668
- @pool.hold(:read_only) do |c|
669
- @pool.all_connections{|c1| a << c1}
670
- end
671
- a.sort_by{|c| c.to_s}.must_equal ["default1", "read_only1"]
672
- end
673
-
674
- it "#servers should return symbols for all servers" do
675
- @pool.servers.sort_by{|s| s.to_s}.must_equal [:default, :read_only]
676
- end
677
-
678
- it "should use the :default server by default" do
679
- @pool.size.must_equal 0
680
- @pool.hold do |c|
681
- c.must_equal "default1"
682
- @pool.allocated.must_equal(Thread.current=>"default1")
683
- end
684
- @pool.available_connections.must_equal ["default1"]
685
- @pool.size.must_equal 1
686
- @invoked_counts.must_equal(:default=>1)
687
- end
688
-
689
- it "should use the :default server an invalid server is used" do
690
- @pool.hold do |c1|
691
- c1.must_equal "default1"
692
- @pool.hold(:blah) do |c2|
693
- c2.must_equal c1
694
- @pool.hold(:blah2) do |c3|
695
- c2.must_equal c3
696
- end
697
- end
698
- end
699
- end
700
-
701
- it "should support a :servers_hash option used for converting the server argument" do
702
- ic = @invoked_counts
703
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, connection_pool_defaults.merge(:servers_hash=>Hash.new(:read_only), :servers=>{:read_only=>{}}))
704
- @pool.hold(:blah) do |c1|
705
- c1.must_equal "read_only1"
706
- @pool.hold(:blah) do |c2|
707
- c2.must_equal c1
708
- @pool.hold(:blah2) do |c3|
709
- c2.must_equal c3
710
- end
711
- end
712
- end
713
-
714
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, connection_pool_defaults.merge(:servers_hash=>Hash.new{|h,k| raise Sequel::Error}, :servers=>{:read_only=>{}}))
715
- proc{@pool.hold(:blah){|c1|}}.must_raise(Sequel::Error)
716
- end
717
-
718
- it "should use the requested server if server is given" do
719
- @pool.size(:read_only).must_equal 0
720
- @pool.hold(:read_only) do |c|
721
- c.must_equal "read_only1"
722
- @pool.allocated(:read_only).must_equal(Thread.current=>"read_only1")
723
- end
724
- @pool.available_connections(:read_only).must_equal ["read_only1"]
725
- @pool.size(:read_only).must_equal 1
726
- @invoked_counts.must_equal(:read_only=>1)
727
- end
728
-
729
- it "#hold should only yield connections for the server requested" do
730
- @pool.hold(:read_only) do |c|
731
- c.must_equal "read_only1"
732
- @pool.allocated(:read_only).must_equal(Thread.current=>"read_only1")
733
- @pool.hold do |d|
734
- d.must_equal "default1"
735
- @pool.hold do |e|
736
- e.must_equal d
737
- @pool.hold(:read_only){|b| b.must_equal c}
738
- end
739
- @pool.allocated.must_equal(Thread.current=>"default1")
740
- end
741
- end
742
- @invoked_counts.must_equal(:read_only=>1, :default=>1)
743
- end
744
-
745
- it "#disconnect should disconnect from all servers" do
746
- @pool.hold(:read_only){}
747
- @pool.hold{}
748
- conns = []
749
- @pool.size.must_equal 1
750
- @pool.size(:read_only).must_equal 1
751
- @pool.db.define_singleton_method(:disconnect_connection){|c| conns << c}
752
- @pool.disconnect
753
- conns.sort.must_equal %w'default1 read_only1'
754
- @pool.size.must_equal 0
755
- @pool.size(:read_only).must_equal 0
756
- @pool.hold(:read_only){|c| c.must_equal 'read_only2'}
757
- @pool.hold{|c| c.must_equal 'default2'}
758
- end
759
-
760
- it "#add_servers should add new servers to the pool" do
761
- pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
762
-
763
- pool.hold{}
764
- pool.hold(:server2){}
765
- pool.hold(:server3){}
766
- pool.hold(:server1) do
767
- pool.allocated.length.must_equal 0
768
- pool.allocated(:server1).length.must_equal 1
769
- pool.allocated(:server2).must_be_nil
770
- pool.allocated(:server3).must_be_nil
771
- pool.available_connections.length.must_equal 1
772
- pool.available_connections(:server1).length.must_equal 0
773
- pool.available_connections(:server2).must_be_nil
774
- pool.available_connections(:server3).must_be_nil
775
-
776
- pool.add_servers([:server2, :server3])
777
- pool.hold(:server2){}
778
- pool.hold(:server3) do
779
- pool.allocated.length.must_equal 0
780
- pool.allocated(:server1).length.must_equal 1
781
- pool.allocated(:server2).length.must_equal 0
782
- pool.allocated(:server3).length.must_equal 1
783
- pool.available_connections.length.must_equal 1
784
- pool.available_connections(:server1).length.must_equal 0
785
- pool.available_connections(:server2).length.must_equal 1
786
- pool.available_connections(:server3).length.must_equal 0
787
- end
788
- end
789
- end
790
-
791
- it "#add_servers should ignore existing keys" do
792
- pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
793
-
794
- pool.allocated.length.must_equal 0
795
- pool.allocated(:server1).length.must_equal 0
796
- pool.available_connections.length.must_equal 0
797
- pool.available_connections(:server1).length.must_equal 0
798
- pool.hold do |c1|
799
- c1.must_equal :default
800
- pool.allocated.length.must_equal 1
801
- pool.allocated(:server1).length.must_equal 0
802
- pool.available_connections.length.must_equal 0
803
- pool.available_connections(:server1).length.must_equal 0
804
- pool.hold(:server1) do |c2|
805
- c2.must_equal :server1
806
- pool.allocated.length.must_equal 1
807
- pool.allocated(:server1).length.must_equal 1
808
- pool.available_connections.length.must_equal 0
809
- pool.available_connections(:server1).length.must_equal 0
810
- pool.add_servers([:default, :server1])
811
- pool.allocated.length.must_equal 1
812
- pool.allocated(:server1).length.must_equal 1
813
- pool.available_connections.length.must_equal 0
814
- pool.available_connections(:server1).length.must_equal 0
815
- end
816
- pool.allocated.length.must_equal 1
817
- pool.allocated(:server1).length.must_equal 0
818
- pool.available_connections.length.must_equal 0
819
- pool.available_connections(:server1).length.must_equal 1
820
- pool.add_servers([:default, :server1])
821
- pool.allocated.length.must_equal 1
822
- pool.allocated(:server1).length.must_equal 0
823
- pool.available_connections.length.must_equal 0
824
- pool.available_connections(:server1).length.must_equal 1
825
- end
826
- pool.allocated.length.must_equal 0
827
- pool.allocated(:server1).length.must_equal 0
828
- pool.available_connections.length.must_equal 1
829
- pool.available_connections(:server1).length.must_equal 1
830
- pool.add_servers([:default, :server1])
831
- pool.allocated.length.must_equal 0
832
- pool.allocated(:server1).length.must_equal 0
833
- pool.available_connections.length.must_equal 1
834
- pool.available_connections(:server1).length.must_equal 1
835
- end
836
-
837
- it "#remove_servers should disconnect available connections immediately" do
838
- pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :max_connections=>5, :servers=>{:server1=>{}})
839
- threads = []
840
- q, q1 = Queue.new, Queue.new
841
- 5.times {|i| threads << Thread.new {pool.hold(:server1){|c| q1.push nil; q.pop}}}
842
- 5.times{q1.pop}
843
- 5.times{q.push nil}
844
- threads.each {|t| t.join}
845
-
846
- pool.size(:server1).must_equal 5
847
- pool.remove_servers([:server1])
848
- pool.size(:server1).must_equal 0
849
- end
850
-
851
- it "#remove_servers should disconnect connections in use as soon as they are returned to the pool" do
852
- dc = []
853
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
854
- c1 = nil
855
- pool.hold(:server1) do |c|
856
- pool.size(:server1).must_equal 1
857
- dc.must_equal []
858
- pool.remove_servers([:server1])
859
- pool.size(:server1).must_equal 0
860
- dc.must_equal []
861
- c1 = c
862
- end
863
- pool.size(:server1).must_equal 0
864
- dc.must_equal [c1]
865
- end
866
-
867
- it "#remove_servers should remove server related data structures immediately" do
868
- pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
869
- pool.available_connections(:server1).must_equal []
870
- pool.allocated(:server1).must_equal({})
871
- pool.remove_servers([:server1])
872
- pool.available_connections(:server1).must_be_nil
873
- pool.allocated(:server1).must_be_nil
874
- end
875
-
876
- it "#remove_servers should not allow the removal of the default server" do
877
- pool = Sequel::ConnectionPool.get_pool(mock_db.call{|s| s}, :servers=>{:server1=>{}})
878
- pool.remove_servers([:server1])
879
- proc{pool.remove_servers([:default])}.must_raise(Sequel::Error)
880
- end
881
-
882
- it "#remove_servers should ignore servers that have already been removed" do
883
- dc = []
884
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| dc << c}){|c| c}, :servers=>{:server1=>{}})
885
- c1 = nil
886
- pool.hold(:server1) do |c|
887
- pool.size(:server1).must_equal 1
888
- dc.must_equal []
889
- pool.remove_servers([:server1])
890
- pool.remove_servers([:server1])
891
- pool.size(:server1).must_equal 0
892
- dc.must_equal []
893
- c1 = c
894
- end
895
- pool.size(:server1).must_equal 0
896
- dc.must_equal [c1]
897
- end
898
- end
899
-
900
- describe "SingleConnectionPool" do
901
- before do
902
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call{1234}, st_connection_pool_defaults)
903
- end
904
-
905
- it "should provide a #hold method" do
906
- conn = nil
907
- @pool.hold{|c| conn = c}
908
- conn.must_equal 1234
909
- end
910
-
911
- it "should provide a #disconnect method" do
912
- conn = nil
913
- x = nil
914
- pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| conn = c; c.must_be_kind_of(Integer)}){1234}, st_connection_pool_defaults)
915
- pool.hold{|c| x = c}
916
- x.must_equal 1234
917
- pool.disconnect
918
- conn.must_equal 1234
919
- pool.disconnect
920
- end
921
- end
922
-
923
- describe "A single threaded pool with multiple servers" do
924
- before do
925
- @max_size=2
926
- msp = proc{@max_size += 1}
927
- @pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){|c| c}, st_connection_pool_defaults.merge(:servers=>{:read_only=>{}}))
928
- end
929
-
930
- it "should support preconnect method that immediately creates the maximum number of connections" do
931
- @pool.send(:preconnect)
932
- i = 0
933
- @pool.all_connections{|c1| i+=1}
934
- i.must_equal 2
935
- end
936
-
937
- it "should support preconnect method that immediately creates the maximum number of connections, ignoring concurrent param" do
938
- @pool.send(:preconnect, true)
939
- i = 0
940
- @pool.all_connections{|c1| i+=1}
941
- i.must_equal 2
942
- end
943
-
944
- it "#all_connections should return connections for all servers" do
945
- @pool.hold{}
946
- @pool.all_connections{|c1| c1.must_equal :default}
947
- a = []
948
- @pool.hold(:read_only) do
949
- @pool.all_connections{|c1| a << c1}
950
- end
951
- a.sort_by{|c| c.to_s}.must_equal [:default, :read_only]
952
- end
953
-
954
- it "#servers should return symbols for all servers" do
955
- @pool.servers.sort_by{|s| s.to_s}.must_equal [:default, :read_only]
956
- end
957
-
958
- it "#add_servers should add new servers to the pool" do
959
- @pool.hold(:blah){|c| c.must_equal :default}
960
- @pool.add_servers([:blah])
961
- @pool.hold(:blah){|c| c.must_equal :blah}
962
- end
963
-
964
- it "#add_servers should ignore keys already existing" do
965
- @pool.hold{|c| c.must_equal :default}
966
- @pool.hold(:read_only){|c| c.must_equal :read_only}
967
- @pool.add_servers([:default, :read_only])
968
- @pool.conn.must_equal :default
969
- @pool.conn(:read_only).must_equal :read_only
970
- end
971
-
972
- it "#remove_servers should remove servers from the pool" do
973
- @pool.hold(:read_only){|c| c.must_equal :read_only}
974
- @pool.remove_servers([:read_only])
975
- @pool.hold(:read_only){|c| c.must_equal :default}
976
- end
977
-
978
- it "#remove_servers should not allow the removal of the default server" do
979
- proc{@pool.remove_servers([:default])}.must_raise(Sequel::Error)
980
- end
981
-
982
- it "#remove_servers should disconnect connection immediately" do
983
- @pool.hold(:read_only){|c| c.must_equal :read_only}
984
- @pool.conn(:read_only).must_equal :read_only
985
- @pool.remove_servers([:read_only])
986
- @pool.conn(:read_only).must_be_nil
987
- @pool.hold{}
988
- @pool.conn(:read_only).must_equal :default
989
- end
990
-
991
- it "#remove_servers should ignore keys that do not exist" do
992
- @pool.remove_servers([:blah])
993
- end
994
-
995
- it "should use the :default server by default" do
996
- @pool.hold{|c| c.must_equal :default}
997
- @pool.conn.must_equal :default
998
- end
999
-
1000
- it "should use the :default server an invalid server is used" do
1001
- @pool.hold do |c1|
1002
- c1.must_equal :default
1003
- @pool.hold(:blah) do |c2|
1004
- c2.must_equal c1
1005
- @pool.hold(:blah2) do |c3|
1006
- c2.must_equal c3
1007
- end
1008
- end
1009
- end
1010
- end
1011
-
1012
- it "should use the requested server if server is given" do
1013
- @pool.hold(:read_only){|c| c.must_equal :read_only}
1014
- @pool.conn(:read_only).must_equal :read_only
1015
- end
1016
-
1017
- it "#hold should only yield connections for the server requested" do
1018
- @pool.hold(:read_only) do |c|
1019
- c.must_equal :read_only
1020
- @pool.hold do |d|
1021
- d.must_equal :default
1022
- @pool.hold do |e|
1023
- e.must_equal d
1024
- @pool.hold(:read_only){|b| b.must_equal c}
1025
- end
1026
- end
1027
- end
1028
- @pool.conn.must_equal :default
1029
- @pool.conn(:read_only).must_equal :read_only
1030
- end
1031
-
1032
- it "#disconnect should disconnect from all servers" do
1033
- @pool.hold(:read_only){}
1034
- @pool.hold{}
1035
- @pool.conn.must_equal :default
1036
- @pool.conn(:read_only).must_equal :read_only
1037
- @pool.disconnect
1038
- @max_size.must_equal 4
1039
- @pool.conn.must_be_nil
1040
- @pool.conn(:read_only).must_be_nil
1041
- end
1042
-
1043
- it ":disconnection_proc option should set the disconnection proc to use" do
1044
- @max_size.must_equal 2
1045
- proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
1046
- @max_size.must_equal 3
1047
- end
1048
-
1049
- it "#hold should remove the connection if a DatabaseDisconnectError is raised" do
1050
- @pool.instance_variable_get(:@conns).length.must_equal 0
1051
- @pool.hold{}
1052
- @pool.instance_variable_get(:@conns).length.must_equal 1
1053
- proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
1054
- @pool.instance_variable_get(:@conns).length.must_equal 0
1055
- end
1056
- end
1057
-
1058
- AllConnectionPoolClassesSpecs = shared_description do
1059
- it "should work correctly after being frozen" do
1060
- o = Object.new
1061
- db = mock_db.call{o}
1062
- cp = @class.new(db, {})
1063
- db.instance_variable_set(:@pool, cp)
1064
- db.freeze
1065
- cp.frozen?.must_equal true
1066
- db.synchronize{|c| c.must_be_same_as o}
1067
- end
1068
-
1069
- it "should have pool correctly handle disconnect errors not raised as DatabaseDisconnectError" do
1070
- db = mock_db.call{Object.new}
1071
- def db.dec; @dec ||= Class.new(StandardError) end
1072
- def db.database_error_classes; super + [dec] end
1073
- def db.disconnect_error?(e, opts); e.message =~ /foo/ end
1074
- cp = @class.new(db, {})
1075
-
1076
- conn = nil
1077
- cp.hold do |c|
1078
- conn = c
1079
- end
1080
-
1081
- proc do
1082
- cp.hold do |c|
1083
- c.must_equal conn
1084
- raise db.dec, "bar"
1085
- end
1086
- end.must_raise db.dec
1087
-
1088
- proc do
1089
- cp.hold do |c|
1090
- c.must_equal conn
1091
- raise StandardError
1092
- end
1093
- end.must_raise StandardError
1094
-
1095
- cp.hold do |c|
1096
- c.must_equal conn
1097
- end
1098
-
1099
- proc do
1100
- cp.hold do |c|
1101
- c.must_equal conn
1102
- raise db.dec, "foo"
1103
- end
1104
- end.must_raise db.dec
1105
-
1106
- cp.hold do |c|
1107
- c.wont_equal conn
1108
- end
1109
- end
1110
-
1111
- it "should have pool_type return a symbol" do
1112
- @class.new(mock_db.call{123}, {}).pool_type.must_be_kind_of(Symbol)
1113
- end
1114
-
1115
- it "should have all_connections yield current and available connections" do
1116
- p = @class.new(mock_db.call{123}, {})
1117
- p.hold{|c| p.all_connections{|c1| c.must_equal c1}}
1118
- end
1119
-
1120
- it "should have a size method that gives the current size of the pool" do
1121
- p = @class.new(mock_db.call{123}, {})
1122
- p.size.must_equal 0
1123
- p.hold{}
1124
- p.size.must_equal 1
1125
- end
1126
-
1127
- it "should have a max_size method that gives the maximum size of the pool" do
1128
- @class.new(mock_db.call{123}, {}).max_size.must_be :>=, 1
1129
- end
1130
-
1131
- it "should support preconnect method that immediately creates the maximum number of connections" do
1132
- p = @class.new(mock_db.call{123}, {})
1133
- p.send(:preconnect)
1134
- i = 0
1135
- p.all_connections{|c1| i+=1}
1136
- i.must_equal p.max_size
1137
- end
1138
-
1139
- it "should support preconnect method that immediately creates the maximum number of connections concurrently" do
1140
- p = @class.new(mock_db.call{123}, {})
1141
- p.send(:preconnect, true)
1142
- i = 0
1143
- p.all_connections{|c1| i+=1}
1144
- i.must_equal p.max_size
1145
- end
1146
-
1147
- it "should be able to modify after_connect proc after the pool is created" do
1148
- a = []
1149
- p = @class.new(mock_db.call{123}, {})
1150
- p.after_connect = pr = proc{|c| a << c}
1151
- p.after_connect.must_equal pr
1152
- a.must_equal []
1153
- p.hold{}
1154
- a.must_equal [123]
1155
- end
1156
-
1157
- it "should not raise an error when disconnecting twice" do
1158
- c = @class.new(mock_db.call{123}, {})
1159
- c.disconnect
1160
- c.disconnect
1161
- end
1162
-
1163
- it "should yield a connection created by the initialize block to hold" do
1164
- x = nil
1165
- @class.new(mock_db.call{123}, {}).hold{|c| x = c}
1166
- x.must_equal 123
1167
- end
1168
-
1169
- it "should have the initialize block accept a shard/server argument" do
1170
- x = nil
1171
- @class.new(mock_db.call{|c| [c, c]}, {}).hold{|c| x = c}
1172
- x.must_equal [:default, :default]
1173
- end
1174
-
1175
- it "should have respect an :after_connect proc that is called with each newly created connection" do
1176
- x = nil
1177
- @class.new(mock_db.call{123}, :after_connect=>proc{|c| x = [c, c]}).hold{}
1178
- x.must_equal [123, 123]
1179
- @class.new(mock_db.call{123}, :after_connect=>lambda{|c| x = [c, c]}).hold{}
1180
- x.must_equal [123, 123]
1181
- @class.new(mock_db.call{123}, :after_connect=>proc{|c, s| x = [c, s]}).hold{}
1182
- x.must_equal [123, :default]
1183
- @class.new(mock_db.call{123}, :after_connect=>lambda{|c, s| x = [c, s]}).hold{}
1184
- x.must_equal [123, :default]
1185
- end
1186
-
1187
- it "should raise a DatabaseConnectionError if the connection raises an exception" do
1188
- proc{@class.new(mock_db.call{|c| raise Exception}, {}).hold{}}.must_raise(Sequel::DatabaseConnectionError)
1189
- end
1190
-
1191
- it "should raise a DatabaseConnectionError if the initialize block returns nil" do
1192
- proc{@class.new(mock_db.call{}, {}).hold{}}.must_raise(Sequel::DatabaseConnectionError)
1193
- end
1194
-
1195
- it "should call the disconnection_proc option if the hold block raises a DatabaseDisconnectError" do
1196
- x = nil
1197
- proc{@class.new(mock_db.call(proc{|c| x = c}){123}).hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
1198
- x.must_equal 123
1199
- end
1200
-
1201
- it "should have a disconnect method that disconnects the connection" do
1202
- x = nil
1203
- c = @class.new(mock_db.call(proc{|c1| x = c1}){123})
1204
- c.hold{}
1205
- x.must_be_nil
1206
- c.disconnect
1207
- x.must_equal 123
1208
- end
1209
-
1210
- it "should have a reentrent hold method" do
1211
- o = Object.new
1212
- c = @class.new(mock_db.call{o}, {})
1213
- c.hold do |x|
1214
- x.must_equal o
1215
- c.hold do |x1|
1216
- x1.must_equal o
1217
- c.hold do |x2|
1218
- x2.must_equal o
1219
- end
1220
- end
1221
- end
1222
- end
1223
-
1224
- it "should have a servers method that returns an array of shard/server symbols" do
1225
- @class.new(mock_db.call{123}, {}).servers.must_equal [:default]
1226
- end
1227
-
1228
- it "should have a servers method that returns an array of shard/server symbols" do
1229
- c = @class.new(mock_db.call{123}, {})
1230
- c.size.must_equal 0
1231
- c.hold{}
1232
- c.size.must_equal 1
1233
- end
1234
- end
1235
-
1236
- [true, false].each do |k|
1237
- [true, false].each do |v|
1238
- opts = {:single_threaded=>k, :servers=>(v ? {} : nil)}
1239
- describe "Connection pool with #{opts.inspect}" do
1240
- before(:all) do
1241
- Sequel::ConnectionPool.send(:get_pool, mock_db.call, opts)
1242
- end
1243
- before do
1244
- @class = Sequel::ConnectionPool.send(:connection_pool_class, opts)
1245
- end
1246
-
1247
- include AllConnectionPoolClassesSpecs
1248
- end
1249
- end
1250
- end