sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -45,6 +45,23 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
45
45
  @allocated[server]
46
46
  end
47
47
 
48
+ # Yield all of the available connections, and the ones currently allocated to
49
+ # this thread. This will not yield connections currently allocated to other
50
+ # threads, as it is not safe to operate on them. This holds the mutex while
51
+ # it is yielding all of the connections, which means that until
52
+ # the method's block returns, the pool is locked.
53
+ def all_connections
54
+ t = Thread.current
55
+ sync do
56
+ @allocated.values.each do |threads|
57
+ threads.each do |thread, conn|
58
+ yield conn if t == thread
59
+ end
60
+ end
61
+ @available_connections.values.each{|v| v.each{|c| yield c}}
62
+ end
63
+ end
64
+
48
65
  # An array of connections opened but not currently used, for the given
49
66
  # server. Nonexistent servers will return nil. Treat this as read only, do
50
67
  # not modify the resulting object.
@@ -94,7 +111,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
94
111
  # connection can be acquired, a Sequel::PoolTimeout is
95
112
  # raised.
96
113
  def hold(server=:default)
97
- sync{server = @servers[server]}
114
+ server = pick_server(server)
98
115
  t = Thread.current
99
116
  if conn = owned_connection(t, server)
100
117
  return yield(conn)
@@ -190,6 +207,11 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
190
207
  def owned_connection(thread, server)
191
208
  sync{@allocated[server][thread]}
192
209
  end
210
+
211
+ # If the server given is in the hash, return it, otherwise, return the default server.
212
+ def pick_server(server)
213
+ sync{@servers[server]}
214
+ end
193
215
 
194
216
  # Releases the connection assigned to the supplied thread and server. If the
195
217
  # server or connection given is scheduled for disconnection, remove the
@@ -199,7 +221,16 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
199
221
  if @connections_to_remove.include?(conn)
200
222
  remove(thread, conn, server)
201
223
  else
202
- available_connections(server) << allocated(server).delete(thread)
224
+ conn = allocated(server).delete(thread)
225
+
226
+ case @connection_handling
227
+ when :queue
228
+ available_connections(server).unshift(conn)
229
+ when :disconnect
230
+ @disconnection_proc.call(conn) if @disconnection_proc
231
+ else
232
+ available_connections(server) << conn
233
+ end
203
234
  end
204
235
  end
205
236
 
@@ -8,6 +8,11 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
8
8
  @conn ? 1 : 0
9
9
  end
10
10
 
11
+ # Yield the connection if one has been made.
12
+ def all_connections
13
+ yield @conn if @conn
14
+ end
15
+
11
16
  # Disconnect the connection from the database.
12
17
  def disconnect(opts=nil, &block)
13
18
  return unless @conn
@@ -13,6 +13,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
13
13
  attr_reader :allocated
14
14
 
15
15
  # The following additional options are respected:
16
+ # * :connection_handling - Set how to handle available connections. By default,
17
+ # uses a a stack for performance. Can be set to :queue to use a queue, which reduces
18
+ # the chances of connections becoming stale.
16
19
  # * :max_connections - The maximum number of connections the connection pool
17
20
  # will open (default 4)
18
21
  # * :pool_sleep_time - The amount of time to sleep before attempting to acquire
@@ -24,22 +27,40 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
24
27
  @max_size = Integer(opts[:max_connections] || 4)
25
28
  raise(Sequel::Error, ':max_connections must be positive') if @max_size < 1
26
29
  @mutex = Mutex.new
30
+ @connection_handling = opts[:connection_handling]
27
31
  @available_connections = []
28
32
  @allocated = {}
29
33
  @timeout = Integer(opts[:pool_timeout] || 5)
30
34
  @sleep_time = Float(opts[:pool_sleep_time] || 0.001)
31
35
  end
32
36
 
33
- # The total number of connections opened for the given server, should
34
- # be equal to available_connections.length + allocated.length.
37
+ # The total number of connections opened, either available or allocated.
38
+ # This may not be completely accurate as it isn't protected by the mutex.
35
39
  def size
