sequel 5.29.0 → 5.30.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 (323) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +8 -1922
  3. data/doc/release_notes/5.30.0.txt +20 -0
  4. data/lib/sequel/adapters/shared/sqlite.rb +7 -1
  5. data/lib/sequel/database/transactions.rb +5 -9
  6. data/lib/sequel/version.rb +1 -1
  7. metadata +4 -368
  8. data/Rakefile +0 -151
  9. data/doc/release_notes/4.0.0.txt +0 -262
  10. data/doc/release_notes/4.1.0.txt +0 -85
  11. data/doc/release_notes/4.10.0.txt +0 -226
  12. data/doc/release_notes/4.11.0.txt +0 -147
  13. data/doc/release_notes/4.12.0.txt +0 -105
  14. data/doc/release_notes/4.13.0.txt +0 -169
  15. data/doc/release_notes/4.14.0.txt +0 -68
  16. data/doc/release_notes/4.15.0.txt +0 -56
  17. data/doc/release_notes/4.16.0.txt +0 -36
  18. data/doc/release_notes/4.17.0.txt +0 -38
  19. data/doc/release_notes/4.18.0.txt +0 -36
  20. data/doc/release_notes/4.19.0.txt +0 -45
  21. data/doc/release_notes/4.2.0.txt +0 -129
  22. data/doc/release_notes/4.20.0.txt +0 -79
  23. data/doc/release_notes/4.21.0.txt +0 -94
  24. data/doc/release_notes/4.22.0.txt +0 -72
  25. data/doc/release_notes/4.23.0.txt +0 -65
  26. data/doc/release_notes/4.24.0.txt +0 -99
  27. data/doc/release_notes/4.25.0.txt +0 -181
  28. data/doc/release_notes/4.26.0.txt +0 -44
  29. data/doc/release_notes/4.27.0.txt +0 -78
  30. data/doc/release_notes/4.28.0.txt +0 -57
  31. data/doc/release_notes/4.29.0.txt +0 -41
  32. data/doc/release_notes/4.3.0.txt +0 -40
  33. data/doc/release_notes/4.30.0.txt +0 -37
  34. data/doc/release_notes/4.31.0.txt +0 -57
  35. data/doc/release_notes/4.32.0.txt +0 -132
  36. data/doc/release_notes/4.33.0.txt +0 -88
  37. data/doc/release_notes/4.34.0.txt +0 -86
  38. data/doc/release_notes/4.35.0.txt +0 -130
  39. data/doc/release_notes/4.36.0.txt +0 -116
  40. data/doc/release_notes/4.37.0.txt +0 -50
  41. data/doc/release_notes/4.38.0.txt +0 -67
  42. data/doc/release_notes/4.39.0.txt +0 -127
  43. data/doc/release_notes/4.4.0.txt +0 -92
  44. data/doc/release_notes/4.40.0.txt +0 -179
  45. data/doc/release_notes/4.41.0.txt +0 -77
  46. data/doc/release_notes/4.42.0.txt +0 -221
  47. data/doc/release_notes/4.43.0.txt +0 -87
  48. data/doc/release_notes/4.44.0.txt +0 -125
  49. data/doc/release_notes/4.45.0.txt +0 -370
  50. data/doc/release_notes/4.46.0.txt +0 -404
  51. data/doc/release_notes/4.47.0.txt +0 -56
  52. data/doc/release_notes/4.48.0.txt +0 -293
  53. data/doc/release_notes/4.49.0.txt +0 -222
  54. data/doc/release_notes/4.5.0.txt +0 -34
  55. data/doc/release_notes/4.6.0.txt +0 -30
  56. data/doc/release_notes/4.7.0.txt +0 -103
  57. data/doc/release_notes/4.8.0.txt +0 -175
  58. data/doc/release_notes/4.9.0.txt +0 -190
  59. data/spec/adapter_spec.rb +0 -4
  60. data/spec/adapters/db2_spec.rb +0 -170
  61. data/spec/adapters/mssql_spec.rb +0 -828
  62. data/spec/adapters/mysql_spec.rb +0 -1060
  63. data/spec/adapters/oracle_spec.rb +0 -371
  64. data/spec/adapters/postgres_spec.rb +0 -4476
  65. data/spec/adapters/spec_helper.rb +0 -44
  66. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  67. data/spec/adapters/sqlite_spec.rb +0 -652
  68. data/spec/bin_spec.rb +0 -278
  69. data/spec/core/connection_pool_spec.rb +0 -1250
  70. data/spec/core/database_spec.rb +0 -2915
  71. data/spec/core/dataset_spec.rb +0 -5544
  72. data/spec/core/deprecated_spec.rb +0 -70
  73. data/spec/core/expression_filters_spec.rb +0 -1498
  74. data/spec/core/mock_adapter_spec.rb +0 -722
  75. data/spec/core/object_graph_spec.rb +0 -336
  76. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  77. data/spec/core/schema_generator_spec.rb +0 -214
  78. data/spec/core/schema_spec.rb +0 -1844
  79. data/spec/core/spec_helper.rb +0 -24
  80. data/spec/core/version_spec.rb +0 -14
  81. data/spec/core_extensions_spec.rb +0 -763
  82. data/spec/core_model_spec.rb +0 -2
  83. data/spec/core_spec.rb +0 -1
  84. data/spec/deprecation_helper.rb +0 -30
  85. data/spec/extensions/accessed_columns_spec.rb +0 -51
  86. data/spec/extensions/active_model_spec.rb +0 -99
  87. data/spec/extensions/after_initialize_spec.rb +0 -28
  88. data/spec/extensions/any_not_empty_spec.rb +0 -23
  89. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  90. data/spec/extensions/association_dependencies_spec.rb +0 -125
  91. data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
  92. data/spec/extensions/association_pks_spec.rb +0 -423
  93. data/spec/extensions/association_proxies_spec.rb +0 -100
  94. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  95. data/spec/extensions/auto_validations_spec.rb +0 -229
  96. data/spec/extensions/blacklist_security_spec.rb +0 -95
  97. data/spec/extensions/blank_spec.rb +0 -69
  98. data/spec/extensions/boolean_readers_spec.rb +0 -93
  99. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  100. data/spec/extensions/caching_spec.rb +0 -273
  101. data/spec/extensions/caller_logging_spec.rb +0 -52
  102. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  103. data/spec/extensions/column_conflicts_spec.rb +0 -75
  104. data/spec/extensions/column_select_spec.rb +0 -129
  105. data/spec/extensions/columns_introspection_spec.rb +0 -90
  106. data/spec/extensions/columns_updated_spec.rb +0 -35
  107. data/spec/extensions/composition_spec.rb +0 -248
  108. data/spec/extensions/connection_expiration_spec.rb +0 -151
  109. data/spec/extensions/connection_validator_spec.rb +0 -144
  110. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  111. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  112. data/spec/extensions/constraint_validations_spec.rb +0 -439
  113. data/spec/extensions/core_refinements_spec.rb +0 -528
  114. data/spec/extensions/csv_serializer_spec.rb +0 -183
  115. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  116. data/spec/extensions/dataset_associations_spec.rb +0 -365
  117. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  118. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  119. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  120. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  121. data/spec/extensions/defaults_setter_spec.rb +0 -150
  122. data/spec/extensions/delay_add_association_spec.rb +0 -73
  123. data/spec/extensions/dirty_spec.rb +0 -222
  124. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  125. data/spec/extensions/eager_each_spec.rb +0 -62
  126. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  127. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  128. data/spec/extensions/empty_failure_backtraces_spec.rb +0 -60
  129. data/spec/extensions/error_splitter_spec.rb +0 -18
  130. data/spec/extensions/error_sql_spec.rb +0 -20
  131. data/spec/extensions/escaped_like_spec.rb +0 -40
  132. data/spec/extensions/eval_inspect_spec.rb +0 -81
  133. data/spec/extensions/exclude_or_null_spec.rb +0 -15
  134. data/spec/extensions/finder_spec.rb +0 -260
  135. data/spec/extensions/force_encoding_spec.rb +0 -126
  136. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  137. data/spec/extensions/graph_each_spec.rb +0 -113
  138. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  139. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  140. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  141. data/spec/extensions/index_caching_spec.rb +0 -66
  142. data/spec/extensions/inflector_spec.rb +0 -183
  143. data/spec/extensions/input_transformer_spec.rb +0 -69
  144. data/spec/extensions/insert_conflict_spec.rb +0 -103
  145. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  146. data/spec/extensions/instance_filters_spec.rb +0 -79
  147. data/spec/extensions/instance_hooks_spec.rb +0 -246
  148. data/spec/extensions/integer64_spec.rb +0 -22
  149. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  150. data/spec/extensions/json_serializer_spec.rb +0 -346
  151. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  152. data/spec/extensions/list_spec.rb +0 -291
  153. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  154. data/spec/extensions/many_through_many_spec.rb +0 -2177
  155. data/spec/extensions/migration_spec.rb +0 -864
  156. data/spec/extensions/modification_detection_spec.rb +0 -93
  157. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  158. data/spec/extensions/named_timezones_spec.rb +0 -218
  159. data/spec/extensions/nested_attributes_spec.rb +0 -815
  160. data/spec/extensions/null_dataset_spec.rb +0 -85
  161. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  162. data/spec/extensions/pagination_spec.rb +0 -116
  163. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  164. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  165. data/spec/extensions/pg_array_spec.rb +0 -398
  166. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
  167. data/spec/extensions/pg_enum_spec.rb +0 -118
  168. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  169. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  170. data/spec/extensions/pg_hstore_spec.rb +0 -219
  171. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  172. data/spec/extensions/pg_inet_spec.rb +0 -72
  173. data/spec/extensions/pg_interval_spec.rb +0 -103
  174. data/spec/extensions/pg_json_ops_spec.rb +0 -356
  175. data/spec/extensions/pg_json_spec.rb +0 -451
  176. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  177. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  178. data/spec/extensions/pg_range_spec.rb +0 -600
  179. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  180. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  181. data/spec/extensions/pg_row_spec.rb +0 -363
  182. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  183. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  184. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  185. data/spec/extensions/prepared_statements_spec.rb +0 -177
  186. data/spec/extensions/pretty_table_spec.rb +0 -123
  187. data/spec/extensions/query_spec.rb +0 -94
  188. data/spec/extensions/rcte_tree_spec.rb +0 -387
  189. data/spec/extensions/round_timestamps_spec.rb +0 -39
  190. data/spec/extensions/s_spec.rb +0 -60
  191. data/spec/extensions/schema_caching_spec.rb +0 -64
  192. data/spec/extensions/schema_dumper_spec.rb +0 -870
  193. data/spec/extensions/select_remove_spec.rb +0 -38
  194. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  195. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  196. data/spec/extensions/serialization_spec.rb +0 -365
  197. data/spec/extensions/server_block_spec.rb +0 -135
  198. data/spec/extensions/server_logging_spec.rb +0 -45
  199. data/spec/extensions/sharding_spec.rb +0 -197
  200. data/spec/extensions/shared_caching_spec.rb +0 -151
  201. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  202. data/spec/extensions/singular_table_names_spec.rb +0 -22
  203. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  204. data/spec/extensions/spec_helper.rb +0 -70
  205. data/spec/extensions/split_array_nil_spec.rb +0 -24
  206. data/spec/extensions/split_values_spec.rb +0 -57
  207. data/spec/extensions/sql_comments_spec.rb +0 -33
  208. data/spec/extensions/sql_expr_spec.rb +0 -59
  209. data/spec/extensions/static_cache_cache_spec.rb +0 -35
  210. data/spec/extensions/static_cache_spec.rb +0 -471
  211. data/spec/extensions/string_agg_spec.rb +0 -90
  212. data/spec/extensions/string_date_time_spec.rb +0 -95
  213. data/spec/extensions/string_stripper_spec.rb +0 -68
  214. data/spec/extensions/subclasses_spec.rb +0 -79
  215. data/spec/extensions/subset_conditions_spec.rb +0 -38
  216. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  217. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  218. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  219. data/spec/extensions/table_select_spec.rb +0 -83
  220. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  221. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  222. data/spec/extensions/throw_failures_spec.rb +0 -74
  223. data/spec/extensions/timestamps_spec.rb +0 -209
  224. data/spec/extensions/to_dot_spec.rb +0 -153
  225. data/spec/extensions/touch_spec.rb +0 -226
  226. data/spec/extensions/tree_spec.rb +0 -334
  227. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  228. data/spec/extensions/unlimited_update_spec.rb +0 -21
  229. data/spec/extensions/update_or_create_spec.rb +0 -83
  230. data/spec/extensions/update_primary_key_spec.rb +0 -105
  231. data/spec/extensions/update_refresh_spec.rb +0 -59
  232. data/spec/extensions/uuid_spec.rb +0 -101
  233. data/spec/extensions/validate_associated_spec.rb +0 -52
  234. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  235. data/spec/extensions/validation_contexts_spec.rb +0 -31
  236. data/spec/extensions/validation_helpers_spec.rb +0 -525
  237. data/spec/extensions/whitelist_security_spec.rb +0 -157
  238. data/spec/extensions/xml_serializer_spec.rb +0 -213
  239. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  240. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  241. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  242. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  243. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  244. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  245. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  246. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  247. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  248. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  249. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  250. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  251. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  252. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  253. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  254. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  255. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  256. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  257. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  258. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  259. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  260. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  261. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  262. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  263. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  264. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  265. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  266. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  267. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  268. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  269. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  270. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  271. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  272. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  273. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  274. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  275. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  276. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  277. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  278. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  279. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  280. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  281. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  282. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  283. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  284. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  285. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  286. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  287. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  288. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  289. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  290. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  291. data/spec/guards_helper.rb +0 -59
  292. data/spec/integration/associations_test.rb +0 -2597
  293. data/spec/integration/database_test.rb +0 -113
  294. data/spec/integration/dataset_test.rb +0 -2037
  295. data/spec/integration/eager_loader_test.rb +0 -687
  296. data/spec/integration/migrator_test.rb +0 -262
  297. data/spec/integration/model_test.rb +0 -203
  298. data/spec/integration/plugin_test.rb +0 -2423
  299. data/spec/integration/prepared_statement_test.rb +0 -405
  300. data/spec/integration/schema_test.rb +0 -903
  301. data/spec/integration/spec_helper.rb +0 -71
  302. data/spec/integration/timezone_test.rb +0 -86
  303. data/spec/integration/transaction_test.rb +0 -603
  304. data/spec/integration/type_test.rb +0 -127
  305. data/spec/model/association_reflection_spec.rb +0 -803
  306. data/spec/model/associations_spec.rb +0 -4738
  307. data/spec/model/base_spec.rb +0 -875
  308. data/spec/model/class_dataset_methods_spec.rb +0 -146
  309. data/spec/model/dataset_methods_spec.rb +0 -198
  310. data/spec/model/eager_loading_spec.rb +0 -2377
  311. data/spec/model/hooks_spec.rb +0 -370
  312. data/spec/model/inflector_spec.rb +0 -26
  313. data/spec/model/model_spec.rb +0 -956
  314. data/spec/model/plugins_spec.rb +0 -429
  315. data/spec/model/record_spec.rb +0 -2118
  316. data/spec/model/spec_helper.rb +0 -46
  317. data/spec/model/validations_spec.rb +0 -220
  318. data/spec/model_no_assoc_spec.rb +0 -1
  319. data/spec/model_spec.rb +0 -1
  320. data/spec/plugin_spec.rb +0 -1
  321. data/spec/sequel_coverage.rb +0 -15
  322. data/spec/sequel_warning.rb +0 -5
  323. data/spec/spec_config.rb +0 -12