36
40
  @allocated.length + @available_connections.length
37
41
  end
38
42
 
39
- # Removes all connections currently available on all servers, optionally
43
+ # Yield all of the available connections, and the one currently allocated to
44
+ # this thread. This will not yield connections currently allocated to other
45
+ # threads, as it is not safe to operate on them. This holds the mutex while
46
+ # it is yielding all of the available connections, which means that until
47
+ # the method's block returns, the pool is locked.
48
+ def all_connections
49
+ hold do |c|
50
+ sync do
51
+ yield c
52
+ @available_connections.each{|c| yield c}
53
+ end
54
+ end
55
+ end
56
+
57
+ # Removes all connections currently available, optionally
40
58
  # yielding each connection to the given block. This method has the effect of
41
59
  # disconnecting from the database, assuming that no connections are currently
42
- # being used.
60
+ # being used. If you want to be able to disconnect connections that are
61
+ # currently in use, use the ShardedThreadedConnectionPool, which can do that.
62
+ # This connection pool does not, for performance reasons. To use the sharded pool,
63
+ # pass the <tt>:servers=>{}</tt> option when connecting to the database.
43
64
  #
44
65
  # Once a connection is requested using #hold, the connection pool
45
66
  # creates new connections to the database.
@@ -51,7 +72,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
51
72
  end
52
73
  end
53
74
 
54
- # Chooses the first available connection to the given server, or if none are
75
+ # Chooses the first available connection, or if none are
55
76
  # available, creates a new connection. Passes the connection to the supplied
56
77
  # block:
57
78
  #
@@ -83,9 +104,10 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
83
104
  end
84
105
  yield conn
85
106
  rescue Sequel::DatabaseDisconnectError
86
- @disconnection_proc.call(conn) if @disconnection_proc && conn
87
- @allocated.delete(t)
107
+ oconn = conn
88
108
  conn = nil
109
+ @disconnection_proc.call(oconn) if @disconnection_proc && oconn
110
+ @allocated.delete(t)
89
111
  raise
90
112
  ensure
91
113
  sync{release(t)} if conn
@@ -94,7 +116,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
94
116
 
95
117
  private
96
118
 
97
- # Assigns a connection to the supplied thread for the given server, if one
119
+ # Assigns a connection to the supplied thread, if one
98
120
  # is available. The calling code should NOT already have the mutex when
99
121
  # calling this.
100
122
  def acquire(thread)
@@ -105,7 +127,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
105
127
  end
106
128
  end
107
129
 
108
- # Returns an available connection to the given server. If no connection is
130
+ # Returns an available connection. If no connection is
109
131
  # available, tries to create a new connection. The calling code should already
110
132
  # have the mutex before calling this.
111
133
  def available
@@ -126,18 +148,25 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
126
148
  super if (n || size) < @max_size
127
149
  end
128
150
 
129
- # Returns the connection owned by the supplied thread for the given server,
151
+ # Returns the connection owned by the supplied thread,
130
152
  # if any. The calling code should NOT already have the mutex before calling this.
131
153
  def owned_connection(thread)
132
154
  sync{@allocated[thread]}
133
155
  end
134
156
 
135
- # Releases the connection assigned to the supplied thread and server. If the
136
- # server or connection given is scheduled for disconnection, remove the
137
- # connection instead of releasing it back to the pool.
157
+ # Releases the connection assigned to the supplied thread back to the pool.
138
158
  # The calling code should already have the mutex before calling this.
139
159
  def release(thread)
140
- @available_connections << @allocated.delete(thread)
160
+ conn = @allocated.delete(thread)
161
+
162
+ case @connection_handling
163
+ when :queue
164
+ @available_connections.unshift(conn)
165
+ when :disconnect
166
+ @disconnection_proc.call(conn) if @disconnection_proc
167
+ else
168
+ @available_connections << conn
169
+ end
141
170
  end
142
171
 
143
172
  # Yield to the block while inside the mutex. The calling code should NOT
@@ -53,10 +53,18 @@ class Sequel::ConnectionPool
53
53
 
54
54
  # Return a connection pool class based on the given options.
55
55
  def connection_pool_class(opts)
56
- opts[:pool_class] || CONNECTION_POOL_MAP[[!!opts[:single_threaded], !!opts[:servers]]]
56
+ CONNECTION_POOL_MAP[opts[:pool_class]] || opts[:pool_class] || CONNECTION_POOL_MAP[[!!opts[:single_threaded], !!opts[:servers]]]
57
57
  end
58
58
  end
59
59
  extend ClassMethods
60
+
61
+ # The after_connect proc used for this pool. This is called with each new
62
+ # connection made, and is usually used to set custom per-connection settings.
63
+ attr_accessor :after_connect
64
+
65
+ # The disconnect_proc used for the pool. This is called with each connection
66
+ # that is disconnected, usually to clean up related resources.
67
+ attr_accessor :disconnection_proc
60
68
 
61
69
  # Instantiates a connection pool with the given options. The block is called
62
70
  # with a single symbol (specifying the server/shard to use) every time a new
@@ -80,7 +88,7 @@ class Sequel::ConnectionPool
80
88
 
81
89
  # An array of symbols for all shards/servers, which is a single <tt>:default</tt> by default.
82
90
  def servers
83
- [:default]
91
+ [DEFAULT_SERVER]
84
92
  end
85
93
 
86
94
  private
data/lib/sequel/core.rb CHANGED
@@ -17,20 +17,26 @@
17
17
  #
18
18
  # Sequel.sqlite('blog.db'){|db| puts db[:users].count}
19
19
  #
20
- # You can set the +SEQUEL_NO_CORE_EXTENSIONS+ constant or environment variable to have
21
- # Sequel not extend the core classes.
20
+ # Sequel currently adds methods to the Array, Hash, String and Symbol classes by
21
+ # default. You can either require 'sequel/no_core_ext' or set the
22
+ # +SEQUEL_NO_CORE_EXTENSIONS+ constant or environment variable before requiring
23
+ # sequel to have # Sequel not add methods to those classes.
22
24
  #
23
25
  # For a more expanded introduction, see the {README}[link:files/README_rdoc.html].
24
26
  # For a quicker introduction, see the {cheat sheet}[link:files/doc/cheat_sheet_rdoc.html].
25
27
  module Sequel
26
28
  @convert_two_digit_years = true
27
29
  @datetime_class = Time
30
+ @empty_array_handle_nulls = true
28
31
  @virtual_row_instance_eval = true
29
32
  @require_thread = nil
30
33
 
31
34
  # Mutex used to protect file loading/requireing
32
35
  @require_mutex = Mutex.new
33
36
 
37
+ # Whether Sequel is being run in single threaded mode
38
+ @single_threaded = false
39
+
34
40
  class << self
35
41
  # Sequel converts two digit years in <tt>Date</tt>s and <tt>DateTime</tt>s by default,
36
42
  # so 01/02/03 is interpreted at January 2nd, 2003, and 12/13/99 is interpreted
@@ -54,6 +60,27 @@ module Sequel
54
60
  # days on +DateTime+).
55
61
  attr_accessor :datetime_class
56
62
 
63
+ # Sets whether or not to attempt to handle NULL values correctly when given
64
+ # an empty array. By default:
65
+ #
66
+ # DB[:a].filter(:b=>[])
67
+ # # SELECT * FROM a WHERE (b != b)
68
+ # DB[:a].exclude(:b=>[])
69
+ # # SELECT * FROM a WHERE (b = b)
70
+ #
71
+ # However, some databases (e.g. MySQL) will perform very poorly
72
+ # with this type of query. You can set this to false to get the
73
+ # following behavior:
74
+ #
75
+ # DB[:a].filter(:b=>[])
76
+ # # SELECT * FROM a WHERE 1 = 0
77
+ # DB[:a].exclude(:b=>[])
78
+ # # SELECT * FROM a WHERE 1 = 1
79
+ #
80
+ # This may not handle NULLs correctly, but can be much faster on
81
+ # some databases.
82
+ attr_accessor :empty_array_handle_nulls
83
+
57
84
  # For backwards compatibility, has no effect.