@@ -1,278 +0,0 @@
1
- require 'rbconfig'
2
- require 'yaml'
3
-
4
- RUBY = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['RUBY_INSTALL_NAME'])
5
- OUTPUT = "spec/bin-sequel-spec-output-#{$$}.log"
6
- TMP_FILE = "spec/bin-sequel-tmp-#{$$}.rb"
7
- BIN_SPEC_DB = "spec/bin-sequel-spec-db-#{$$}.sqlite3"
8
- BIN_SPEC_DB2 = "spec/bin-sequel-spec-db2-#{$$}.sqlite3"
9
-
10
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
11
- CONN_PREFIX = 'jdbc:sqlite:'
12
- CONN_HASH = {:adapter=>'jdbc', :uri=>"#{CONN_PREFIX}#{BIN_SPEC_DB}"}
13
- else
14
- CONN_PREFIX = 'sqlite://'
15
- CONN_HASH = {:adapter=>'sqlite', :database=>BIN_SPEC_DB}
16
- end
17
-
18
- require_relative '../lib/sequel'
19
-
20
- Sequel::DB = nil
21
- File.delete(BIN_SPEC_DB) if File.file?(BIN_SPEC_DB)
22
- File.delete(BIN_SPEC_DB2) if File.file?(BIN_SPEC_DB2)
23
- DB = Sequel.connect("#{CONN_PREFIX}#{BIN_SPEC_DB}", :test=>false)
24
- DB2 = Sequel.connect("#{CONN_PREFIX}#{BIN_SPEC_DB2}", :test=>false)
25
-
26
- ENV['MT_NO_PLUGINS'] = '1' # Work around stupid autoloading of plugins
27
- gem 'minitest'
28
- require 'minitest/global_expectations/autorun'
29
-
30
- describe "bin/sequel" do
31
- def bin(opts={})
32
- cmd = "#{opts[:pre]}\"#{RUBY}\" -I lib bin/sequel #{opts[:args]} #{"#{CONN_PREFIX}#{BIN_SPEC_DB}" unless opts[:no_conn]} #{opts[:post]}> #{OUTPUT}#{" 2>&1" if opts[:stderr]}"
33
- system(cmd)
34
- File.read(OUTPUT)
35
- end
36
-
37
- after do
38
- DB.disconnect
39
- DB2.disconnect
40
- [BIN_SPEC_DB, BIN_SPEC_DB2, TMP_FILE, OUTPUT].each do |file|
41
- if File.file?(file)
42
- begin
43
- File.delete(file)
44
- rescue Errno::ENOENT
45
- nil
46
- end
47
- end
48
- end
49
- end
50
-
51
- it "-h should print the help" do
52
- help = bin(:args=>"-h", :no_conn=>true)
53
- help.must_match(/\ASequel: The Database Toolkit for Ruby/)
54
- help.must_match(/^Usage: sequel /)
55
- end
56
-
57
- it "-c should run code" do
58
- bin(:args=>'-c "print DB.tables.inspect"').must_equal '[]'
59
- DB.create_table(:a){Integer :a}
60
- bin(:args=>'-c "print DB.tables.inspect"').must_equal '[:a]'
61
- bin(:args=>'-v -c "print DB.tables.inspect"').strip.must_equal "sequel #{Sequel.version}\n[:a]"
62
- end
63
-
64
- it "-C should copy databases" do
65
- DB.create_table(:a) do
66
- primary_key :a
67
- String :name
68
- end
69
- DB.create_table(:b) do
70
- foreign_key :a, :a
71
- index :a
72
- end
73
- DB[:a].insert(1, 'foo')
74
- DB[:b].insert(1)
75
- bin(:args=>'-C', :post=>"#{CONN_PREFIX}#{BIN_SPEC_DB2}").must_match Regexp.new(<<END)
76
- Databases connections successful
77
- Migrations dumped successfully
78
- Tables created
79
- Begin copying data
80
- Begin copying records for table: a
81
- Finished copying 1 records for table: a
82
- Begin copying records for table: b
83
- Finished copying 1 records for table: b
84
- Finished copying data
85
- Begin creating indexes
86
- Finished creating indexes
87
- Begin adding foreign key constraints
88
- Finished adding foreign key constraints
89
- Database copy finished in \\d+\\.\\d+ seconds
90
- END
91
- DB2.tables.sort_by{|t| t.to_s}.must_equal [:a, :b]
92
- DB[:a].all.must_equal [{:a=>1, :name=>'foo'}]
93
- DB[:b].all.must_equal [{:a=>1}]
94
- DB2.schema(:a).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.must_equal [[:a, false, nil, true, "integer", :integer, nil], [:name, true, nil, false, "varchar(255)", :string, nil]]
95
- DB2.schema(:b).map{|col, sch| [col, *sch.values_at(:allow_null, :default, :primary_key, :db_type, :type, :ruby_default)]}.must_equal [[:a, true, nil, false, "integer", :integer, nil]]
96
- DB2.indexes(:a).must_equal({})
97
- DB2.indexes(:b).must_equal(:b_a_index=>{:unique=>false, :columns=>[:a]})
98
- DB2.foreign_key_list(:a).must_equal []
99
- DB2.foreign_key_list(:b).must_equal [{:columns=>[:a], :table=>:a, :key=>nil, :on_update=>:no_action, :on_delete=>:no_action}]
100
- end
101
-
102
- it "-C should convert integer to bigint when copying from SQLite to other databases" do
103
- DB.create_table(:a) do
104
- Integer :id
105
- end
106
- bin(:args=>'-EC', :post=>"mock://postgres").must_include 'CREATE TABLE "a" ("id" bigint)'
107
- end
108
-
109
- it "-d and -D should dump generic and specific migrations" do
110
- DB.create_table(:a) do
111
- primary_key :a
112
- String :name
113
- end
114
- DB.create_table(:b) do
115
- foreign_key :a, :a
116
- index :a
117
- end
118
- bin(:args=>'-d').must_equal <<END
119
- Sequel.migration do
120
- change do
121
- create_table(:a) do
122
- primary_key :a
123
- String :name, :size=>255
124
- end
125
-
126
- create_table(:b, :ignore_index_errors=>true) do
127
- foreign_key :a, :a
128
-
129
- index [:a]
130
- end
131
- end
132
- end
133
- END
134
- bin(:args=>'-D').must_equal <<END
135
- Sequel.migration do
136
- change do
137
- create_table(:a) do
138
- primary_key :a
139
- column :name, "varchar(255)"
140
- end
141
-
142
- create_table(:b) do
143
- foreign_key :a, :a
144
-
145
- index [:a]
146
- end
147
- end
148
- end
149
- END
150
- end
151
-
152
- it "-E should echo SQL statements to stdout" do
153
- bin(:args=>'-E -c DB.tables').must_include "SELECT * FROM `sqlite_master` WHERE ((`name` != 'sqlite_sequence') AND (`type` = 'table'))"
154
- end
155
-
156
- it "-I should include directory in load path" do
157
- bin(:args=>'-Ifoo -c "p 1 if $:.include?(\'foo\')"').must_equal "1\n"
158
- end
159
-
160
- it "-l should log SQL statements to file" do
161
- bin(:args=>"-l #{TMP_FILE} -c DB.tables").must_equal ''
162
- File.read(TMP_FILE).must_include "SELECT * FROM `sqlite_master` WHERE ((`name` != 'sqlite_sequence') AND (`type` = 'table'))"
163
- end
164
-
165
- it "-L should load all *.rb files in given directory" do
166
- bin(:args=>'-r ./lib/sequel/extensions/migration -L ./spec/files/integer_migrations -c "p Sequel::Migration.descendants.length"').must_equal "3\n"
167
- end
168
-
169
- it "-m should migrate database up" do
170
- bin(:args=>"-m spec/files/integer_migrations").must_equal ''
171
- DB.tables.sort_by{|t| t.to_s}.must_equal [:schema_info, :sm1111, :sm2222, :sm3333]
172
- end
173
-
174
- it "-M should specify version to migrate to" do
175
- bin(:args=>"-m spec/files/integer_migrations -M 2").must_equal ''
176
- DB.tables.sort_by{|t| t.to_s}.must_equal [:schema_info, :sm1111, :sm2222]
177
- end
178
-
179
- it "-N should not test for a valid connection" do
180
- bin(:no_conn=>true, :args=>"-c '' -N #{CONN_PREFIX}spec/nonexistent/foo").must_equal ''
181
- bin(:no_conn=>true, :args=>"-c '' #{CONN_PREFIX}spec/nonexistent/foo", :stderr=>true).must_match(/\AError: Sequel::DatabaseConnectionError: /)
182
- end
183
-
184
- it "-r should require a given library" do
185
- bin(:args=>'-rsequel/extensions/sql_expr -c "print DB.literal(1.sql_expr)"').must_equal "1"
186
- end
187
-
188
- it "-S should dump the schema cache" do
189
- bin(:args=>"-S #{TMP_FILE}").must_equal ''
190
- Marshal.load(File.read(TMP_FILE)).must_equal({})
191
- DB.create_table(:a){Integer :a}
192
- bin(:args=>"-S #{TMP_FILE}").must_equal ''
193
- Marshal.load(File.read(TMP_FILE)).must_equal("`a`"=>[[:a, {:type=>:integer, :db_type=>"integer", :ruby_default=>nil, :allow_null=>true, :default=>nil, :primary_key=>false}]])
194
- end
195
-
196
- it "-X should dump the index cache" do
197
- bin(:args=>"-X #{TMP_FILE}").must_equal ''
198
- Marshal.load(File.read(TMP_FILE)).must_equal({})
199
- DB.create_table(:a){Integer :id}
200
- DB.create_table(:b){Integer :b, index: {name: "idx_test", unique: true}}
201
- bin(:args=>"-X #{TMP_FILE}").must_equal ''
202
- Marshal.load(File.read(TMP_FILE)).must_equal("`a`"=>{}, "`b`"=>{:idx_test=>{:unique=>true, :columns=>[:b]}})
203
- end
204
-
205
- it "-t should output full backtraces on error" do
206
- bin(:args=>'-c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").must_be :<, 3
207
- bin(:args=>'-t -c "lambda{lambda{lambda{raise \'foo\'}.call}.call}.call"', :stderr=>true).count("\n").must_be :>, 3
208
- end
209
-
210
- it "-v should output the Sequel version and exit if database is not given" do
211
- bin(:args=>"-v", :no_conn=>true).strip.must_equal "sequel #{Sequel.version}"
212
- end
213
-
214
- it "should error if using -M without -m" do
215
- bin(:args=>'-M 2', :stderr=>true).must_equal "Error: Must specify -m if using -M\n"
216
- end
217
-
218
- it "should error if using mutually exclusive options together" do
219
- bin(:args=>'-c foo -d', :stderr=>true).must_equal "Error: Cannot specify -c and -d together\n"
220
- bin(:args=>'-D -d', :stderr=>true).must_equal "Error: Cannot specify -D and -d together\n"
221
- bin(:args=>'-m foo -d', :stderr=>true).must_equal "Error: Cannot specify -m and -d together\n"
222
- bin(:args=>'-S foo -d', :stderr=>true).must_equal "Error: Cannot specify -S and -d together\n"
223
- bin(:args=>'-S foo -C', :stderr=>true).must_equal "Error: Cannot specify -S and -C together\n"
224
- end
225
-
226
- it "should warn if providing too many arguments" do
227
- bin(:args=>'-c "" "" 1 2 3 4', :stderr=>true).must_equal "Warning: last 5 arguments ignored\n"
228
- end
229
-
230
- it "should use a mock database if no database is given" do
231
- bin(:args=>'-c "print DB.adapter_scheme"', :no_conn=>true).must_equal "mock"
232
- end
233
-
234
- it "should work with a yaml config file" do
235
- File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(CONN_HASH))}
236
- bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[]"
237
- DB.create_table(:a){Integer :a}
238
- bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
239
- end
240
-
241
- it "should work with a yaml config file with string keys" do
242
- h = {}
243
- CONN_HASH.each{|k,v| h[k.to_s] = v}
244
- File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(h))}
245
- DB.create_table(:a){Integer :a}
246
- bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
247
- end
248
-
249
- it "should work with a yaml config file with environments" do
250
- File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(:development=>CONN_HASH))}
251
- bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[]"
252
- DB.create_table(:a){Integer :a}
253
- bin(:args=>"-c \"print DB.tables.inspect\" #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
254
- end
255
-
256
- it "-e should set environment for yaml config file" do
257
- File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump(:foo=>CONN_HASH))}
258
- bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[]"
259
- DB.create_table(:a){Integer :a}
260
- bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
261
- File.open(TMP_FILE, 'wb'){|f| f.write(YAML.dump('foo'=>CONN_HASH))}
262
- bin(:args=>"-c \"print DB.tables.inspect\" -e foo #{TMP_FILE}", :no_conn=>true).must_equal "[:a]"
263
- end
264
-
265
- it "should run code in given filenames" do
266
- File.open(TMP_FILE, 'wb'){|f| f.write('print DB.tables.inspect')}
267
- bin(:post=>TMP_FILE).must_equal '[]'
268
- DB.create_table(:a){Integer :a}
269
- bin(:post=>TMP_FILE).must_equal '[:a]'
270
- bin(:post=>TMP_FILE, :args=>'-v').strip.must_equal "sequel #{Sequel.version}\n[:a]"
271
- end
272
-
273
- it "should run code provided on stdin" do
274
- bin(:pre=>'echo print DB.tables.inspect | ').must_equal '[]'
275
- DB.create_table(:a){Integer :a}
276
- bin(:pre=>'echo print DB.tables.inspect | ').must_equal '[:a]'
277
- end
278
- end
@@ -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