58
85
  attr_accessor :virtual_row_instance_eval
59
86
 
@@ -64,6 +91,7 @@ module Sequel
64
91
 
65
92
  # Make thread safe requiring reentrant to prevent deadlocks.
66
93
  def check_requiring_thread
94
+ return yield if @single_threaded
67
95
  t = Thread.current
68
96
  return(yield) if @require_thread == t
69
97
  @require_mutex.synchronize do
@@ -118,6 +146,12 @@ module Sequel
118
146
  def self.connect(*args, &block)
119
147
  Database.connect(*args, &block)
120
148
  end
149
+
150
+ # Assume the core extensions are not loaded by default, if the core_extensions
151
+ # extension is loaded, this will be overridden.
152
+ def self.core_extensions?
153
+ false
154
+ end
121
155
 
122
156
  # Convert the +exception+ to the given class. The given class should be
123
157
  # <tt>Sequel::Error</tt> or a subclass. Returns an instance of +klass+ with
@@ -182,25 +216,62 @@ module Sequel
182
216
  def self.quote_identifiers=(value)
183
217
  Database.quote_identifiers = value
184
218
  end
219
+
220
+ # Convert each item in the array to the correct type, handling multi-dimensional
221
+ # arrays. For each element in the array or subarrays, call the converter,
222
+ # unless the value is nil.
223
+ def self.recursive_map(array, converter)
224
+ array.map do |i|
225
+ if i.is_a?(Array)
226
+ recursive_map(i, converter)
227
+ elsif i
228
+ converter.call(i)
229
+ end
230
+ end
231
+ end
185
232
 
186
233
  # Require all given +files+ which should be in the same or a subdirectory of
187
234
  # this file. If a +subdir+ is given, assume all +files+ are in that subdir.
188
235
  # This is used to ensure that the files loaded are from the same version of
189
236
  # Sequel as this file.
190
237
  def self.require(files, subdir=nil)
191
- Array(files).each{|f| super("#{File.dirname(__FILE__)}/#{"#{subdir}/" if subdir}#{f}")}
238
+ Array(files).each{|f| super("#{File.dirname(__FILE__).untaint}/#{"#{subdir}/" if subdir}#{f}")}
192
239
  end
193
240
 
194
- # Set whether to set the single threaded mode for all databases by default. By default,
241
+ # Set whether Sequel is being used in single threaded mode. By default,
195
242
  # Sequel uses a thread-safe connection pool, which isn't as fast as the
196
- # single threaded connection pool. If your program will only have one thread,
197
- # and speed is a priority, you may want to set this to true:
243
+ # single threaded connection pool, and also has some additional thread
244
+ # safety checks. If your program will only have one thread,
245
+ # and speed is a priority, you should set this to true:
198
246
  #
199
247
  # Sequel.single_threaded = true
200
248
  def self.single_threaded=(value)
249
+ @single_threaded = value
201
250
  Database.single_threaded = value
202
251
  end
203
252
 
253
+ COLUMN_REF_RE1 = /\A((?:(?!__).)+)__((?:(?!___).)+)___(.+)\z/.freeze
254
+ COLUMN_REF_RE2 = /\A((?:(?!___).)+)___(.+)\z/.freeze
255
+ COLUMN_REF_RE3 = /\A((?:(?!__).)+)__(.+)\z/.freeze
256
+
257
+ # Splits the symbol into three parts. Each part will
258
+ # either be a string or nil.
259
+ #
260
+ # For columns, these parts are the table, column, and alias.
261
+ # For tables, these parts are the schema, table, and alias.
262
+ def self.split_symbol(sym)
263
+ case s = sym.to_s
264
+ when COLUMN_REF_RE1
265
+ [$1, $2, $3]
266
+ when COLUMN_REF_RE2
267
+ [nil, $1, $2]
268
+ when COLUMN_REF_RE3
269
+ [$1, $2, nil]
270
+ else
271
+ [nil, s, nil]
272
+ end
273
+ end
274
+
204
275
  # Converts the given +string+ into a +Date+ object.
205
276
  #
206
277
  # Sequel.string_to_date('2010-09-10') # Date.civil(2010, 09, 10)
@@ -228,17 +299,76 @@ module Sequel
228
299
  end
229
300
  end
230
301
 
231
- # Converts the given +string+ into a +Time+ object.
302
+ # Converts the given +string+ into a <tt>Sequel::SQLTime</tt> object.
232
303
  #
233
- # Sequel.string_to_datetime('10:20:30') # Time.parse('10:20:30')
304
+ # v = Sequel.string_to_time('10:20:30') # Sequel::SQLTime.parse('10:20:30')
305
+ # DB.literal(v) # => '10:20:30'
234
306
  def self.string_to_time(string)
235
307
  begin
236
- Time.parse(string)
308
+ SQLTime.parse(string)
237
309
  rescue => e
238
310
  raise convert_exception_class(e, InvalidValue)
239
311
  end
240
312
  end
241
313
 
314
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE != 'ruby'
315
+ # Mutex used to protect mutable data structures
316
+ @data_mutex = Mutex.new
317
+
318
+ # Unless in single threaded mode, protects access to any mutable
319
+ # global data structure in Sequel.
320
+ # Uses a non-reentrant mutex, so calling code should be careful.
321
+ def self.synchronize(&block)
322
+ @single_threaded ? yield : @data_mutex.synchronize(&block)
323
+ end
324
+ else
325
+ # Yield directly to the block. You don't need to synchronize
326
+ # access on MRI because the GVL makes certain methods atomic.
327
+ def self.synchronize(&block)
328
+ yield
329
+ end
330
+ end
331
+
332
+ # Uses a transaction on all given databases with the given options. This:
333
+ #
334
+ # Sequel.transaction([DB1, DB2, DB3]){...}
335
+ #
336
+ # is equivalent to:
337
+ #
338
+ # DB1.transaction do
339
+ # DB2.transaction do
340
+ # DB3.transaction do
341
+ # ...
342
+ # end
343
+ # end
344
+ # end
345
+ #
346
+ # except that if Sequel::Rollback is raised by the block, the transaction is
347
+ # rolled back on all databases instead of just the last one.
348
+ #
349
+ # Note that this method cannot guarantee that all databases will commit or
350
+ # rollback. For example, if DB3 commits but attempting to commit on DB2
351
+ # fails (maybe because foreign key checks are deferred), there is no way
352
+ # to uncommit the changes on DB3. For that kind of support, you need to
353
+ # have two-phase commit/prepared transactions (which Sequel supports on
354
+ # some databases).
355
+ def self.transaction(dbs, opts={}, &block)
356
+ unless opts[:rollback]
357
+ rescue_rollback = true
358
+ opts = opts.merge(:rollback=>:reraise)
359
+ end
360
+ pr = dbs.reverse.inject(block){|bl, db| proc{db.transaction(opts, &bl)}}
361
+ if rescue_rollback
362
+ begin
363
+ pr.call
364
+ rescue Sequel::Rollback => e
365
+ nil
366
+ end
367
+ else
368
+ pr.call
369
+ end
370
+ end
371
+
242
372
  # Same as Sequel.require, but wrapped in a mutex in order to be thread safe.
243
373
  def self.ts_require(*args)
244
374
  check_requiring_thread{require(*args)}
@@ -292,8 +422,10 @@ module Sequel
292
422
 
293
423
  private_class_method :adapter_method, :def_adapter_method
294
424
 
295
- require(%w"metaprogramming sql connection_pool exceptions dataset database timezones version")
296
- require('core_sql') if !defined?(::SEQUEL_NO_CORE_EXTENSIONS) && !ENV.has_key?('SEQUEL_NO_CORE_EXTENSIONS')
425
+ require(%w"metaprogramming sql connection_pool exceptions dataset database timezones ast_transformer version")
426
+ if !defined?(::SEQUEL_NO_CORE_EXTENSIONS) && !ENV.has_key?('SEQUEL_NO_CORE_EXTENSIONS')
427
+ extension(:core_extensions)
428
+ end
297
429
 
298
430
  # Add the database adapter class methods to Sequel via metaprogramming
299
431
  def_adapter_method(*Database::ADAPTERS)
@@ -1,12 +1,12 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods relating to adapters, connecting, disconnecting, and sharding
4
+ # :section: 4 - Methods relating to adapters, connecting, disconnecting, and sharding
5
5
  # This methods involve the Database's connection pool.
6
6
  # ---------------------
7
7
 
8
8
  # Array of supported database adapters
9
- ADAPTERS = %w'ado amalgalite db2 dbi do firebird informix jdbc mysql mysql2 odbc openbase oracle postgres sqlite swift tinytds'.collect{|x| x.to_sym}
9
+ ADAPTERS = %w'ado amalgalite db2 dbi do firebird ibmdb informix jdbc mock mysql mysql2 odbc openbase oracle postgres sqlite swift tinytds'.collect{|x| x.to_sym}
10
10
 
11
11
  # Whether to use the single threaded connection pool by default
12
12
  @@single_threaded = false
@@ -46,6 +46,7 @@ module Sequel
46
46
  when String
47
47
  if match = /\A(jdbc|do):/o.match(conn_string)
48
48
  c = adapter_class(match[1].to_sym)
49
+ opts = opts.merge(:orig_opts=>opts.dup)
49
50
  opts = {:uri=>conn_string}.merge(opts)
50
51
  else
51
52
  uri = URI.parse(conn_string)
@@ -54,12 +55,15 @@ module Sequel
54
55
  c = adapter_class(scheme)
55
56
  uri_options = c.send(:uri_to_options, uri)
56
57
  uri.query.split('&').collect{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
57
- uri_options.entries.each{|k,v| uri_options[k] = URI.unescape(v) if v.is_a?(String)}
58
+ uri_options.to_a.each{|k,v| uri_options[k] = URI.unescape(v) if v.is_a?(String)}
59
+ opts = opts.merge(:orig_opts=>opts.dup)
60
+ opts[:uri] = conn_string
58
61
  opts = uri_options.merge(opts)
59
62
  opts[:adapter] = scheme
60
63
  end
61
64
  when Hash
62
65
  opts = conn_string.merge(opts)
66
+ opts = opts.merge(:orig_opts=>opts.dup)
63
67
  c = adapter_class(opts[:adapter_class] || opts[:adapter] || opts['adapter'])
64
68
  else
65
69
  raise Error, "Sequel::Database.connect takes either a Hash or a String, given: #{conn_string.inspect}"
@@ -77,7 +81,7 @@ module Sequel
77
81
  ensure
78
82
  if block_given?
79
83
  db.disconnect if db
80
- ::Sequel::DATABASES.delete(db)
84
+ Sequel.synchronize{::Sequel::DATABASES.delete(db)}
81
85
  end
82
86
  end
83
87
  block_given? ? result : db
@@ -131,8 +135,10 @@ module Sequel
131
135
  #
132
136
  # DB.add_servers(:f=>{:host=>"hash_host_f"})
133
137
  def add_servers(servers)
134
- @opts[:servers] = @opts[:servers] ? @opts[:servers].merge(servers) : servers
135
- @pool.add_servers(servers.keys)
138
+ if h = @opts[:servers]
139
+ Sequel.synchronize{h.merge!(servers)}
140
+ @pool.add_servers(servers.keys)
141
+ end
136
142
  end
137
143
 
138
144
  # Connects to the database. This method should be overridden by descendants.
@@ -155,8 +161,8 @@ module Sequel
155
161
 
156
162
  # Disconnects all available connections from the connection pool. Any
157
163
  # connections currently in use will not be disconnected. Options:
158
- # * :servers - Should be a symbol specifing the server to disconnect from,
159
- # or an array of symbols to specify multiple servers.
164
+ # :servers :: Should be a symbol specifing the server to disconnect from,
165
+ # or an array of symbols to specify multiple servers.
160
166
  #
161
167
  # Example:
162
168
  #
@@ -187,11 +193,8 @@ module Sequel
187
193
  #
188
194
  # DB.remove_servers(:f1, :f2)
189
195
  def remove_servers(*servers)
190
- if @opts[:servers] && !@opts[:servers].empty?
191
- servs = @opts[:servers].dup
192
- servers.flatten!
193
- servers.each{|s| servs.delete(s)}
194
- @opts[:servers] = servs
196
+ if h = @opts[:servers]
197
+ servers.flatten.each{|s| Sequel.synchronize{h.delete(s)}}
195
198
  @pool.remove_servers(servers)
196
199
  end
197
200
  end
@@ -209,21 +212,26 @@ module Sequel
209
212
  @single_threaded
210
213
  end
211
214
 
212
- # Acquires a database connection, yielding it to the passed block. This is
213
- # useful if you want to make sure the same connection is used for all
214
- # database queries in the block. It is also useful if you want to gain
215
- # direct access to the underlying connection object if you need to do
216
- # something Sequel does not natively support.
217
- #
218
- # If a server option is given, acquires a connection for that specific
219
- # server, instead of the :default server.
220
- #
221
- #
222
- # DB.synchronize do |conn|
223
- # ...
224
- # end
225
- def synchronize(server=nil, &block)
226
- @pool.hold(server || :default, &block)
215
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby'
216
+ # Acquires a database connection, yielding it to the passed block. This is
217
+ # useful if you want to make sure the same connection is used for all
218
+ # database queries in the block. It is also useful if you want to gain
219
+ # direct access to the underlying connection object if you need to do
220
+ # something Sequel does not natively support.
221
+ #
222
+ # If a server option is given, acquires a connection for that specific
223
+ # server, instead of the :default server.
224
+ #
225
+ # DB.synchronize do |conn|
226
+ # ...
227
+ # end
228
+ def synchronize(server=nil)
229
+ @pool.hold(server || :default){|conn| yield conn}
230
+ end
231
+ else
232
+ def synchronize(server=nil, &block)
233
+ @pool.hold(server || :default, &block)
234
+ end
227
235
  end
228
236
 
229
237
  # Attempts to acquire a database connection. Returns true if successful.
@@ -255,6 +263,8 @@ module Sequel
255
263
  else
256
264
  raise Error, 'Server opts should be a hash or proc'
257
265
  end
266
+ elsif server.is_a?(Hash)
267
+ @opts.merge(server)
258
268
  else
259
269
  @opts.dup
260
270
  end
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods that create datasets
4
+ # :section: 3 - Methods that create datasets
5
5
  # These methods all return instances of this database's dataset class.
6
6
  # ---------------------
7
7
 
@@ -24,10 +24,10 @@ module Sequel
24
24
  #
25
25
  # DB.dataset # SELECT *
26
26
  # DB.dataset.from(:items) # SELECT * FROM items
27
- def dataset
28
- ds = Sequel::Dataset.new(self)
27
+ def dataset(opts=nil)
28
+ @dataset_class.new(self, opts)
29
29
  end
30
-
30
+
31
31
  # Fetches records for an arbitrary SQL statement. If a block is given,
32
32
  # it is used to iterate over the records:
33
33
  #