sequel 4.36.0 → 5.61.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 (760) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +548 -5749
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +265 -159
  5. data/bin/sequel +34 -12
  6. data/doc/advanced_associations.rdoc +228 -187
  7. data/doc/association_basics.rdoc +281 -291
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +86 -51
  10. data/doc/code_order.rdoc +25 -19
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/fork_safety.rdoc +84 -0
  16. data/doc/mass_assignment.rdoc +74 -31
  17. data/doc/migration.rdoc +59 -51
  18. data/doc/model_dataset_method_design.rdoc +129 -0
  19. data/doc/model_hooks.rdoc +15 -25
  20. data/doc/model_plugins.rdoc +12 -12
  21. data/doc/mssql_stored_procedures.rdoc +3 -3
  22. data/doc/object_model.rdoc +58 -68
  23. data/doc/opening_databases.rdoc +85 -95
  24. data/doc/postgresql.rdoc +263 -38
  25. data/doc/prepared_statements.rdoc +29 -24
  26. data/doc/querying.rdoc +189 -167
  27. data/doc/reflection.rdoc +5 -6
  28. data/doc/release_notes/5.0.0.txt +159 -0
  29. data/doc/release_notes/5.1.0.txt +31 -0
  30. data/doc/release_notes/5.10.0.txt +84 -0
  31. data/doc/release_notes/5.11.0.txt +83 -0
  32. data/doc/release_notes/5.12.0.txt +141 -0
  33. data/doc/release_notes/5.13.0.txt +27 -0
  34. data/doc/release_notes/5.14.0.txt +63 -0
  35. data/doc/release_notes/5.15.0.txt +39 -0
  36. data/doc/release_notes/5.16.0.txt +110 -0
  37. data/doc/release_notes/5.17.0.txt +31 -0
  38. data/doc/release_notes/5.18.0.txt +69 -0
  39. data/doc/release_notes/5.19.0.txt +28 -0
  40. data/doc/release_notes/5.2.0.txt +33 -0
  41. data/doc/release_notes/5.20.0.txt +89 -0
  42. data/doc/release_notes/5.21.0.txt +87 -0
  43. data/doc/release_notes/5.22.0.txt +48 -0
  44. data/doc/release_notes/5.23.0.txt +56 -0
  45. data/doc/release_notes/5.24.0.txt +56 -0
  46. data/doc/release_notes/5.25.0.txt +32 -0
  47. data/doc/release_notes/5.26.0.txt +35 -0
  48. data/doc/release_notes/5.27.0.txt +21 -0
  49. data/doc/release_notes/5.28.0.txt +16 -0
  50. data/doc/release_notes/5.29.0.txt +22 -0
  51. data/doc/release_notes/5.3.0.txt +121 -0
  52. data/doc/release_notes/5.30.0.txt +20 -0
  53. data/doc/release_notes/5.31.0.txt +148 -0
  54. data/doc/release_notes/5.32.0.txt +46 -0
  55. data/doc/release_notes/5.33.0.txt +24 -0
  56. data/doc/release_notes/5.34.0.txt +40 -0
  57. data/doc/release_notes/5.35.0.txt +56 -0
  58. data/doc/release_notes/5.36.0.txt +60 -0
  59. data/doc/release_notes/5.37.0.txt +30 -0
  60. data/doc/release_notes/5.38.0.txt +28 -0
  61. data/doc/release_notes/5.39.0.txt +19 -0
  62. data/doc/release_notes/5.4.0.txt +80 -0
  63. data/doc/release_notes/5.40.0.txt +40 -0
  64. data/doc/release_notes/5.41.0.txt +25 -0
  65. data/doc/release_notes/5.42.0.txt +136 -0
  66. data/doc/release_notes/5.43.0.txt +98 -0
  67. data/doc/release_notes/5.44.0.txt +32 -0
  68. data/doc/release_notes/5.45.0.txt +34 -0
  69. data/doc/release_notes/5.46.0.txt +87 -0
  70. data/doc/release_notes/5.47.0.txt +59 -0
  71. data/doc/release_notes/5.48.0.txt +14 -0
  72. data/doc/release_notes/5.49.0.txt +59 -0
  73. data/doc/release_notes/5.5.0.txt +61 -0
  74. data/doc/release_notes/5.50.0.txt +78 -0
  75. data/doc/release_notes/5.51.0.txt +47 -0
  76. data/doc/release_notes/5.52.0.txt +87 -0
  77. data/doc/release_notes/5.53.0.txt +23 -0
  78. data/doc/release_notes/5.54.0.txt +27 -0
  79. data/doc/release_notes/5.55.0.txt +21 -0
  80. data/doc/release_notes/5.56.0.txt +51 -0
  81. data/doc/release_notes/5.57.0.txt +23 -0
  82. data/doc/release_notes/5.58.0.txt +31 -0
  83. data/doc/release_notes/5.59.0.txt +73 -0
  84. data/doc/release_notes/5.6.0.txt +31 -0
  85. data/doc/release_notes/5.60.0.txt +22 -0
  86. data/doc/release_notes/5.61.0.txt +43 -0
  87. data/doc/release_notes/5.7.0.txt +108 -0
  88. data/doc/release_notes/5.8.0.txt +170 -0
  89. data/doc/release_notes/5.9.0.txt +99 -0
  90. data/doc/schema_modification.rdoc +95 -75
  91. data/doc/security.rdoc +109 -80
  92. data/doc/sharding.rdoc +74 -47
  93. data/doc/sql.rdoc +147 -122
  94. data/doc/testing.rdoc +43 -20
  95. data/doc/thread_safety.rdoc +2 -4
  96. data/doc/transactions.rdoc +97 -18
  97. data/doc/validations.rdoc +52 -50
  98. data/doc/virtual_rows.rdoc +90 -109
  99. data/lib/sequel/adapters/ado/access.rb +15 -17
  100. data/lib/sequel/adapters/ado/mssql.rb +6 -15
  101. data/lib/sequel/adapters/ado.rb +150 -20
  102. data/lib/sequel/adapters/amalgalite.rb +11 -23
  103. data/lib/sequel/adapters/ibmdb.rb +47 -55
  104. data/lib/sequel/adapters/jdbc/db2.rb +29 -39
  105. data/lib/sequel/adapters/jdbc/derby.rb +58 -54
  106. data/lib/sequel/adapters/jdbc/h2.rb +93 -35
  107. data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
  108. data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
  109. data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
  110. data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
  111. data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
  112. data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
  113. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
  114. data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
  115. data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
  116. data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
  117. data/lib/sequel/adapters/jdbc.rb +145 -130
  118. data/lib/sequel/adapters/mock.rb +100 -111
  119. data/lib/sequel/adapters/mysql.rb +114 -122
  120. data/lib/sequel/adapters/mysql2.rb +147 -63
  121. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  122. data/lib/sequel/adapters/odbc/mssql.rb +8 -14
  123. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  124. data/lib/sequel/adapters/odbc.rb +20 -25
  125. data/lib/sequel/adapters/oracle.rb +50 -56
  126. data/lib/sequel/adapters/postgres.rb +305 -327
  127. data/lib/sequel/adapters/postgresql.rb +1 -1
  128. data/lib/sequel/adapters/shared/access.rb +74 -78
  129. data/lib/sequel/adapters/shared/db2.rb +118 -71
  130. data/lib/sequel/adapters/shared/mssql.rb +301 -220
  131. data/lib/sequel/adapters/shared/mysql.rb +299 -217
  132. data/lib/sequel/adapters/shared/oracle.rb +226 -65
  133. data/lib/sequel/adapters/shared/postgres.rb +935 -395
  134. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
  135. data/lib/sequel/adapters/shared/sqlite.rb +447 -173
  136. data/lib/sequel/adapters/sqlanywhere.rb +48 -35
  137. data/lib/sequel/adapters/sqlite.rb +156 -111
  138. data/lib/sequel/adapters/tinytds.rb +30 -38
  139. data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
  140. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
  141. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
  142. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  143. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  144. data/lib/sequel/adapters/utils/replace.rb +1 -4
  145. data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
  146. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  147. data/lib/sequel/ast_transformer.rb +17 -89
  148. data/lib/sequel/connection_pool/sharded_single.rb +18 -15
  149. data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
  150. data/lib/sequel/connection_pool/single.rb +18 -13
  151. data/lib/sequel/connection_pool/threaded.rb +121 -120
  152. data/lib/sequel/connection_pool.rb +48 -29
  153. data/lib/sequel/core.rb +351 -301
  154. data/lib/sequel/database/connecting.rb +69 -57
  155. data/lib/sequel/database/dataset.rb +13 -5
  156. data/lib/sequel/database/dataset_defaults.rb +18 -102
  157. data/lib/sequel/database/features.rb +18 -4
  158. data/lib/sequel/database/logging.rb +12 -11
  159. data/lib/sequel/database/misc.rb +180 -122
  160. data/lib/sequel/database/query.rb +47 -27
  161. data/lib/sequel/database/schema_generator.rb +178 -84
  162. data/lib/sequel/database/schema_methods.rb +172 -97
  163. data/lib/sequel/database/transactions.rb +205 -44
  164. data/lib/sequel/database.rb +17 -2
  165. data/lib/sequel/dataset/actions.rb +339 -155
  166. data/lib/sequel/dataset/dataset_module.rb +46 -0
  167. data/lib/sequel/dataset/features.rb +90 -35
  168. data/lib/sequel/dataset/graph.rb +80 -58
  169. data/lib/sequel/dataset/misc.rb +137 -47
  170. data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
  171. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  172. data/lib/sequel/dataset/query.rb +530 -222
  173. data/lib/sequel/dataset/sql.rb +590 -368
  174. data/lib/sequel/dataset.rb +26 -16
  175. data/lib/sequel/deprecated.rb +12 -2
  176. data/lib/sequel/exceptions.rb +46 -16
  177. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  178. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  179. data/lib/sequel/extensions/_pretty_table.rb +2 -5
  180. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  181. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  182. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  183. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  184. data/lib/sequel/extensions/blank.rb +8 -0
  185. data/lib/sequel/extensions/caller_logging.rb +79 -0
  186. data/lib/sequel/extensions/columns_introspection.rb +4 -3
  187. data/lib/sequel/extensions/connection_expiration.rb +20 -10
  188. data/lib/sequel/extensions/connection_validator.rb +11 -10
  189. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  190. data/lib/sequel/extensions/constraint_validations.rb +62 -39
  191. data/lib/sequel/extensions/core_extensions.rb +42 -48
  192. data/lib/sequel/extensions/core_refinements.rb +80 -59
  193. data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
  194. data/lib/sequel/extensions/date_arithmetic.rb +98 -39
  195. data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
  196. data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
  197. data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
  198. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  199. data/lib/sequel/extensions/escaped_like.rb +100 -0
  200. data/lib/sequel/extensions/eval_inspect.rb +12 -15
  201. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  202. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  203. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  204. data/lib/sequel/extensions/from_block.rb +1 -34
  205. data/lib/sequel/extensions/graph_each.rb +4 -4
  206. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  207. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  208. data/lib/sequel/extensions/index_caching.rb +109 -0
  209. data/lib/sequel/extensions/inflector.rb +13 -5
  210. data/lib/sequel/extensions/integer64.rb +32 -0
  211. data/lib/sequel/extensions/is_distinct_from.rb +141 -0
  212. data/lib/sequel/extensions/looser_typecasting.rb +17 -8
  213. data/lib/sequel/extensions/migration.rb +119 -78
  214. data/lib/sequel/extensions/named_timezones.rb +88 -23
  215. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
  216. data/lib/sequel/extensions/null_dataset.rb +8 -8
  217. data/lib/sequel/extensions/pagination.rb +32 -29
  218. data/lib/sequel/extensions/pg_array.rb +221 -287
  219. data/lib/sequel/extensions/pg_array_ops.rb +17 -9
  220. data/lib/sequel/extensions/pg_enum.rb +63 -23
  221. data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
  222. data/lib/sequel/extensions/pg_hstore.rb +45 -54
  223. data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
  224. data/lib/sequel/extensions/pg_inet.rb +31 -12
  225. data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
  226. data/lib/sequel/extensions/pg_interval.rb +56 -29
  227. data/lib/sequel/extensions/pg_json.rb +417 -140
  228. data/lib/sequel/extensions/pg_json_ops.rb +270 -18
  229. data/lib/sequel/extensions/pg_loose_count.rb +4 -2
  230. data/lib/sequel/extensions/pg_multirange.rb +372 -0
  231. data/lib/sequel/extensions/pg_range.rb +131 -191
  232. data/lib/sequel/extensions/pg_range_ops.rb +42 -13
  233. data/lib/sequel/extensions/pg_row.rb +48 -81
  234. data/lib/sequel/extensions/pg_row_ops.rb +33 -14
  235. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  236. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  237. data/lib/sequel/extensions/query.rb +9 -7
  238. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  239. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  240. data/lib/sequel/extensions/s.rb +60 -0
  241. data/lib/sequel/extensions/schema_caching.rb +10 -1
  242. data/lib/sequel/extensions/schema_dumper.rb +71 -48
  243. data/lib/sequel/extensions/select_remove.rb +4 -4
  244. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  245. data/lib/sequel/extensions/server_block.rb +51 -27
  246. data/lib/sequel/extensions/split_array_nil.rb +4 -4
  247. data/lib/sequel/extensions/sql_comments.rb +119 -7
  248. data/lib/sequel/extensions/sql_expr.rb +2 -1
  249. data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
  250. data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
  251. data/lib/sequel/extensions/string_agg.rb +11 -8
  252. data/lib/sequel/extensions/string_date_time.rb +19 -23
  253. data/lib/sequel/extensions/symbol_aref.rb +55 -0
  254. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  255. data/lib/sequel/extensions/symbol_as.rb +23 -0
  256. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  257. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  258. data/lib/sequel/extensions/to_dot.rb +10 -4
  259. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  260. data/lib/sequel/model/associations.rb +1006 -284
  261. data/lib/sequel/model/base.rb +560 -805
  262. data/lib/sequel/model/dataset_module.rb +11 -10
  263. data/lib/sequel/model/default_inflections.rb +1 -1
  264. data/lib/sequel/model/errors.rb +10 -3
  265. data/lib/sequel/model/exceptions.rb +8 -10
  266. data/lib/sequel/model/inflections.rb +7 -20
  267. data/lib/sequel/model/plugins.rb +114 -0
  268. data/lib/sequel/model.rb +32 -82
  269. data/lib/sequel/plugins/active_model.rb +30 -14
  270. data/lib/sequel/plugins/after_initialize.rb +1 -1
  271. data/lib/sequel/plugins/association_dependencies.rb +25 -18
  272. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  273. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  274. data/lib/sequel/plugins/association_pks.rb +147 -70
  275. data/lib/sequel/plugins/association_proxies.rb +33 -9
  276. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  277. data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
  278. data/lib/sequel/plugins/auto_validations.rb +95 -28
  279. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  280. data/lib/sequel/plugins/before_after_save.rb +0 -42
  281. data/lib/sequel/plugins/blacklist_security.rb +21 -12
  282. data/lib/sequel/plugins/boolean_readers.rb +5 -5
  283. data/lib/sequel/plugins/boolean_subsets.rb +13 -8
  284. data/lib/sequel/plugins/caching.rb +25 -16
  285. data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
  286. data/lib/sequel/plugins/column_conflicts.rb +16 -3
  287. data/lib/sequel/plugins/column_encryption.rb +728 -0
  288. data/lib/sequel/plugins/column_select.rb +7 -5
  289. data/lib/sequel/plugins/columns_updated.rb +42 -0
  290. data/lib/sequel/plugins/composition.rb +42 -26
  291. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  292. data/lib/sequel/plugins/constraint_validations.rb +20 -14
  293. data/lib/sequel/plugins/csv_serializer.rb +56 -35
  294. data/lib/sequel/plugins/dataset_associations.rb +40 -17
  295. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  296. data/lib/sequel/plugins/defaults_setter.rb +65 -10
  297. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  298. data/lib/sequel/plugins/dirty.rb +62 -24
  299. data/lib/sequel/plugins/eager_each.rb +3 -3
  300. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  301. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  302. data/lib/sequel/plugins/enum.rb +124 -0
  303. data/lib/sequel/plugins/error_splitter.rb +17 -12
  304. data/lib/sequel/plugins/finder.rb +246 -0
  305. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  306. data/lib/sequel/plugins/force_encoding.rb +7 -12
  307. data/lib/sequel/plugins/hook_class_methods.rb +37 -54
  308. data/lib/sequel/plugins/input_transformer.rb +18 -10
  309. data/lib/sequel/plugins/insert_conflict.rb +76 -0
  310. data/lib/sequel/plugins/insert_returning_select.rb +2 -2
  311. data/lib/sequel/plugins/instance_filters.rb +10 -8
  312. data/lib/sequel/plugins/instance_hooks.rb +34 -17
  313. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  314. data/lib/sequel/plugins/inverted_subsets.rb +22 -13
  315. data/lib/sequel/plugins/json_serializer.rb +124 -64
  316. data/lib/sequel/plugins/lazy_attributes.rb +21 -14
  317. data/lib/sequel/plugins/list.rb +35 -21
  318. data/lib/sequel/plugins/many_through_many.rb +134 -21
  319. data/lib/sequel/plugins/modification_detection.rb +15 -5
  320. data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
  321. data/lib/sequel/plugins/nested_attributes.rb +61 -31
  322. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  323. data/lib/sequel/plugins/pg_array_associations.rb +103 -53
  324. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
  325. data/lib/sequel/plugins/pg_row.rb +5 -51
  326. data/lib/sequel/plugins/prepared_statements.rb +60 -72
  327. data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
  328. data/lib/sequel/plugins/rcte_tree.rb +68 -82
  329. data/lib/sequel/plugins/require_valid_schema.rb +67 -0
  330. data/lib/sequel/plugins/serialization.rb +43 -46
  331. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
  332. data/lib/sequel/plugins/sharding.rb +15 -10
  333. data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
  334. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  335. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  336. data/lib/sequel/plugins/split_values.rb +11 -6
  337. data/lib/sequel/plugins/sql_comments.rb +189 -0
  338. data/lib/sequel/plugins/static_cache.rb +77 -53
  339. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  340. data/lib/sequel/plugins/string_stripper.rb +3 -3
  341. data/lib/sequel/plugins/subclasses.rb +43 -10
  342. data/lib/sequel/plugins/subset_conditions.rb +15 -5
  343. data/lib/sequel/plugins/table_select.rb +2 -2
  344. data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
  345. data/lib/sequel/plugins/throw_failures.rb +110 -0
  346. data/lib/sequel/plugins/timestamps.rb +20 -8
  347. data/lib/sequel/plugins/touch.rb +19 -8
  348. data/lib/sequel/plugins/tree.rb +62 -32
  349. data/lib/sequel/plugins/typecast_on_load.rb +12 -4
  350. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  351. data/lib/sequel/plugins/unused_associations.rb +521 -0
  352. data/lib/sequel/plugins/update_or_create.rb +4 -4
  353. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  354. data/lib/sequel/plugins/update_refresh.rb +26 -15
  355. data/lib/sequel/plugins/uuid.rb +7 -11
  356. data/lib/sequel/plugins/validate_associated.rb +18 -0
  357. data/lib/sequel/plugins/validation_class_methods.rb +38 -19
  358. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  359. data/lib/sequel/plugins/validation_helpers.rb +57 -41
  360. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  361. data/lib/sequel/plugins/xml_serializer.rb +30 -31
  362. data/lib/sequel/sql.rb +471 -331
  363. data/lib/sequel/timezones.rb +78 -47
  364. data/lib/sequel/version.rb +7 -2
  365. data/lib/sequel.rb +1 -1
  366. metadata +217 -521
  367. data/Rakefile +0 -164
  368. data/doc/active_record.rdoc +0 -928
  369. data/doc/release_notes/1.0.txt +0 -38
  370. data/doc/release_notes/1.1.txt +0 -143
  371. data/doc/release_notes/1.3.txt +0 -101
  372. data/doc/release_notes/1.4.0.txt +0 -53
  373. data/doc/release_notes/1.5.0.txt +0 -155
  374. data/doc/release_notes/2.0.0.txt +0 -298
  375. data/doc/release_notes/2.1.0.txt +0 -271
  376. data/doc/release_notes/2.10.0.txt +0 -328
  377. data/doc/release_notes/2.11.0.txt +0 -215
  378. data/doc/release_notes/2.12.0.txt +0 -534
  379. data/doc/release_notes/2.2.0.txt +0 -253
  380. data/doc/release_notes/2.3.0.txt +0 -88
  381. data/doc/release_notes/2.4.0.txt +0 -106
  382. data/doc/release_notes/2.5.0.txt +0 -137
  383. data/doc/release_notes/2.6.0.txt +0 -157
  384. data/doc/release_notes/2.7.0.txt +0 -166
  385. data/doc/release_notes/2.8.0.txt +0 -171
  386. data/doc/release_notes/2.9.0.txt +0 -97
  387. data/doc/release_notes/3.0.0.txt +0 -221
  388. data/doc/release_notes/3.1.0.txt +0 -406
  389. data/doc/release_notes/3.10.0.txt +0 -286
  390. data/doc/release_notes/3.11.0.txt +0 -254
  391. data/doc/release_notes/3.12.0.txt +0 -304
  392. data/doc/release_notes/3.13.0.txt +0 -210
  393. data/doc/release_notes/3.14.0.txt +0 -118
  394. data/doc/release_notes/3.15.0.txt +0 -78
  395. data/doc/release_notes/3.16.0.txt +0 -45
  396. data/doc/release_notes/3.17.0.txt +0 -58
  397. data/doc/release_notes/3.18.0.txt +0 -120
  398. data/doc/release_notes/3.19.0.txt +0 -67
  399. data/doc/release_notes/3.2.0.txt +0 -268
  400. data/doc/release_notes/3.20.0.txt +0 -41
  401. data/doc/release_notes/3.21.0.txt +0 -87
  402. data/doc/release_notes/3.22.0.txt +0 -39
  403. data/doc/release_notes/3.23.0.txt +0 -172
  404. data/doc/release_notes/3.24.0.txt +0 -420
  405. data/doc/release_notes/3.25.0.txt +0 -88
  406. data/doc/release_notes/3.26.0.txt +0 -88
  407. data/doc/release_notes/3.27.0.txt +0 -82
  408. data/doc/release_notes/3.28.0.txt +0 -304
  409. data/doc/release_notes/3.29.0.txt +0 -459
  410. data/doc/release_notes/3.3.0.txt +0 -192
  411. data/doc/release_notes/3.30.0.txt +0 -135
  412. data/doc/release_notes/3.31.0.txt +0 -146
  413. data/doc/release_notes/3.32.0.txt +0 -202
  414. data/doc/release_notes/3.33.0.txt +0 -157
  415. data/doc/release_notes/3.34.0.txt +0 -671
  416. data/doc/release_notes/3.35.0.txt +0 -144
  417. data/doc/release_notes/3.36.0.txt +0 -245
  418. data/doc/release_notes/3.37.0.txt +0 -338
  419. data/doc/release_notes/3.38.0.txt +0 -234
  420. data/doc/release_notes/3.39.0.txt +0 -237
  421. data/doc/release_notes/3.4.0.txt +0 -325
  422. data/doc/release_notes/3.40.0.txt +0 -73
  423. data/doc/release_notes/3.41.0.txt +0 -155
  424. data/doc/release_notes/3.42.0.txt +0 -74
  425. data/doc/release_notes/3.43.0.txt +0 -105
  426. data/doc/release_notes/3.44.0.txt +0 -152
  427. data/doc/release_notes/3.45.0.txt +0 -179
  428. data/doc/release_notes/3.46.0.txt +0 -122
  429. data/doc/release_notes/3.47.0.txt +0 -270
  430. data/doc/release_notes/3.48.0.txt +0 -477
  431. data/doc/release_notes/3.5.0.txt +0 -510
  432. data/doc/release_notes/3.6.0.txt +0 -366
  433. data/doc/release_notes/3.7.0.txt +0 -179
  434. data/doc/release_notes/3.8.0.txt +0 -151
  435. data/doc/release_notes/3.9.0.txt +0 -233
  436. data/doc/release_notes/4.0.0.txt +0 -262
  437. data/doc/release_notes/4.1.0.txt +0 -85
  438. data/doc/release_notes/4.10.0.txt +0 -226
  439. data/doc/release_notes/4.11.0.txt +0 -147
  440. data/doc/release_notes/4.12.0.txt +0 -105
  441. data/doc/release_notes/4.13.0.txt +0 -169
  442. data/doc/release_notes/4.14.0.txt +0 -68
  443. data/doc/release_notes/4.15.0.txt +0 -56
  444. data/doc/release_notes/4.16.0.txt +0 -36
  445. data/doc/release_notes/4.17.0.txt +0 -38
  446. data/doc/release_notes/4.18.0.txt +0 -36
  447. data/doc/release_notes/4.19.0.txt +0 -45
  448. data/doc/release_notes/4.2.0.txt +0 -129
  449. data/doc/release_notes/4.20.0.txt +0 -79
  450. data/doc/release_notes/4.21.0.txt +0 -94
  451. data/doc/release_notes/4.22.0.txt +0 -72
  452. data/doc/release_notes/4.23.0.txt +0 -65
  453. data/doc/release_notes/4.24.0.txt +0 -99
  454. data/doc/release_notes/4.25.0.txt +0 -181
  455. data/doc/release_notes/4.26.0.txt +0 -44
  456. data/doc/release_notes/4.27.0.txt +0 -78
  457. data/doc/release_notes/4.28.0.txt +0 -57
  458. data/doc/release_notes/4.29.0.txt +0 -41
  459. data/doc/release_notes/4.3.0.txt +0 -40
  460. data/doc/release_notes/4.30.0.txt +0 -37
  461. data/doc/release_notes/4.31.0.txt +0 -57
  462. data/doc/release_notes/4.32.0.txt +0 -132
  463. data/doc/release_notes/4.33.0.txt +0 -88
  464. data/doc/release_notes/4.34.0.txt +0 -86
  465. data/doc/release_notes/4.35.0.txt +0 -130
  466. data/doc/release_notes/4.36.0.txt +0 -116
  467. data/doc/release_notes/4.4.0.txt +0 -92
  468. data/doc/release_notes/4.5.0.txt +0 -34
  469. data/doc/release_notes/4.6.0.txt +0 -30
  470. data/doc/release_notes/4.7.0.txt +0 -103
  471. data/doc/release_notes/4.8.0.txt +0 -175
  472. data/doc/release_notes/4.9.0.txt +0 -190
  473. data/lib/sequel/adapters/cubrid.rb +0 -144
  474. data/lib/sequel/adapters/do/mysql.rb +0 -66
  475. data/lib/sequel/adapters/do/postgres.rb +0 -44
  476. data/lib/sequel/adapters/do/sqlite3.rb +0 -42
  477. data/lib/sequel/adapters/do.rb +0 -158
  478. data/lib/sequel/adapters/jdbc/as400.rb +0 -84
  479. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
  480. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
  481. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
  482. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
  483. data/lib/sequel/adapters/odbc/progress.rb +0 -10
  484. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  485. data/lib/sequel/adapters/shared/firebird.rb +0 -247
  486. data/lib/sequel/adapters/shared/informix.rb +0 -54
  487. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
  488. data/lib/sequel/adapters/shared/progress.rb +0 -40
  489. data/lib/sequel/adapters/swift/mysql.rb +0 -49
  490. data/lib/sequel/adapters/swift/postgres.rb +0 -47
  491. data/lib/sequel/adapters/swift/sqlite.rb +0 -49
  492. data/lib/sequel/adapters/swift.rb +0 -160
  493. data/lib/sequel/adapters/utils/pg_types.rb +0 -70
  494. data/lib/sequel/dataset/mutation.rb +0 -111
  495. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
  496. data/lib/sequel/extensions/filter_having.rb +0 -63
  497. data/lib/sequel/extensions/hash_aliases.rb +0 -49
  498. data/lib/sequel/extensions/meta_def.rb +0 -35
  499. data/lib/sequel/extensions/query_literals.rb +0 -84
  500. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
  501. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
  502. data/lib/sequel/extensions/set_overrides.rb +0 -76
  503. data/lib/sequel/no_core_ext.rb +0 -3
  504. data/lib/sequel/plugins/association_autoreloading.rb +0 -9
  505. data/lib/sequel/plugins/identifier_columns.rb +0 -47
  506. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
  507. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
  508. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
  509. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
  510. data/lib/sequel/plugins/schema.rb +0 -82
  511. data/lib/sequel/plugins/scissors.rb +0 -35
  512. data/spec/adapter_spec.rb +0 -4
  513. data/spec/adapters/db2_spec.rb +0 -160
  514. data/spec/adapters/firebird_spec.rb +0 -411
  515. data/spec/adapters/informix_spec.rb +0 -100
  516. data/spec/adapters/mssql_spec.rb +0 -733
  517. data/spec/adapters/mysql_spec.rb +0 -1319
  518. data/spec/adapters/oracle_spec.rb +0 -313
  519. data/spec/adapters/postgres_spec.rb +0 -3790
  520. data/spec/adapters/spec_helper.rb +0 -49
  521. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  522. data/spec/adapters/sqlite_spec.rb +0 -688
  523. data/spec/bin_spec.rb +0 -258
  524. data/spec/core/connection_pool_spec.rb +0 -1045
  525. data/spec/core/database_spec.rb +0 -2636
  526. data/spec/core/dataset_spec.rb +0 -5175
  527. data/spec/core/deprecated_spec.rb +0 -70
  528. data/spec/core/expression_filters_spec.rb +0 -1247
  529. data/spec/core/mock_adapter_spec.rb +0 -464
  530. data/spec/core/object_graph_spec.rb +0 -303
  531. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  532. data/spec/core/schema_generator_spec.rb +0 -203
  533. data/spec/core/schema_spec.rb +0 -1676
  534. data/spec/core/spec_helper.rb +0 -34
  535. data/spec/core/version_spec.rb +0 -7
  536. data/spec/core_extensions_spec.rb +0 -699
  537. data/spec/core_model_spec.rb +0 -2
  538. data/spec/core_spec.rb +0 -1
  539. data/spec/extensions/accessed_columns_spec.rb +0 -51
  540. data/spec/extensions/active_model_spec.rb +0 -85
  541. data/spec/extensions/after_initialize_spec.rb +0 -24
  542. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  543. data/spec/extensions/association_dependencies_spec.rb +0 -117
  544. data/spec/extensions/association_pks_spec.rb +0 -405
  545. data/spec/extensions/association_proxies_spec.rb +0 -86
  546. data/spec/extensions/auto_validations_spec.rb +0 -192
  547. data/spec/extensions/before_after_save_spec.rb +0 -40
  548. data/spec/extensions/blacklist_security_spec.rb +0 -88
  549. data/spec/extensions/blank_spec.rb +0 -69
  550. data/spec/extensions/boolean_readers_spec.rb +0 -93
  551. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  552. data/spec/extensions/caching_spec.rb +0 -270
  553. data/spec/extensions/class_table_inheritance_spec.rb +0 -444
  554. data/spec/extensions/column_conflicts_spec.rb +0 -60
  555. data/spec/extensions/column_select_spec.rb +0 -108
  556. data/spec/extensions/columns_introspection_spec.rb +0 -91
  557. data/spec/extensions/composition_spec.rb +0 -242
  558. data/spec/extensions/connection_expiration_spec.rb +0 -121
  559. data/spec/extensions/connection_validator_spec.rb +0 -127
  560. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
  561. data/spec/extensions/constraint_validations_spec.rb +0 -389
  562. data/spec/extensions/core_refinements_spec.rb +0 -519
  563. data/spec/extensions/csv_serializer_spec.rb +0 -180
  564. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  565. data/spec/extensions/dataset_associations_spec.rb +0 -343
  566. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  567. data/spec/extensions/date_arithmetic_spec.rb +0 -167
  568. data/spec/extensions/defaults_setter_spec.rb +0 -102
  569. data/spec/extensions/delay_add_association_spec.rb +0 -74
  570. data/spec/extensions/dirty_spec.rb +0 -180
  571. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
  572. data/spec/extensions/eager_each_spec.rb +0 -66
  573. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  574. data/spec/extensions/error_splitter_spec.rb +0 -18
  575. data/spec/extensions/error_sql_spec.rb +0 -20
  576. data/spec/extensions/eval_inspect_spec.rb +0 -73
  577. data/spec/extensions/filter_having_spec.rb +0 -40
  578. data/spec/extensions/force_encoding_spec.rb +0 -114
  579. data/spec/extensions/from_block_spec.rb +0 -21
  580. data/spec/extensions/graph_each_spec.rb +0 -119
  581. data/spec/extensions/hash_aliases_spec.rb +0 -24
  582. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  583. data/spec/extensions/identifier_columns_spec.rb +0 -17
  584. data/spec/extensions/inflector_spec.rb +0 -183
  585. data/spec/extensions/input_transformer_spec.rb +0 -54
  586. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  587. data/spec/extensions/instance_filters_spec.rb +0 -79
  588. data/spec/extensions/instance_hooks_spec.rb +0 -276
  589. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  590. data/spec/extensions/json_serializer_spec.rb +0 -304
  591. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  592. data/spec/extensions/list_spec.rb +0 -278
  593. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  594. data/spec/extensions/many_through_many_spec.rb +0 -2172
  595. data/spec/extensions/meta_def_spec.rb +0 -21
  596. data/spec/extensions/migration_spec.rb +0 -728
  597. data/spec/extensions/modification_detection_spec.rb +0 -80
  598. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  599. data/spec/extensions/named_timezones_spec.rb +0 -108
  600. data/spec/extensions/nested_attributes_spec.rb +0 -697
  601. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -65
  602. data/spec/extensions/null_dataset_spec.rb +0 -85
  603. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  604. data/spec/extensions/pagination_spec.rb +0 -118
  605. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  606. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  607. data/spec/extensions/pg_array_spec.rb +0 -390
  608. data/spec/extensions/pg_enum_spec.rb +0 -92
  609. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  610. data/spec/extensions/pg_hstore_spec.rb +0 -206
  611. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  612. data/spec/extensions/pg_inet_spec.rb +0 -52
  613. data/spec/extensions/pg_interval_spec.rb +0 -76
  614. data/spec/extensions/pg_json_ops_spec.rb +0 -275
  615. data/spec/extensions/pg_json_spec.rb +0 -218
  616. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  617. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  618. data/spec/extensions/pg_range_spec.rb +0 -473
  619. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  620. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  621. data/spec/extensions/pg_row_spec.rb +0 -360
  622. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  623. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  624. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  625. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  626. data/spec/extensions/prepared_statements_spec.rb +0 -103
  627. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  628. data/spec/extensions/pretty_table_spec.rb +0 -92
  629. data/spec/extensions/query_literals_spec.rb +0 -183
  630. data/spec/extensions/query_spec.rb +0 -102
  631. data/spec/extensions/rcte_tree_spec.rb +0 -392
  632. data/spec/extensions/round_timestamps_spec.rb +0 -43
  633. data/spec/extensions/schema_caching_spec.rb +0 -41
  634. data/spec/extensions/schema_dumper_spec.rb +0 -814
  635. data/spec/extensions/schema_spec.rb +0 -117
  636. data/spec/extensions/scissors_spec.rb +0 -26
  637. data/spec/extensions/select_remove_spec.rb +0 -38
  638. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  639. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  640. data/spec/extensions/serialization_spec.rb +0 -362
  641. data/spec/extensions/server_block_spec.rb +0 -90
  642. data/spec/extensions/server_logging_spec.rb +0 -45
  643. data/spec/extensions/set_overrides_spec.rb +0 -61
  644. data/spec/extensions/sharding_spec.rb +0 -198
  645. data/spec/extensions/shared_caching_spec.rb +0 -175
  646. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  647. data/spec/extensions/singular_table_names_spec.rb +0 -22
  648. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  649. data/spec/extensions/spec_helper.rb +0 -71
  650. data/spec/extensions/split_array_nil_spec.rb +0 -24
  651. data/spec/extensions/split_values_spec.rb +0 -22
  652. data/spec/extensions/sql_comments_spec.rb +0 -27
  653. data/spec/extensions/sql_expr_spec.rb +0 -60
  654. data/spec/extensions/static_cache_spec.rb +0 -361
  655. data/spec/extensions/string_agg_spec.rb +0 -85
  656. data/spec/extensions/string_date_time_spec.rb +0 -95
  657. data/spec/extensions/string_stripper_spec.rb +0 -68
  658. data/spec/extensions/subclasses_spec.rb +0 -66
  659. data/spec/extensions/subset_conditions_spec.rb +0 -38
  660. data/spec/extensions/table_select_spec.rb +0 -71
  661. data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
  662. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  663. data/spec/extensions/timestamps_spec.rb +0 -175
  664. data/spec/extensions/to_dot_spec.rb +0 -154
  665. data/spec/extensions/touch_spec.rb +0 -203
  666. data/spec/extensions/tree_spec.rb +0 -274
  667. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  668. data/spec/extensions/unlimited_update_spec.rb +0 -20
  669. data/spec/extensions/update_or_create_spec.rb +0 -87
  670. data/spec/extensions/update_primary_key_spec.rb +0 -100
  671. data/spec/extensions/update_refresh_spec.rb +0 -53
  672. data/spec/extensions/uuid_spec.rb +0 -106
  673. data/spec/extensions/validate_associated_spec.rb +0 -52
  674. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  675. data/spec/extensions/validation_helpers_spec.rb +0 -554
  676. data/spec/extensions/xml_serializer_spec.rb +0 -207
  677. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  678. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  679. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  680. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  681. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  682. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  683. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  684. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  685. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  686. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  687. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  688. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  689. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  690. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  691. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  692. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  693. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  694. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  695. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  696. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  697. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  698. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  699. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  700. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  701. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  702. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  703. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  704. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  705. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  706. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  707. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  708. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  709. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  710. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  711. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  712. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  713. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  714. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  715. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  716. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  717. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  718. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  719. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  720. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  721. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  722. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  723. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  724. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  725. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  726. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  727. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  728. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  729. data/spec/guards_helper.rb +0 -55
  730. data/spec/integration/associations_test.rb +0 -2506
  731. data/spec/integration/database_test.rb +0 -113
  732. data/spec/integration/dataset_test.rb +0 -1858
  733. data/spec/integration/eager_loader_test.rb +0 -687
  734. data/spec/integration/migrator_test.rb +0 -262
  735. data/spec/integration/model_test.rb +0 -230
  736. data/spec/integration/plugin_test.rb +0 -2297
  737. data/spec/integration/prepared_statement_test.rb +0 -467
  738. data/spec/integration/schema_test.rb +0 -815
  739. data/spec/integration/spec_helper.rb +0 -56
  740. data/spec/integration/timezone_test.rb +0 -86
  741. data/spec/integration/transaction_test.rb +0 -406
  742. data/spec/integration/type_test.rb +0 -133
  743. data/spec/model/association_reflection_spec.rb +0 -565
  744. data/spec/model/associations_spec.rb +0 -4589
  745. data/spec/model/base_spec.rb +0 -759
  746. data/spec/model/class_dataset_methods_spec.rb +0 -150
  747. data/spec/model/dataset_methods_spec.rb +0 -149
  748. data/spec/model/eager_loading_spec.rb +0 -2197
  749. data/spec/model/hooks_spec.rb +0 -604
  750. data/spec/model/inflector_spec.rb +0 -26
  751. data/spec/model/model_spec.rb +0 -1097
  752. data/spec/model/plugins_spec.rb +0 -299
  753. data/spec/model/record_spec.rb +0 -2162
  754. data/spec/model/spec_helper.rb +0 -46
  755. data/spec/model/validations_spec.rb +0 -193
  756. data/spec/model_no_assoc_spec.rb +0 -1
  757. data/spec/model_spec.rb +0 -1
  758. data/spec/plugin_spec.rb +0 -1
  759. data/spec/sequel_coverage.rb +0 -15
  760. data/spec/spec_config.rb +0 -10
@@ -1,2636 +0,0 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
-
3
- describe "A new Database" do
4
- before do
5
- @db = Sequel::Database.new(1 => 2, :logger => 3)
6
- end
7
- after do
8
- Sequel.quote_identifiers = false
9
- Sequel.identifier_input_method = nil
10
- Sequel.identifier_output_method = nil
11
- end
12
-
13
- it "should receive options" do
14
- @db.opts[1].must_equal 2
15
- @db.opts[:logger].must_equal 3
16
- end
17
-
18
- it "should set the logger from opts[:logger] and opts[:loggers]" do
19
- @db.loggers.must_equal [3]
20
- Sequel::Database.new(1 => 2, :loggers => 3).loggers.must_equal [3]
21
- Sequel::Database.new(1 => 2, :loggers => [3]).loggers.must_equal [3]
22
- Sequel::Database.new(1 => 2, :logger => 4, :loggers => 3).loggers.must_equal [4,3]
23
- Sequel::Database.new(1 => 2, :logger => [4], :loggers => [3]).loggers.must_equal [4,3]
24
- end
25
-
26
- it "should support :preconnect option to preconnect to database" do
27
- @db.pool.size.must_equal 0
28
- c = Class.new(Sequel::Database) do
29
- def connect(_)
30
- :connect
31
- end
32
- end
33
- db = c.new(1 => 2, :logger => 3, :preconnect=>true)
34
- db.pool.size.must_equal db.pool.max_size
35
- db = c.new(1 => 2, :logger => 3, :preconnect=>:concurrently)
36
- db.pool.size.must_equal db.pool.max_size
37
- end
38
-
39
- it "should handle the default string column size" do
40
- @db.default_string_column_size.must_equal 255
41
- db = Sequel::Database.new(:default_string_column_size=>50)
42
- db.default_string_column_size.must_equal 50
43
- db.default_string_column_size = 2
44
- db.default_string_column_size.must_equal 2
45
- end
46
-
47
- it "should set the sql_log_level from opts[:sql_log_level]" do
48
- Sequel::Database.new(1 => 2, :sql_log_level=>:debug).sql_log_level.must_equal :debug
49
- Sequel::Database.new(1 => 2, :sql_log_level=>'debug').sql_log_level.must_equal :debug
50
- end
51
-
52
- it "should create a connection pool" do
53
- @db.pool.must_be_kind_of(Sequel::ConnectionPool)
54
- @db.pool.max_size.must_equal 4
55
-
56
- Sequel::Database.new(:max_connections => 10).pool.max_size.must_equal 10
57
- end
58
-
59
- it "should have the connection pool use the connect method to get connections" do
60
- cc = nil
61
- d = Sequel::Database.new
62
- meta_def(d, :connect){|c| 1234}
63
- d.synchronize {|c| cc = c}
64
- cc.must_equal 1234
65
- end
66
-
67
- it "should respect the :single_threaded option" do
68
- db = Sequel::Database.new(:single_threaded=>true){123}
69
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
70
- db = Sequel::Database.new(:single_threaded=>'t'){123}
71
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
72
- db = Sequel::Database.new(:single_threaded=>'1'){123}
73
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
74
- db = Sequel::Database.new(:single_threaded=>false){123}
75
- db.pool.must_be_kind_of(Sequel::ConnectionPool)
76
- db = Sequel::Database.new(:single_threaded=>'f'){123}
77
- db.pool.must_be_kind_of(Sequel::ConnectionPool)
78
- db = Sequel::Database.new(:single_threaded=>'0'){123}
79
- db.pool.must_be_kind_of(Sequel::ConnectionPool)
80
- end
81
-
82
- it "should respect the :quote_identifiers option" do
83
- db = Sequel::Database.new(:quote_identifiers=>false)
84
- db.quote_identifiers?.must_equal false
85
- db = Sequel::Database.new(:quote_identifiers=>true)
86
- db.quote_identifiers?.must_equal true
87
- end
88
-
89
- it "should upcase on input and downcase on output by default" do
90
- db = Sequel::Database.new
91
- db.send(:identifier_input_method_default).must_equal :upcase
92
- db.send(:identifier_output_method_default).must_equal :downcase
93
- end
94
-
95
- it "should respect the :identifier_input_method option" do
96
- Sequel.identifier_input_method = nil
97
- Sequel::Database.identifier_input_method.must_equal false
98
- db = Sequel::Database.new(:identifier_input_method=>nil)
99
- db.identifier_input_method.must_equal nil
100
- db.identifier_input_method = :downcase
101
- db.identifier_input_method.must_equal :downcase
102
- db = Sequel::Database.new(:identifier_input_method=>:upcase)
103
- db.identifier_input_method.must_equal :upcase
104
- db.identifier_input_method = nil
105
- db.identifier_input_method.must_equal nil
106
- Sequel.identifier_input_method = :downcase
107
- Sequel::Database.identifier_input_method.must_equal :downcase
108
- db = Sequel::Database.new(:identifier_input_method=>nil)
109
- db.identifier_input_method.must_equal nil
110
- db.identifier_input_method = :upcase
111
- db.identifier_input_method.must_equal :upcase
112
- db = Sequel::Database.new(:identifier_input_method=>:upcase)
113
- db.identifier_input_method.must_equal :upcase
114
- db.identifier_input_method = nil
115
- db.identifier_input_method.must_equal nil
116
- end
117
-
118
- it "should respect the :identifier_output_method option" do
119
- Sequel.identifier_output_method = nil
120
- Sequel::Database.identifier_output_method.must_equal false
121
- db = Sequel::Database.new(:identifier_output_method=>nil)
122
- db.identifier_output_method.must_equal nil
123
- db.identifier_output_method = :downcase
124
- db.identifier_output_method.must_equal :downcase
125
- db = Sequel::Database.new(:identifier_output_method=>:upcase)
126
- db.identifier_output_method.must_equal :upcase
127
- db.identifier_output_method = nil
128
- db.identifier_output_method.must_equal nil
129
- Sequel.identifier_output_method = :downcase
130
- Sequel::Database.identifier_output_method.must_equal :downcase
131
- db = Sequel::Database.new(:identifier_output_method=>nil)
132
- db.identifier_output_method.must_equal nil
133
- db.identifier_output_method = :upcase
134
- db.identifier_output_method.must_equal :upcase
135
- db = Sequel::Database.new(:identifier_output_method=>:upcase)
136
- db.identifier_output_method.must_equal :upcase
137
- db.identifier_output_method = nil
138
- db.identifier_output_method.must_equal nil
139
- end
140
-
141
- it "should use the default Sequel.quote_identifiers value" do
142
- Sequel.quote_identifiers = true
143
- Sequel::Database.new({}).quote_identifiers?.must_equal true
144
- Sequel.quote_identifiers = false
145
- Sequel::Database.new({}).quote_identifiers?.must_equal false
146
- Sequel::Database.quote_identifiers = true
147
- Sequel::Database.new({}).quote_identifiers?.must_equal true
148
- Sequel::Database.quote_identifiers = false
149
- Sequel::Database.new({}).quote_identifiers?.must_equal false
150
- end
151
-
152
- it "should use the default Sequel.identifier_input_method value" do
153
- Sequel.identifier_input_method = :downcase
154
- Sequel::Database.new({}).identifier_input_method.must_equal :downcase
155
- Sequel.identifier_input_method = :upcase
156
- Sequel::Database.new({}).identifier_input_method.must_equal :upcase
157
- Sequel::Database.identifier_input_method = :downcase
158
- Sequel::Database.new({}).identifier_input_method.must_equal :downcase
159
- Sequel::Database.identifier_input_method = :upcase
160
- Sequel::Database.new({}).identifier_input_method.must_equal :upcase
161
- end
162
-
163
- it "should use the default Sequel.identifier_output_method value" do
164
- Sequel.identifier_output_method = :downcase
165
- Sequel::Database.new({}).identifier_output_method.must_equal :downcase
166
- Sequel.identifier_output_method = :upcase
167
- Sequel::Database.new({}).identifier_output_method.must_equal :upcase
168
- Sequel::Database.identifier_output_method = :downcase
169
- Sequel::Database.new({}).identifier_output_method.must_equal :downcase
170
- Sequel::Database.identifier_output_method = :upcase
171
- Sequel::Database.new({}).identifier_output_method.must_equal :upcase
172
- end
173
-
174
- it "should respect the quote_indentifiers_default method if Sequel.quote_identifiers = nil" do
175
- Sequel.quote_identifiers = nil
176
- Sequel::Database.new({}).quote_identifiers?.must_equal true
177
- x = Class.new(Sequel::Database){def quote_identifiers_default; false end}
178
- x.new({}).quote_identifiers?.must_equal false
179
- y = Class.new(Sequel::Database){def quote_identifiers_default; true end}
180
- y.new({}).quote_identifiers?.must_equal true
181
- end
182
-
183
- it "should respect the identifier_input_method_default method" do
184
- class Sequel::Database
185
- @identifier_input_method = nil
186
- end
187
- x = Class.new(Sequel::Database){def identifier_input_method_default; :downcase end}
188
- x.new({}).identifier_input_method.must_equal :downcase
189
- y = Class.new(Sequel::Database){def identifier_input_method_default; :camelize end}
190
- y.new({}).identifier_input_method.must_equal :camelize
191
- end
192
-
193
- it "should respect the identifier_output_method_default method if Sequel.identifier_output_method is not called" do
194
- class Sequel::Database
195
- @identifier_output_method = nil
196
- end
197
- x = Class.new(Sequel::Database){def identifier_output_method_default; :upcase end}
198
- x.new({}).identifier_output_method.must_equal :upcase
199
- y = Class.new(Sequel::Database){def identifier_output_method_default; :underscore end}
200
- y.new({}).identifier_output_method.must_equal :underscore
201
- end
202
-
203
- it "should just use a :uri option for jdbc with the full connection string" do
204
- db = Sequel::Database.stub(:adapter_class, Sequel::Database) do
205
- Sequel.connect('jdbc:test://host/db_name')
206
- end
207
- db.must_be_kind_of(Sequel::Database)
208
- db.opts[:uri].must_equal 'jdbc:test://host/db_name'
209
- end
210
-
211
- it "should just use a :uri option for do with the full connection string" do
212
- db = Sequel::Database.stub(:adapter_class, Sequel::Database) do
213
- Sequel.connect('do:test://host/db_name')
214
- end
215
- db.must_be_kind_of(Sequel::Database)
216
- db.opts[:uri].must_equal 'do:test://host/db_name'
217
- end
218
-
219
- it "should populate :adapter option when using connection string" do
220
- Sequel.connect('mock:/').opts[:adapter].must_equal "mock"
221
- end
222
-
223
- it "should respect the :keep_reference option for not keeping a reference in Sequel::DATABASES" do
224
- db = Sequel.connect('mock:///?keep_reference=f')
225
- Sequel::DATABASES.wont_include(db)
226
- end
227
-
228
- it 'should strip square brackets for ipv6 hosts' do
229
- Sequel.connect('mock://[::1]').opts[:host].must_equal "::1"
230
- end if RUBY_VERSION >= '1.9.3'
231
- end
232
-
233
- describe "Database#disconnect" do
234
- it "should call pool.disconnect" do
235
- d = Sequel::Database.new
236
- p = d.pool
237
- def p.disconnect(h)
238
- raise unless h == {}
239
- 2
240
- end
241
- d.disconnect.must_equal 2
242
- end
243
- end
244
-
245
- describe "Sequel.extension" do
246
- it "should attempt to load the given extension" do
247
- proc{Sequel.extension :blah}.must_raise(LoadError)
248
- end
249
- end
250
-
251
- describe "Database#log_info" do
252
- before do
253
- @o = Object.new
254
- def @o.logs; @logs || []; end
255
- def @o.to_ary; [self]; end
256
- def @o.method_missing(*args); (@logs ||= []) << args; end
257
- @db = Sequel::Database.new(:logger=>@o)
258
- end
259
-
260
- it "should log message at info level to all loggers" do
261
- @db.log_info('blah')
262
- @o.logs.must_equal [[:info, 'blah']]
263
- end
264
-
265
- it "should log message with args at info level to all loggers" do
266
- @db.log_info('blah', [1, 2])
267
- @o.logs.must_equal [[:info, 'blah; [1, 2]']]
268
- end
269
- end
270
-
271
- describe "Database#log_yield" do
272
- before do
273
- @o = Object.new
274
- def @o.logs; @logs || []; end
275
- def @o.warn(*args); (@logs ||= []) << [:warn] + args; end
276
- def @o.method_missing(*args); (@logs ||= []) << args; end
277
- def @o.to_ary; [self]; end
278
- @db = Sequel::Database.new(:logger=>@o)
279
- end
280
-
281
- it "should yield to the passed block" do
282
- a = nil
283
- @db.log_yield('blah'){a = 1}
284
- a.must_equal 1
285
- end
286
-
287
- it "should raise an exception if a block is not passed" do
288
- proc{@db.log_yield('blah')}.must_raise LocalJumpError
289
- end
290
-
291
- it "should log message with duration at info level to all loggers" do
292
- @db.log_yield('blah'){}
293
- @o.logs.length.must_equal 1
294
- @o.logs.first.length.must_equal 2
295
- @o.logs.first.first.must_equal :info
296
- @o.logs.first.last.must_match(/\A\(\d\.\d{6}s\) blah\z/)
297
- end
298
-
299
- it "should respect sql_log_level setting" do
300
- @db.sql_log_level = :debug
301
- @db.log_yield('blah'){}
302
- @o.logs.length.must_equal 1
303
- @o.logs.first.length.must_equal 2
304
- @o.logs.first.first.must_equal :debug
305
- @o.logs.first.last.must_match(/\A\(\d\.\d{6}s\) blah\z/)
306
- end
307
-
308
- it "should log message with duration at warn level if duration greater than log_warn_duration" do
309
- @db.log_warn_duration = 0
310
- @db.log_yield('blah'){}
311
- @o.logs.length.must_equal 1
312
- @o.logs.first.length.must_equal 2
313
- @o.logs.first.first.must_equal :warn
314
- @o.logs.first.last.must_match(/\A\(\d\.\d{6}s\) blah\z/)
315
- end
316
-
317
- it "should log message with duration at info level if duration less than log_warn_duration" do
318
- @db.log_warn_duration = 1000
319
- @db.log_yield('blah'){}
320
- @o.logs.length.must_equal 1
321
- @o.logs.first.length.must_equal 2
322
- @o.logs.first.first.must_equal :info
323
- @o.logs.first.last.must_match(/\A\(\d\.\d{6}s\) blah\z/)
324
- end
325
-
326
- it "should log message at error level if block raises an error" do
327
- @db.log_warn_duration = 0
328
- proc{@db.log_yield('blah'){raise Sequel::Error, 'adsf'}}.must_raise Sequel::Error
329
- @o.logs.length.must_equal 1
330
- @o.logs.first.length.must_equal 2
331
- @o.logs.first.first.must_equal :error
332
- @o.logs.first.last.must_match(/\ASequel::Error: adsf: blah\z/)
333
- end
334
-
335
- it "should include args with message if args passed" do
336
- @db.log_yield('blah', [1, 2]){}
337
- @o.logs.length.must_equal 1
338
- @o.logs.first.length.must_equal 2
339
- @o.logs.first.first.must_equal :info
340
- @o.logs.first.last.must_match(/\A\(\d\.\d{6}s\) blah; \[1, 2\]\z/)
341
- end
342
- end
343
-
344
- describe "Database#log_connection_yield" do
345
- before do
346
- @o = Object.new
347
- def @o.logs; @logs || []; end
348
- def @o.to_ary; [self]; end
349
- def @o.method_missing(*args); (@logs ||= []) << args; end
350
- @conn = Object.new
351
- @db = Sequel::Database.new(:logger=>@o)
352
- end
353
-
354
- it "should log SQL to the loggers" do
355
- @db.log_connection_yield("some SQL", @conn){}
356
- @o.logs.length.must_equal 1
357
- @o.logs.first.length.must_equal 2
358
- @o.logs.first.first.must_equal :info
359
- @o.logs.first.last.must_match(/some SQL\z/)
360
- @o.logs.first.last.wont_match(/\(conn: -?\d+\) some SQL\z/)
361
- end
362
-
363
- it "should include connection information when logging" do
364
- @db.log_connection_info = true
365
- @db.log_connection_yield("some SQL", @conn){}
366
- @o.logs.length.must_equal 1
367
- @o.logs.first.length.must_equal 2
368
- @o.logs.first.first.must_equal :info
369
- @o.logs.first.last.must_match(/\(conn: -?\d+\) some SQL\z/)
370
- end
371
- end
372
-
373
- describe "Database#uri" do
374
- before do
375
- @c = Class.new(Sequel::Database) do
376
- set_adapter_scheme :mau
377
- end
378
-
379
- @db = Sequel.connect('mau://user:pass@localhost:9876/maumau')
380
- end
381
-
382
- it "should return the connection URI for the database" do
383
- @db.uri.must_equal 'mau://user:pass@localhost:9876/maumau'
384
- end
385
-
386
- it "should return nil if a connection uri was not used" do
387
- Sequel.mock.uri.must_equal nil
388
- end
389
-
390
- it "should be aliased as #url" do
391
- @db.url.must_equal 'mau://user:pass@localhost:9876/maumau'
392
- end
393
- end
394
-
395
- describe "Database.adapter_scheme and #adapter_scheme" do
396
- it "should return the database scheme" do
397
- Sequel::Database.adapter_scheme.must_equal nil
398
-
399
- @c = Class.new(Sequel::Database) do
400
- set_adapter_scheme :mau
401
- end
402
-
403
- @c.adapter_scheme.must_equal :mau
404
- @c.new({}).adapter_scheme.must_equal :mau
405
- end
406
- end
407
-
408
- describe "Database#dataset" do
409
- before do
410
- @db = Sequel::Database.new
411
- @ds = @db.dataset
412
- end
413
-
414
- it "should provide a blank dataset through #dataset" do
415
- @ds.must_be_kind_of(Sequel::Dataset)
416
- @ds.opts.must_equal({})
417
- @ds.db.must_be_same_as(@db)
418
- end
419
-
420
- it "should provide a #from dataset" do
421
- d = @db.from(:mau)
422
- d.must_be_kind_of(Sequel::Dataset)
423
- d.sql.must_equal 'SELECT * FROM mau'
424
-
425
- e = @db[:miu]
426
- e.must_be_kind_of(Sequel::Dataset)
427
- e.sql.must_equal 'SELECT * FROM miu'
428
- end
429
-
430
- it "should provide a filtered #from dataset if a block is given" do
431
- d = @db.from(:mau){x.sql_number > 100}
432
- d.must_be_kind_of(Sequel::Dataset)
433
- d.sql.must_equal 'SELECT * FROM mau WHERE (x > 100)'
434
- end
435
-
436
- it "should provide a #select dataset" do
437
- d = @db.select(:a, :b, :c).from(:mau)
438
- d.must_be_kind_of(Sequel::Dataset)
439
- d.sql.must_equal 'SELECT a, b, c FROM mau'
440
- end
441
-
442
- it "should allow #select to take a block" do
443
- d = @db.select(:a, :b){c}.from(:mau)
444
- d.must_be_kind_of(Sequel::Dataset)
445
- d.sql.must_equal 'SELECT a, b, c FROM mau'
446
- end
447
- end
448
-
449
- describe "Database#dataset_class" do
450
- before do
451
- @db = Sequel::Database.new
452
- @dsc = Class.new(Sequel::Dataset)
453
- end
454
-
455
- it "should have setter set the class to use to create datasets" do
456
- @db.dataset_class = @dsc
457
- ds = @db.dataset
458
- ds.must_be_kind_of(@dsc)
459
- ds.opts.must_equal({})
460
- ds.db.must_be_same_as(@db)
461
- end
462
-
463
- it "should have getter return the class to use to create datasets" do
464
- [@db.dataset_class, @db.dataset_class.superclass].must_include(Sequel::Dataset)
465
- @db.dataset_class = @dsc
466
- [@db.dataset_class, @db.dataset_class.superclass].must_include(@dsc)
467
- end
468
- end
469
-
470
- describe "Database#extend_datasets" do
471
- before do
472
- @db = Sequel::Database.new
473
- @m = Module.new{def foo() [3] end}
474
- @m2 = Module.new{def foo() [4] + super end}
475
- @db.extend_datasets(@m)
476
- end
477
-
478
- it "should clear a cached dataset" do
479
- @db = Sequel::Database.new
480
- @db.literal(1).must_equal '1'
481
- @db.extend_datasets{def literal(v) '2' end}
482
- @db.literal(1).must_equal '2'
483
- end
484
-
485
- it "should change the dataset class to a subclass the first time it is called" do
486
- @db.dataset_class.superclass.must_equal Sequel::Dataset
487
- end
488
-
489
- it "should not create a subclass of the dataset class if called more than once" do
490
- @db.extend_datasets(@m2)
491
- @db.dataset_class.superclass.must_equal Sequel::Dataset
492
- end
493
-
494
- it "should make the dataset class include the module" do
495
- @db.dataset_class.ancestors.must_include(@m)
496
- @db.dataset_class.ancestors.wont_include(@m2)
497
- @db.extend_datasets(@m2)
498
- @db.dataset_class.ancestors.must_include(@m)
499
- @db.dataset_class.ancestors.must_include(@m2)
500
- end
501
-
502
- it "should have datasets respond to the module's methods" do
503
- @db.dataset.foo.must_equal [3]
504
- @db.extend_datasets(@m2)
505
- @db.dataset.foo.must_equal [4, 3]
506
- end
507
-
508
- it "should take a block and create a module from it to use" do
509
- @db.dataset.foo.must_equal [3]
510
- @db.extend_datasets{def foo() [5] + super end}
511
- @db.dataset.foo.must_equal [5, 3]
512
- end
513
-
514
- it "should raise an error if both a module and a block are provided" do
515
- proc{@db.extend_datasets(@m2){def foo() [5] + super end}}.must_raise(Sequel::Error)
516
- end
517
-
518
- it "should be able to override methods defined in the original Dataset class" do
519
- @db.extend_datasets(Module.new{def select(*a, &block) super.order(*a, &block) end})
520
- @db[:t].select(:a, :b).sql.must_equal 'SELECT a, b FROM t ORDER BY a, b'
521
- end
522
-
523
- it "should reapply settings if dataset_class is changed" do
524
- c = Class.new(Sequel::Dataset)
525
- @db.dataset_class = c
526
- @db.dataset_class.superclass.must_equal c
527
- @db.dataset_class.ancestors.must_include(@m)
528
- @db.dataset.foo.must_equal [3]
529
- end
530
- end
531
-
532
- describe "Database#disconnect_connection" do
533
- it "should call close on the connection" do
534
- o = Object.new
535
- def o.close() @closed=true end
536
- Sequel::Database.new.disconnect_connection(o)
537
- o.instance_variable_get(:@closed).must_equal true
538
- end
539
- end
540
-
541
- describe "Database#valid_connection?" do
542
- it "should issue a query to validate the connection" do
543
- db = Sequel.mock
544
- db.synchronize{|c| db.valid_connection?(c)}.must_equal true
545
- db.synchronize do |c|
546
- def c.execute(*) raise Sequel::DatabaseError, "error" end
547
- db.valid_connection?(c)
548
- end.must_equal false
549
- end
550
- end
551
-
552
- describe "Database#run" do
553
- before do
554
- @db = Sequel.mock(:servers=>{:s1=>{}})
555
- end
556
-
557
- it "should execute the code on the database" do
558
- @db.run("DELETE FROM items")
559
- @db.sqls.must_equal ["DELETE FROM items"]
560
- end
561
-
562
- it "should handle placeholder literal strings" do
563
- @db.run(Sequel.lit("DELETE FROM ?", :items))
564
- @db.sqls.must_equal ["DELETE FROM items"]
565
- end
566
-
567
- it "should return nil" do
568
- @db.run("DELETE FROM items").must_equal nil
569
- end
570
-
571
- it "should accept options passed to execute_ddl" do
572
- @db.run("DELETE FROM items", :server=>:s1)
573
- @db.sqls.must_equal ["DELETE FROM items -- s1"]
574
- end
575
- end
576
-
577
- describe "Database#<<" do
578
- before do
579
- @db = Sequel.mock
580
- end
581
-
582
- it "should execute the code on the database" do
583
- @db << "DELETE FROM items"
584
- @db.sqls.must_equal ["DELETE FROM items"]
585
- end
586
-
587
- it "should handle placeholder literal strings" do
588
- @db << Sequel.lit("DELETE FROM ?", :items)
589
- @db.sqls.must_equal ["DELETE FROM items"]
590
- end
591
-
592
- it "should be chainable" do
593
- @db << "DELETE FROM items" << "DELETE FROM items2"
594
- @db.sqls.must_equal ["DELETE FROM items", "DELETE FROM items2"]
595
- end
596
- end
597
-
598
- describe "Database#synchronize" do
599
- before do
600
- @db = Sequel::Database.new(:max_connections => 1)
601
- meta_def(@db, :connect){|c| 12345}
602
- end
603
-
604
- it "should wrap the supplied block in pool.hold" do
605
- q, q1, q2 = Queue.new, Queue.new, Queue.new
606
- c1, c2 = nil
607
- t1 = Thread.new{@db.synchronize{|c| c1 = c; q.push nil; q1.pop}; q.push nil}
608
- q.pop
609
- c1.must_equal 12345
610
- t2 = Thread.new{@db.synchronize{|c| c2 = c; q2.push nil}}
611
- @db.pool.available_connections.must_be :empty?
612
- c2.must_equal nil
613
- q1.push nil
614
- q.pop
615
- q2.pop
616
- c2.must_equal 12345
617
- t1.join
618
- t2.join
619
- end
620
- end
621
-
622
- describe "Database#test_connection" do
623
- before do
624
- @db = Sequel::Database.new
625
- pr = proc{@test = rand(100)}
626
- meta_def(@db, :connect){|c| pr.call}
627
- end
628
-
629
- it "should attempt to get a connection" do
630
- @db.test_connection
631
- @test.wont_equal nil
632
- end
633
-
634
- it "should return true if successful" do
635
- @db.test_connection.must_equal true
636
- end
637
-
638
- it "should raise an error if the attempting to connect raises an error" do
639
- def @db.connect(*) raise Sequel::Error end
640
- proc{@db.test_connection}.must_raise(Sequel::DatabaseConnectionError)
641
- end
642
- end
643
-
644
- describe "Database#table_exists?" do
645
- it "should test existence by selecting a row from the table's dataset" do
646
- db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
647
- db.table_exists?(:a).must_equal false
648
- db.sqls.must_equal ["SELECT NULL AS nil FROM a LIMIT 1"]
649
- db.table_exists?(:b).must_equal true
650
- db.table_exists?(:c).must_equal true
651
- end
652
-
653
- it "should use a savepoint if inside a transaction" do
654
- db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
655
- def db.supports_savepoints?; true end
656
- db.transaction do
657
- db.table_exists?(:a).must_equal false
658
- end
659
- db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SELECT NULL AS nil FROM a LIMIT 1", "ROLLBACK TO SAVEPOINT autopoint_1", "COMMIT"]
660
- db.table_exists?(:b).must_equal true
661
- db.table_exists?(:c).must_equal true
662
- end
663
- end
664
-
665
- DatabaseTransactionSpecs = shared_description do
666
- it "should wrap the supplied block with BEGIN + COMMIT statements" do
667
- @db.transaction{@db.execute 'DROP TABLE test;'}
668
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
669
- end
670
-
671
- it "should support transaction isolation levels" do
672
- meta_def(@db, :supports_transaction_isolation_levels?){true}
673
- [:uncommitted, :committed, :repeatable, :serializable].each do |l|
674
- @db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
675
- end
676
- @db.sqls.must_equal ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
677
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
678
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
679
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
680
- end
681
-
682
- it "should allow specifying a default transaction isolation level" do
683
- meta_def(@db, :supports_transaction_isolation_levels?){true}
684
- [:uncommitted, :committed, :repeatable, :serializable].each do |l|
685
- @db.transaction_isolation_level = l
686
- @db.transaction{@db.run "DROP TABLE #{l}"}
687
- end
688
- @db.sqls.must_equal ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
689
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
690
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
691
- 'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
692
- end
693
-
694
- it "should support :retry_on option for automatically retrying transactions" do
695
- a = []
696
- @db.transaction(:retry_on=>Sequel::DatabaseDisconnectError){a << 1; raise Sequel::DatabaseDisconnectError if a.length < 2}
697
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'BEGIN', 'COMMIT']
698
- a.must_equal [1, 1]
699
-
700
- a = []
701
- @db.transaction(:retry_on=>[Sequel::ConstraintViolation, Sequel::SerializationFailure]) do
702
- a << 1
703
- raise Sequel::SerializationFailure if a.length == 1
704
- raise Sequel::ConstraintViolation if a.length == 2
705
- end
706
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'BEGIN', 'ROLLBACK', 'BEGIN', 'COMMIT']
707
- a.must_equal [1, 1, 1]
708
- end
709
-
710
- it "should support :num_retries option for limiting the number of retry times" do
711
- a = []
712
- lambda do
713
- @db.transaction(:num_retries=>1, :retry_on=>[Sequel::ConstraintViolation, Sequel::SerializationFailure]) do
714
- a << 1
715
- raise Sequel::SerializationFailure if a.length == 1
716
- raise Sequel::ConstraintViolation if a.length == 2
717
- end
718
- end.must_raise(Sequel::ConstraintViolation)
719
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'BEGIN', 'ROLLBACK']
720
- a.must_equal [1, 1]
721
- end
722
-
723
- it "should support :num_retries=>nil option to retry indefinitely" do
724
- a = []
725
- lambda do
726
- @db.transaction(:num_retries=>nil, :retry_on=>[Sequel::ConstraintViolation]) do
727
- a << 1
728
- raise Sequel::SerializationFailure if a.length >= 100
729
- raise Sequel::ConstraintViolation
730
- end
731
- end.must_raise(Sequel::SerializationFailure)
732
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK'] * 100
733
- a.must_equal [1] * 100
734
- end
735
-
736
- it "should support :before_retry option for invoking callback before retrying" do
737
- a, errs, calls = [], [], []
738
- retryer = proc{|n, err| calls << n; errs << err }
739
- @db.transaction(:retry_on=>Sequel::DatabaseDisconnectError, :before_retry => retryer) do
740
- a << 1; raise Sequel::DatabaseDisconnectError if a.length < 3
741
- end
742
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'BEGIN', 'ROLLBACK', 'BEGIN', 'COMMIT']
743
- a.must_equal [1, 1, 1]
744
- errs.count.must_equal 2
745
- errs.each { |e| e.class.must_equal Sequel::DatabaseDisconnectError }
746
- calls.must_equal [1, 2]
747
- end
748
-
749
- it "should raise an error if attempting to use :retry_on inside another transaction" do
750
- proc{@db.transaction{@db.transaction(:retry_on=>Sequel::ConstraintViolation){}}}.must_raise(Sequel::Error)
751
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
752
- end
753
-
754
- it "should handle returning inside of the block by committing" do
755
- def @db.ret_commit
756
- transaction do
757
- execute 'DROP TABLE test;'
758
- return
759
- end
760
- end
761
- @db.ret_commit
762
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
763
- end
764
-
765
- it "should issue ROLLBACK if an exception is raised, and re-raise" do
766
- @db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
767
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
768
-
769
- proc {@db.transaction {raise RuntimeError}}.must_raise(RuntimeError)
770
- end
771
-
772
- it "should handle errors when sending BEGIN" do
773
- ec = Class.new(StandardError)
774
- meta_def(@db, :database_error_classes){[ec]}
775
- meta_def(@db, :log_connection_execute){|c, sql| sql =~ /BEGIN/ ? raise(ec, 'bad') : super(c, sql)}
776
- begin
777
- @db.transaction{@db.execute 'DROP TABLE test;'}
778
- rescue Sequel::DatabaseError => e
779
- end
780
- e.wont_equal nil
781
- e.wrapped_exception.must_be_kind_of(ec)
782
- @db.sqls.must_equal ['ROLLBACK']
783
- end
784
-
785
- it "should handle errors when sending COMMIT" do
786
- ec = Class.new(StandardError)
787
- meta_def(@db, :database_error_classes){[ec]}
788
- meta_def(@db, :log_connection_execute){|c, sql| sql =~ /COMMIT/ ? raise(ec, 'bad') : super(c, sql)}
789
- begin
790
- @db.transaction{@db.execute 'DROP TABLE test;'}
791
- rescue Sequel::DatabaseError => e
792
- end
793
- e.wont_equal nil
794
- e.wrapped_exception.must_be_kind_of(ec)
795
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'ROLLBACK']
796
- end
797
-
798
- it "should raise original exception if there is an exception raised when rolling back" do
799
- ec = Class.new(StandardError)
800
- meta_def(@db, :database_error_classes){[ec]}
801
- meta_def(@db, :log_connection_execute){|c, sql| sql =~ /ROLLBACK/ ? raise(ec, 'bad') : super(c, sql)}
802
- begin
803
- @db.transaction{raise ArgumentError, 'asdf'}
804
- rescue => e
805
- end
806
- e.must_be_kind_of(ArgumentError)
807
- @db.sqls.must_equal ['BEGIN']
808
- end
809
-
810
- it "should issue ROLLBACK if Sequel::Rollback is called in the transaction" do
811
- @db.transaction do
812
- @db.drop_table(:a)
813
- raise Sequel::Rollback
814
- @db.drop_table(:b)
815
- end
816
-
817
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
818
- end
819
-
820
- it "should have in_transaction? return true if inside a transaction" do
821
- c = nil
822
- @db.transaction{c = @db.in_transaction?}
823
- c.must_equal true
824
- end
825
-
826
- it "should have in_transaction? handle sharding correctly" do
827
- c = []
828
- @db.transaction(:server=>:test){c << @db.in_transaction?}
829
- @db.transaction(:server=>:test){c << @db.in_transaction?(:server=>:test)}
830
- c.must_equal [false, true]
831
- end
832
-
833
- it "should have in_transaction? return false if not in a transaction" do
834
- @db.in_transaction?.must_equal false
835
- end
836
-
837
- it "should return nil if Sequel::Rollback is called in the transaction" do
838
- @db.transaction{raise Sequel::Rollback}.must_equal nil
839
- end
840
-
841
- it "should reraise Sequel::Rollback errors when using :rollback=>:reraise option is given" do
842
- proc {@db.transaction(:rollback=>:reraise){raise Sequel::Rollback}}.must_raise(Sequel::Rollback)
843
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
844
- proc {@db.transaction(:rollback=>:reraise){raise ArgumentError}}.must_raise(ArgumentError)
845
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
846
- @db.transaction(:rollback=>:reraise){1}.must_equal 1
847
- @db.sqls.must_equal ['BEGIN', 'COMMIT']
848
- end
849
-
850
- it "should always rollback if :rollback=>:always option is given" do
851
- proc {@db.transaction(:rollback=>:always){raise ArgumentError}}.must_raise(ArgumentError)
852
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
853
- @db.transaction(:rollback=>:always){raise Sequel::Rollback}.must_equal nil
854
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
855
- @db.transaction(:rollback=>:always){1}.must_equal 1
856
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
857
- catch(:foo) do
858
- @db.transaction(:rollback=>:always){throw :foo}
859
- end
860
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
861
- end
862
-
863
- it "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
864
- meta_def(@db, :commit_transaction){raise ArgumentError}
865
- lambda{@db.transaction{}}.must_raise(ArgumentError)
866
-
867
- meta_def(@db, :database_error_classes){[ArgumentError]}
868
- lambda{@db.transaction{}}.must_raise(Sequel::DatabaseError)
869
- end
870
-
871
- it "should be re-entrant" do
872
- q, q1 = Queue.new, Queue.new
873
- cc = nil
874
- t = Thread.new do
875
- @db.transaction {@db.transaction {@db.transaction {|c|
876
- cc = c
877
- q.pop
878
- q1.push nil
879
- q.pop
880
- }}}
881
- end
882
- q.push nil
883
- q1.pop
884
- cc.must_be_kind_of(Sequel::Mock::Connection)
885
- tr = @db.instance_variable_get(:@transactions)
886
- tr.keys.must_equal [cc]
887
- q.push nil
888
- t.join
889
- tr.must_be :empty?
890
- end
891
-
892
- it "should correctly handle nested transacation use with separate shards" do
893
- @db.transaction do |c1|
894
- @db.transaction(:server=>:test) do |c2|
895
- c1.wont_equal c2
896
- @db.execute 'DROP TABLE test;'
897
- end
898
- end
899
- @db.sqls.must_equal ['BEGIN', 'BEGIN -- test', 'DROP TABLE test;', 'COMMIT -- test', 'COMMIT']
900
- end
901
-
902
- if (!defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby') and !RUBY_VERSION.start_with?('1.9')
903
- it "should handle Thread#kill for transactions inside threads" do
904
- q = Queue.new
905
- q1 = Queue.new
906
- t = Thread.new do
907
- @db.transaction do
908
- @db.execute 'DROP TABLE test'
909
- q1.push nil
910
- q.pop
911
- @db.execute 'DROP TABLE test2'
912
- end
913
- end
914
- q1.pop
915
- t.kill
916
- t.join
917
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
918
- end
919
- end
920
-
921
- it "should raise an Error if after_commit or after_rollback is called without a block" do
922
- proc{@db.after_commit}.must_raise(Sequel::Error)
923
- proc{@db.after_rollback}.must_raise(Sequel::Error)
924
- end
925
-
926
- it "should have after_commit and after_rollback respect :server option" do
927
- @db.transaction(:server=>:test){@db.after_commit(:server=>:test){@db.execute('foo', :server=>:test)}}
928
- @db.sqls.must_equal ['BEGIN -- test', 'COMMIT -- test', 'foo -- test']
929
- @db.transaction(:server=>:test){@db.after_rollback(:server=>:test){@db.execute('foo', :server=>:test)}; raise Sequel::Rollback}
930
- @db.sqls.must_equal ['BEGIN -- test', 'ROLLBACK -- test', 'foo -- test']
931
- end
932
-
933
- it "should execute after_commit outside transactions" do
934
- @db.after_commit{@db.execute('foo')}
935
- @db.sqls.must_equal ['foo']
936
- end
937
-
938
- it "should ignore after_rollback outside transactions" do
939
- @db.after_rollback{@db.execute('foo')}
940
- @db.sqls.must_equal []
941
- end
942
-
943
- it "should support after_commit inside transactions" do
944
- @db.transaction{@db.after_commit{@db.execute('foo')}}
945
- @db.sqls.must_equal ['BEGIN', 'COMMIT', 'foo']
946
- end
947
-
948
- it "should support after_rollback inside transactions" do
949
- @db.transaction{@db.after_rollback{@db.execute('foo')}}
950
- @db.sqls.must_equal ['BEGIN', 'COMMIT']
951
- end
952
-
953
- it "should have transaction inside after_commit work correctly" do
954
- @db.transaction{@db.after_commit{@db.transaction{@db.execute('foo')}}}
955
- @db.sqls.must_equal ['BEGIN', 'COMMIT', 'BEGIN', 'foo', 'COMMIT']
956
- end
957
-
958
- it "should have transaction inside after_rollback work correctly" do
959
- @db.transaction(:rollback=>:always){@db.after_rollback{@db.transaction{@db.execute('foo')}}}
960
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'BEGIN', 'foo', 'COMMIT']
961
- end
962
-
963
- it "should not call after_commit if the transaction rolls back" do
964
- @db.transaction{@db.after_commit{@db.execute('foo')}; raise Sequel::Rollback}
965
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
966
- end
967
-
968
- it "should call after_rollback if the transaction rolls back" do
969
- @db.transaction{@db.after_rollback{@db.execute('foo')}; raise Sequel::Rollback}
970
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'foo']
971
- end
972
-
973
- it "should call multiple after_commit blocks in order if called inside transactions" do
974
- @db.transaction{@db.after_commit{@db.execute('foo')}; @db.after_commit{@db.execute('bar')}}
975
- @db.sqls.must_equal ['BEGIN', 'COMMIT', 'foo', 'bar']
976
- end
977
-
978
- it "should call multiple after_rollback blocks in order if called inside transactions" do
979
- @db.transaction{@db.after_rollback{@db.execute('foo')}; @db.after_rollback{@db.execute('bar')}; raise Sequel::Rollback}
980
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'foo', 'bar']
981
- end
982
-
983
- it "should support after_commit inside nested transactions" do
984
- @db.transaction{@db.transaction{@db.after_commit{@db.execute('foo')}}}
985
- @db.sqls.must_equal ['BEGIN', 'COMMIT', 'foo']
986
- end
987
-
988
- it "should support after_rollback inside nested transactions" do
989
- @db.transaction{@db.transaction{@db.after_rollback{@db.execute('foo')}}; raise Sequel::Rollback}
990
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK', 'foo']
991
- end
992
-
993
- it "should raise an error if you attempt to use after_commit inside a prepared transaction" do
994
- meta_def(@db, :supports_prepared_transactions?){true}
995
- proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{@db.execute('foo')}}}.must_raise(Sequel::Error)
996
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
997
- end
998
-
999
- it "should raise an error if you attempt to use after_rollback inside a prepared transaction" do
1000
- meta_def(@db, :supports_prepared_transactions?){true}
1001
- proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{@db.execute('foo')}}}.must_raise(Sequel::Error)
1002
- @db.sqls.must_equal ['BEGIN', 'ROLLBACK']
1003
- end
1004
- end
1005
-
1006
- describe "Database#transaction with savepoint support" do
1007
- before do
1008
- @db = Sequel.mock(:servers=>{:test=>{}})
1009
- end
1010
-
1011
- include DatabaseTransactionSpecs
1012
-
1013
- it "should support :retry_on option for automatically retrying transactions when using :savepoint option" do
1014
- a = []
1015
- @db.transaction do
1016
- @db.transaction(:retry_on=>Sequel::SerializationFailure, :savepoint=>true) do
1017
- a << 1
1018
- raise Sequel::SerializationFailure if a.length == 1
1019
- end
1020
- end
1021
- @db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "ROLLBACK TO SAVEPOINT autopoint_1", "SAVEPOINT autopoint_1", "RELEASE SAVEPOINT autopoint_1", "COMMIT"]
1022
- a.must_equal [1, 1]
1023
- end
1024
-
1025
- it "should automatically use a savepoint if :rollback=>:always given inside a transaction" do
1026
- @db.transaction do
1027
- @db.transaction(:rollback=>:always) do
1028
- @db.get(1)
1029
- end
1030
- end
1031
- @db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SELECT 1 AS v LIMIT 1", "ROLLBACK TO SAVEPOINT autopoint_1", "COMMIT"]
1032
- end
1033
-
1034
- it "should support :retry_on option for automatically retrying transactions inside an :auto_savepoint transaction" do
1035
- a = []
1036
- @db.transaction(:auto_savepoint=>true) do
1037
- @db.transaction(:retry_on=>Sequel::SerializationFailure) do
1038
- a << 1
1039
- raise Sequel::SerializationFailure if a.length == 1
1040
- end
1041
- end
1042
- @db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "ROLLBACK TO SAVEPOINT autopoint_1", "SAVEPOINT autopoint_1", "RELEASE SAVEPOINT autopoint_1", "COMMIT"]
1043
- a.must_equal [1, 1]
1044
- end
1045
-
1046
- it "should support after_commit inside savepoints" do
1047
- @db.transaction do
1048
- @db.after_commit{@db.execute('foo')}
1049
- @db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
1050
- @db.after_commit{@db.execute('baz')}
1051
- end
1052
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT', 'foo', 'bar', 'baz']
1053
- end
1054
-
1055
- it "should support after_rollback inside savepoints" do
1056
- @db.transaction do
1057
- @db.after_rollback{@db.execute('foo')}
1058
- @db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
1059
- @db.after_rollback{@db.execute('baz')}
1060
- raise Sequel::Rollback
1061
- end
1062
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
1063
- end
1064
-
1065
- it "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
1066
- meta_def(@db, :supports_prepared_transactions?){true}
1067
- proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.must_raise(Sequel::Error)
1068
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
1069
- end
1070
-
1071
- it "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
1072
- meta_def(@db, :supports_prepared_transactions?){true}
1073
- proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.must_raise(Sequel::Error)
1074
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
1075
- end
1076
-
1077
- it "should create savepoint if inside a transaction when :savepoint=>:only is used" do
1078
- @db.transaction{@db.transaction(:savepoint=>:only){}}
1079
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1','RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1080
- end
1081
-
1082
- it "should not create transaction if not inside a transaction when :savepoint=>:only is used" do
1083
- @db.transaction(:savepoint=>:only){}
1084
- @db.sqls.must_equal []
1085
- end
1086
- end
1087
-
1088
- describe "Database#transaction without savepoint support" do
1089
- before do
1090
- @db = Sequel.mock(:servers=>{:test=>{}})
1091
- meta_def(@db, :supports_savepoints?){false}
1092
- end
1093
-
1094
- it "should not create savepoint if inside a transaction when :savepoint=>:only is used" do
1095
- @db.transaction{@db.transaction(:savepoint=>:only){}}
1096
- @db.sqls.must_equal ['BEGIN', 'COMMIT']
1097
- end
1098
-
1099
- it "should automatically use a savepoint if :rollback=>:always given inside a transaction" do
1100
- proc do
1101
- @db.transaction do
1102
- @db.transaction(:rollback=>:always) do
1103
- @db.get(1)
1104
- end
1105
- end
1106
- end.must_raise Sequel::Error
1107
- @db.sqls.must_equal ["BEGIN", "ROLLBACK"]
1108
- end
1109
-
1110
- include DatabaseTransactionSpecs
1111
- end
1112
-
1113
- describe "Sequel.transaction" do
1114
- before do
1115
- @sqls = []
1116
- @db1 = Sequel.mock(:append=>'1', :sqls=>@sqls)
1117
- @db2 = Sequel.mock(:append=>'2', :sqls=>@sqls)
1118
- @db3 = Sequel.mock(:append=>'3', :sqls=>@sqls)
1119
- end
1120
-
1121
- it "should run the block inside transacitons on all three databases" do
1122
- Sequel.transaction([@db1, @db2, @db3]){1}.must_equal 1
1123
- @sqls.must_equal ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
1124
- end
1125
-
1126
- it "should pass options to all the blocks" do
1127
- Sequel.transaction([@db1, @db2, @db3], :rollback=>:always){1}.must_equal 1
1128
- @sqls.must_equal ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
1129
- end
1130
-
1131
- it "should handle Sequel::Rollback exceptions raised by the block to rollback on all databases" do
1132
- Sequel.transaction([@db1, @db2, @db3]){raise Sequel::Rollback}.must_equal nil
1133
- @sqls.must_equal ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
1134
- end
1135
-
1136
- it "should handle nested transactions" do
1137
- Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3]){1}}.must_equal 1
1138
- @sqls.must_equal ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
1139
- end
1140
-
1141
- it "should handle savepoints" do
1142
- Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3], :savepoint=>true){1}}.must_equal 1
1143
- @sqls.must_equal ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3',
1144
- 'SAVEPOINT autopoint_1 -- 1', 'SAVEPOINT autopoint_1 -- 2', 'SAVEPOINT autopoint_1 -- 3',
1145
- 'RELEASE SAVEPOINT autopoint_1 -- 3', 'RELEASE SAVEPOINT autopoint_1 -- 2', 'RELEASE SAVEPOINT autopoint_1 -- 1',
1146
- 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
1147
- end
1148
- end
1149
-
1150
- describe "Database#transaction with savepoints" do
1151
- before do
1152
- @db = Sequel.mock
1153
- end
1154
-
1155
- it "should wrap the supplied block with BEGIN + COMMIT statements" do
1156
- @db.transaction {@db.execute 'DROP TABLE test;'}
1157
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1158
- end
1159
-
1160
- it "should use savepoints if given the :savepoint option" do
1161
- @db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}}
1162
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1163
- end
1164
-
1165
- it "should use savepoints if surrounding transaction uses :auto_savepoint option" do
1166
- @db.transaction(:auto_savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}
1167
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1168
-
1169
- @db.transaction(:auto_savepoint=>true){@db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}}
1170
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1171
-
1172
- @db.transaction(:auto_savepoint=>true){@db.transaction(:auto_savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}}
1173
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'SAVEPOINT autopoint_2', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_2', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1174
-
1175
- @db.transaction{@db.transaction(:auto_savepoint=>true, :savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}}
1176
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'SAVEPOINT autopoint_2', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_2', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1177
- end
1178
-
1179
- it "should not use savepoints if surrounding transaction uses :auto_savepoint and current transaction uses :savepoint=>false option" do
1180
- @db.transaction(:auto_savepoint=>true){@db.transaction(:savepoint=>false){@db.execute 'DROP TABLE test;'}}
1181
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1182
- end
1183
-
1184
- it "should not use a savepoint if no transaction is in progress" do
1185
- @db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
1186
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1187
- end
1188
-
1189
- it "should reuse the current transaction if no :savepoint option is given" do
1190
- @db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}
1191
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1192
- end
1193
-
1194
- it "should handle returning inside of the block by committing" do
1195
- def @db.ret_commit
1196
- transaction do
1197
- execute 'DROP TABLE test;'
1198
- return
1199
- end
1200
- end
1201
- @db.ret_commit
1202
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test;', 'COMMIT']
1203
- end
1204
-
1205
- it "should handle returning inside of a savepoint by committing" do
1206
- def @db.ret_commit
1207
- transaction do
1208
- transaction(:savepoint=>true) do
1209
- execute 'DROP TABLE test;'
1210
- return
1211
- end
1212
- end
1213
- end
1214
- @db.ret_commit
1215
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
1216
- end
1217
-
1218
- it "should issue ROLLBACK if an exception is raised, and re-raise" do
1219
- @db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
1220
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
1221
-
1222
- proc {@db.transaction {raise RuntimeError}}.must_raise(RuntimeError)
1223
- end
1224
-
1225
- it "should issue ROLLBACK SAVEPOINT if an exception is raised inside a savepoint, and re-raise" do
1226
- @db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test'; raise RuntimeError}} rescue nil
1227
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test', 'ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
1228
-
1229
- proc {@db.transaction {raise RuntimeError}}.must_raise(RuntimeError)
1230
- end
1231
-
1232
- it "should issue ROLLBACK if Sequel::Rollback is raised in the transaction" do
1233
- @db.transaction do
1234
- @db.drop_table(:a)
1235
- raise Sequel::Rollback
1236
- @db.drop_table(:b)
1237
- end
1238
-
1239
- @db.sqls.must_equal ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
1240
- end
1241
-
1242
- it "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is raised in a savepoint" do
1243
- @db.transaction do
1244
- @db.transaction(:savepoint=>true) do
1245
- @db.drop_table(:a)
1246
- raise Sequel::Rollback
1247
- end
1248
- @db.drop_table(:b)
1249
- end
1250
-
1251
- @db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'DROP TABLE b', 'COMMIT']
1252
- end
1253
-
1254
- it "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
1255
- meta_def(@db, :commit_transaction){raise ArgumentError}
1256
- lambda{@db.transaction{}}.must_raise(ArgumentError)
1257
- lambda{@db.transaction{@db.transaction(:savepoint=>true){}}}.must_raise(ArgumentError)
1258
-
1259
- meta_def(@db, :database_error_classes){[ArgumentError]}
1260
- lambda{@db.transaction{}}.must_raise(Sequel::DatabaseError)
1261
- lambda{@db.transaction{@db.transaction(:savepoint=>true){}}}.must_raise(Sequel::DatabaseError)
1262
- end
1263
- end
1264
-
1265
- describe "A Database adapter with a scheme" do
1266
- before do
1267
- require 'sequel/adapters/mock'
1268
- @ccc = Class.new(Sequel::Mock::Database)
1269
- @ccc.send(:set_adapter_scheme, :ccc)
1270
- end
1271
-
1272
- it "should be registered in the ADAPTER_MAP" do
1273
- Sequel::ADAPTER_MAP[:ccc].must_equal @ccc
1274
- end
1275
-
1276
- it "should give the database_type as the adapter scheme by default" do
1277
- @ccc.new.database_type.must_equal :ccc
1278
- end
1279
-
1280
- it "should be instantiated when its scheme is specified" do
1281
- c = Sequel::Database.connect('ccc://localhost/db')
1282
- c.must_be_kind_of(@ccc)
1283
- c.opts[:host].must_equal 'localhost'
1284
- c.opts[:database].must_equal 'db'
1285
- end
1286
-
1287
- it "should be accessible through Sequel.connect" do
1288
- c = Sequel.connect 'ccc://localhost/db'
1289
- c.must_be_kind_of(@ccc)
1290
- c.opts[:host].must_equal 'localhost'
1291
- c.opts[:database].must_equal 'db'
1292
- end
1293
-
1294
- it "should be accessible through Sequel.connect via a block" do
1295
- x = nil
1296
- y = nil
1297
- z = nil
1298
- returnValue = 'anything'
1299
-
1300
- p = proc do |c|
1301
- c.must_be_kind_of(@ccc)
1302
- c.opts[:host].must_equal 'localhost'
1303
- c.opts[:database].must_equal 'db'
1304
- z = y
1305
- y = x
1306
- x = c
1307
- returnValue
1308
- end
1309
-
1310
- @ccc.class_eval do
1311
- self::DISCONNECTS = []
1312
- def disconnect
1313
- self.class::DISCONNECTS << self
1314
- end
1315
- end
1316
- Sequel::Database.connect('ccc://localhost/db', &p).must_equal returnValue
1317
- @ccc::DISCONNECTS.must_equal [x]
1318
-
1319
- Sequel.connect('ccc://localhost/db', &p).must_equal returnValue
1320
- @ccc::DISCONNECTS.must_equal [y, x]
1321
-
1322
- Sequel.send(:def_adapter_method, :ccc)
1323
- Sequel.ccc('db', :host=>'localhost', &p).must_equal returnValue
1324
- @ccc::DISCONNECTS.must_equal [z, y, x]
1325
- class << Sequel; remove_method(:ccc) end
1326
- end
1327
-
1328
- it "should be accessible through Sequel.<adapter>" do
1329
- Sequel.send(:def_adapter_method, :ccc)
1330
-
1331
- # invalid parameters
1332
- proc {Sequel.ccc('abc', 'def')}.must_raise(Sequel::Error)
1333
- proc {Sequel.ccc(1)}.must_raise(Sequel::Error)
1334
-
1335
- c = Sequel.ccc('mydb')
1336
- c.must_be_kind_of(@ccc)
1337
- c.opts.values_at(:adapter, :database, :adapter_class).must_equal [:ccc, 'mydb', @ccc]
1338
-
1339
- c = Sequel.ccc('mydb', :host => 'localhost')
1340
- c.must_be_kind_of(@ccc)
1341
- c.opts.values_at(:adapter, :database, :host, :adapter_class).must_equal [:ccc, 'mydb', 'localhost', @ccc]
1342
-
1343
- c = Sequel.ccc
1344
- c.must_be_kind_of(@ccc)
1345
- c.opts.values_at(:adapter, :adapter_class).must_equal [:ccc, @ccc]
1346
-
1347
- c = Sequel.ccc(:database => 'mydb', :host => 'localhost')
1348
- c.must_be_kind_of(@ccc)
1349
- c.opts.values_at(:adapter, :database, :host, :adapter_class).must_equal [:ccc, 'mydb', 'localhost', @ccc]
1350
- class << Sequel; remove_method(:ccc) end
1351
- end
1352
-
1353
- it "should be accessible through Sequel.connect with options" do
1354
- c = Sequel.connect(:adapter => :ccc, :database => 'mydb')
1355
- c.must_be_kind_of(@ccc)
1356
- c.opts[:adapter].must_equal :ccc
1357
- end
1358
-
1359
- it "should be accessible through Sequel.connect with URL parameters" do
1360
- c = Sequel.connect 'ccc:///db?host=/tmp&user=test'
1361
- c.must_be_kind_of(@ccc)
1362
- c.opts[:host].must_equal '/tmp'
1363
- c.opts[:database].must_equal 'db'
1364
- c.opts[:user].must_equal 'test'
1365
- end
1366
-
1367
- it "should have URL parameters take precedence over fixed URL parts" do
1368
- c = Sequel.connect 'ccc://localhost/db?host=a&database=b'
1369
- c.must_be_kind_of(@ccc)
1370
- c.opts[:host].must_equal 'a'
1371
- c.opts[:database].must_equal 'b'
1372
- end
1373
-
1374
- it "should have hash options take predence over URL parameters or parts" do
1375
- c = Sequel.connect 'ccc://localhost/db?host=/tmp', :host=>'a', :database=>'b', :user=>'c'
1376
- c.must_be_kind_of(@ccc)
1377
- c.opts[:host].must_equal 'a'
1378
- c.opts[:database].must_equal 'b'
1379
- c.opts[:user].must_equal 'c'
1380
- end
1381
-
1382
- it "should unescape values of URL parameters and parts" do
1383
- c = Sequel.connect 'ccc:///d%5bb%5d?host=domain%5cinstance'
1384
- c.must_be_kind_of(@ccc)
1385
- c.opts[:database].must_equal 'd[b]'
1386
- c.opts[:host].must_equal 'domain\\instance'
1387
- end
1388
-
1389
- it "should test the connection if test parameter is truthy" do
1390
- @ccc.send(:define_method, :connect){}
1391
- proc{Sequel.connect 'ccc:///d%5bb%5d?test=t'}.must_raise(Sequel::DatabaseConnectionError)
1392
- proc{Sequel.connect 'ccc:///d%5bb%5d?test=1'}.must_raise(Sequel::DatabaseConnectionError)
1393
- proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>true}.must_raise(Sequel::DatabaseConnectionError)
1394
- proc{Sequel.connect 'ccc:///d%5bb%5d', :test=>'t'}.must_raise(Sequel::DatabaseConnectionError)
1395
- end
1396
-
1397
- it "should not test the connection if test parameter is not truthy" do
1398
- Sequel.connect 'ccc:///d%5bb%5d?test=f'
1399
- Sequel.connect 'ccc:///d%5bb%5d?test=0'
1400
- Sequel.connect 'ccc:///d%5bb%5d', :test=>false
1401
- Sequel.connect 'ccc:///d%5bb%5d', :test=>'f'
1402
- end
1403
- end
1404
-
1405
- describe "Sequel::Database.connect" do
1406
- it "should raise an Error if not given a String or Hash" do
1407
- proc{Sequel::Database.connect(nil)}.must_raise(Sequel::Error)
1408
- proc{Sequel::Database.connect(Object.new)}.must_raise(Sequel::Error)
1409
- end
1410
- end
1411
-
1412
- describe "An unknown database scheme" do
1413
- it "should raise an error in Sequel::Database.connect" do
1414
- proc {Sequel::Database.connect('ddd://localhost/db')}.must_raise(Sequel::AdapterNotFound)
1415
- end
1416
-
1417
- it "should raise an error in Sequel.connect" do
1418
- proc {Sequel.connect('ddd://localhost/db')}.must_raise(Sequel::AdapterNotFound)
1419
- end
1420
- end
1421
-
1422
- describe "A broken adapter (lib is there but the class is not)" do
1423
- before do
1424
- @fn = File.join(File.dirname(__FILE__), '../../lib/sequel/adapters/blah.rb')
1425
- File.open(@fn,'a'){}
1426
- end
1427
-
1428
- after do
1429
- File.delete(@fn)
1430
- end
1431
-
1432
- it "should raise an error" do
1433
- proc {Sequel.connect('blah://blow')}.must_raise(Sequel::AdapterNotFound)
1434
- end
1435
- end
1436
-
1437
- describe "Sequel::Database.load_adapter" do
1438
- it "should not raise an error if subadapter does not exist" do
1439
- Sequel::Database.load_adapter(:foo, :subdir=>'bar').must_equal nil
1440
- end
1441
- end
1442
-
1443
- describe "A single threaded database" do
1444
- after do
1445
- Sequel::Database.single_threaded = false
1446
- end
1447
-
1448
- it "should use a SingleConnectionPool instead of a ConnectionPool" do
1449
- db = Sequel::Database.new(:single_threaded => true){123}
1450
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
1451
- end
1452
-
1453
- it "should be constructable using :single_threaded => true option" do
1454
- db = Sequel::Database.new(:single_threaded => true){123}
1455
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
1456
- end
1457
-
1458
- it "should be constructable using Database.single_threaded = true" do
1459
- Sequel::Database.single_threaded = true
1460
- db = Sequel::Database.new{123}
1461
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
1462
- end
1463
-
1464
- it "should be constructable using Sequel.single_threaded = true" do
1465
- Sequel.single_threaded = true
1466
- db = Sequel::Database.new{123}
1467
- db.pool.must_be_kind_of(Sequel::SingleConnectionPool)
1468
- end
1469
- end
1470
-
1471
- describe "A single threaded database" do
1472
- before do
1473
- conn = 1234567
1474
- @db = Sequel::Database.new(:single_threaded => true)
1475
- meta_def(@db, :connect) do |c|
1476
- conn += 1
1477
- end
1478
- end
1479
-
1480
- it "should invoke connection_proc only once" do
1481
- @db.pool.hold {|c| c.must_equal 1234568}
1482
- @db.pool.hold {|c| c.must_equal 1234568}
1483
- end
1484
-
1485
- it "should disconnect correctly" do
1486
- def @db.disconnect_connection(c); @dc = c end
1487
- def @db.dc; @dc end
1488
- x = nil
1489
- @db.pool.hold{|c| x = c}
1490
- @db.pool.hold{|c| c.must_equal x}
1491
- @db.disconnect
1492
- @db.dc.must_equal x
1493
- end
1494
-
1495
- it "should convert an Exception on connection into a DatabaseConnectionError" do
1496
- db = Sequel::Database.new(:single_threaded => true, :servers=>{})
1497
- def db.connect(*) raise Exception end
1498
- proc {db.pool.hold {|c|}}.must_raise(Sequel::DatabaseConnectionError)
1499
- end
1500
-
1501
- it "should raise a DatabaseConnectionError if the connection proc returns nil" do
1502
- db = Sequel.mock(:single_threaded => true, :servers=>{})
1503
- def db.connect(*) end
1504
- proc {db.pool.hold {|c|}}.must_raise(Sequel::DatabaseConnectionError)
1505
- end
1506
- end
1507
-
1508
- describe "A database" do
1509
- after do
1510
- Sequel::Database.single_threaded = false
1511
- end
1512
-
1513
- it "should have single_threaded? respond to true if in single threaded mode" do
1514
- db = Sequel::Database.new(:single_threaded => true){1234}
1515
- db.must_be :single_threaded?
1516
-
1517
- db = Sequel::Database.new(:max_options => 1)
1518
- db.wont_be :single_threaded?
1519
-
1520
- db = Sequel::Database.new
1521
- db.wont_be :single_threaded?
1522
-
1523
- Sequel::Database.single_threaded = true
1524
-
1525
- db = Sequel::Database.new{123}
1526
- db.must_be :single_threaded?
1527
-
1528
- db = Sequel::Database.new(:max_options => 4){123}
1529
- db.must_be :single_threaded?
1530
- end
1531
-
1532
- it "should be able to set loggers via the logger= and loggers= methods" do
1533
- db = Sequel::Database.new
1534
- s = "I'm a logger"
1535
- db.logger = s
1536
- db.loggers.must_equal [s]
1537
- db.logger = nil
1538
- db.loggers.must_equal []
1539
-
1540
- db.loggers = [s]
1541
- db.loggers.must_equal [s]
1542
- db.loggers = []
1543
- db.loggers.must_equal []
1544
-
1545
- t = "I'm also a logger"
1546
- db.loggers = [s, t]
1547
- db.loggers.must_equal [s,t]
1548
- end
1549
- end
1550
-
1551
- describe "Database#fetch" do
1552
- before do
1553
- @db = Sequel.mock(:fetch=>proc{|sql| {:sql => sql}})
1554
- end
1555
-
1556
- it "should create a dataset and invoke its fetch_rows method with the given sql" do
1557
- sql = nil
1558
- @db.fetch('select * from xyz') {|r| sql = r[:sql]}
1559
- sql.must_equal 'select * from xyz'
1560
- end
1561
-
1562
- it "should format the given sql with any additional arguments" do
1563
- sql = nil
1564
- @db.fetch('select * from xyz where x = ? and y = ?', 15, 'abc') {|r| sql = r[:sql]}
1565
- sql.must_equal "select * from xyz where x = 15 and y = 'abc'"
1566
-
1567
- @db.fetch('select name from table where name = ? or id in ?', 'aman', [3,4,7]) {|r| sql = r[:sql]}
1568
- sql.must_equal "select name from table where name = 'aman' or id in (3, 4, 7)"
1569
- end
1570
-
1571
- it "should format the given sql with named arguments" do
1572
- sql = nil
1573
- @db.fetch('select * from xyz where x = :x and y = :y', :x=>15, :y=>'abc') {|r| sql = r[:sql]}
1574
- sql.must_equal "select * from xyz where x = 15 and y = 'abc'"
1575
- end
1576
-
1577
- it "should return the dataset if no block is given" do
1578
- @db.fetch('select * from xyz').must_be_kind_of(Sequel::Dataset)
1579
-
1580
- @db.fetch('select a from b').map {|r| r[:sql]}.must_equal ['select a from b']
1581
-
1582
- @db.fetch('select c from d').inject([]) {|m, r| m << r; m}.must_equal \
1583
- [{:sql => 'select c from d'}]
1584
- end
1585
-
1586
- it "should return a dataset that always uses the given sql for SELECTs" do
1587
- ds = @db.fetch('select * from xyz')
1588
- ds.select_sql.must_equal 'select * from xyz'
1589
- ds.sql.must_equal 'select * from xyz'
1590
-
1591
- ds.filter!{price.sql_number < 100}
1592
- ds.select_sql.must_equal 'select * from xyz'
1593
- ds.sql.must_equal 'select * from xyz'
1594
- end
1595
- end
1596
-
1597
-
1598
- describe "Database#[]" do
1599
- before do
1600
- @db = Sequel.mock
1601
- end
1602
-
1603
- it "should return a dataset when symbols are given" do
1604
- ds = @db[:items]
1605
- ds.must_be_kind_of(Sequel::Dataset)
1606
- ds.opts[:from].must_equal [:items]
1607
- end
1608
-
1609
- it "should return a dataset when a string is given" do
1610
- @db.fetch = proc{|sql| {:sql=>sql}}
1611
- sql = nil
1612
- @db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
1613
- sql.must_equal "select * from xyz where x = 15 and y = 'abc'"
1614
- end
1615
- end
1616
-
1617
- describe "Database#inspect" do
1618
- it "should include the class name and the connection url" do
1619
- Sequel.connect('mock://foo/bar').inspect.must_equal '#<Sequel::Mock::Database: "mock://foo/bar">'
1620
- end
1621
-
1622
- it "should include the class name and the connection options if an options hash was given" do
1623
- Sequel.connect(:adapter=>:mock).inspect.must_match(/#<Sequel::Mock::Database: \{:adapter=>:mock\}>/)
1624
- end
1625
-
1626
- it "should include the class name, uri, and connection options if uri and options hash was given" do
1627
- Sequel.connect('mock://foo', :database=>'bar').inspect.must_match(/#<Sequel::Mock::Database: "mock:\/\/foo" \{:database=>"bar"\}>/)
1628
- end
1629
- end
1630
-
1631
- describe "Database#get" do
1632
- before do
1633
- @db = Sequel.mock(:fetch=>{:a=>1})
1634
- end
1635
-
1636
- it "should use Dataset#get to get a single value" do
1637
- @db.get(:a).must_equal 1
1638
- @db.sqls.must_equal ['SELECT a LIMIT 1']
1639
-
1640
- @db.get(Sequel.function(:version).as(:version))
1641
- @db.sqls.must_equal ['SELECT version() AS version LIMIT 1']
1642
- end
1643
-
1644
- it "should accept a block" do
1645
- @db.get{a}
1646
- @db.sqls.must_equal ['SELECT a LIMIT 1']
1647
-
1648
- @db.get{version(a).as(version)}
1649
- @db.sqls.must_equal ['SELECT version(a) AS version LIMIT 1']
1650
- end
1651
-
1652
- it "should work when an alias cannot be determined" do
1653
- @db.get(1).must_equal 1
1654
- @db.sqls.must_equal ['SELECT 1 AS v LIMIT 1']
1655
- end
1656
- end
1657
-
1658
- describe "Database#call" do
1659
- it "should call the prepared statement with the given name" do
1660
- db = Sequel.mock(:fetch=>{:id => 1, :x => 1})
1661
- db[:items].prepare(:select, :select_all)
1662
- db.call(:select_all).must_equal [{:id => 1, :x => 1}]
1663
- db[:items].filter(:n=>:$n).prepare(:select, :select_n)
1664
- db.call(:select_n, :n=>1).must_equal [{:id => 1, :x => 1}]
1665
- db.sqls.must_equal ['SELECT * FROM items', 'SELECT * FROM items WHERE (n = 1)']
1666
- end
1667
- end
1668
-
1669
- describe "Database#server_opts" do
1670
- it "should return the general opts if no :servers option is used" do
1671
- opts = {:host=>1, :database=>2}
1672
- Sequel::Database.new(opts).send(:server_opts, :server1)[:host].must_equal 1
1673
- end
1674
-
1675
- it "should return the general opts if entry for the server is present in the :servers option" do
1676
- opts = {:host=>1, :database=>2, :servers=>{}}
1677
- Sequel::Database.new(opts).send(:server_opts, :server1)[:host].must_equal 1
1678
- end
1679
-
1680
- it "should return the general opts merged with the specific opts if given as a hash" do
1681
- opts = {:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}}}
1682
- Sequel::Database.new(opts).send(:server_opts, :server1)[:host].must_equal 3
1683
- end
1684
-
1685
- it "should return the sgeneral opts merged with the specific opts if given as a proc" do
1686
- opts = {:host=>1, :database=>2, :servers=>{:server1=>proc{|db| {:host=>4}}}}
1687
- Sequel::Database.new(opts).send(:server_opts, :server1)[:host].must_equal 4
1688
- end
1689
-
1690
- it "should raise an error if the specific opts is not a proc or hash" do
1691
- opts = {:host=>1, :database=>2, :servers=>{:server1=>2}}
1692
- proc{Sequel::Database.new(opts).send(:server_opts, :server1)}.must_raise(Sequel::Error)
1693
- end
1694
-
1695
- it "should return the general opts merged with given opts if given opts is a Hash" do
1696
- opts = {:host=>1, :database=>2}
1697
- Sequel::Database.new(opts).send(:server_opts, :host=>2)[:host].must_equal 2
1698
- end
1699
- end
1700
-
1701
- describe "Database#add_servers" do
1702
- before do
1703
- @db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
1704
- end
1705
-
1706
- it "should add new servers to the connection pool" do
1707
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1708
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1709
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 1}
1710
-
1711
- @db.add_servers(:server2=>{:host=>6})
1712
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1713
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1714
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 6}
1715
-
1716
- @db.disconnect
1717
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1718
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1719
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 6}
1720
- end
1721
-
1722
- it "should replace options for future connections to existing servers" do
1723
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1724
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1725
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 1}
1726
-
1727
- @db.add_servers(:default=>proc{{:host=>4}}, :server1=>{:host=>8})
1728
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1729
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1730
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 1}
1731
-
1732
- @db.disconnect
1733
- @db.synchronize{|c| c.opts[:host].must_equal 4}
1734
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 8}
1735
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 4}
1736
- end
1737
- end
1738
-
1739
- describe "Database#remove_servers" do
1740
- before do
1741
- @db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
1742
- end
1743
-
1744
- it "should remove servers from the connection pool" do
1745
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1746
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 3}
1747
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 4}
1748
-
1749
- @db.remove_servers(:server1, :server2)
1750
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1751
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 1}
1752
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 1}
1753
- end
1754
-
1755
- it "should accept arrays of symbols" do
1756
- @db.remove_servers([:server1, :server2])
1757
- @db.synchronize{|c| c.opts[:host].must_equal 1}
1758
- @db.synchronize(:server1){|c| c.opts[:host].must_equal 1}
1759
- @db.synchronize(:server2){|c| c.opts[:host].must_equal 1}
1760
- end
1761
-
1762
- it "should allow removal while connections are still open" do
1763
- @db.synchronize do |c1|
1764
- c1.opts[:host].must_equal 1
1765
- @db.synchronize(:server1) do |c2|
1766
- c2.opts[:host].must_equal 3
1767
- @db.synchronize(:server2) do |c3|
1768
- c3.opts[:host].must_equal 4
1769
- @db.remove_servers(:server1, :server2)
1770
- @db.synchronize(:server1) do |c4|
1771
- c4.wont_equal c2
1772
- c4.must_equal c1
1773
- c4.opts[:host].must_equal 1
1774
- @db.synchronize(:server2) do |c5|
1775
- c5.wont_equal c3
1776
- c5.must_equal c1
1777
- c5.opts[:host].must_equal 1
1778
- end
1779
- end
1780
- c3.opts[:host].must_equal 4
1781
- end
1782
- c2.opts[:host].must_equal 3
1783
- end
1784
- c1.opts[:host].must_equal 1
1785
- end
1786
- end
1787
- end
1788
-
1789
- describe "Database#each_server with do/jdbc adapter connection string without :adapter option" do
1790
- it "should yield a separate database object for each server" do
1791
- require 'sequel/adapters/mock'
1792
- klass = Class.new(Sequel::Database)
1793
- def klass.adapter_class(v)
1794
- raise unless v == :jdbc
1795
- Sequel::Mock::Database
1796
- end
1797
- @db = klass.connect('jdbc:blah:', :host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
1798
-
1799
- hosts = []
1800
- @db.each_server do |db|
1801
- db.must_be_kind_of(Sequel::Database)
1802
- db.wont_equal @db
1803
- db.opts[:adapter_class].must_equal Sequel::Mock::Database
1804
- db.opts[:database].must_equal 2
1805
- hosts << db.opts[:host]
1806
- end
1807
- hosts.sort.must_equal [1, 3]
1808
- end
1809
-
1810
- it "should raise if not given a block" do
1811
- proc{Sequel.mock.each_server}.must_raise(Sequel::Error)
1812
- end
1813
- end
1814
-
1815
- describe "Database#each_server" do
1816
- before do
1817
- @db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
1818
- end
1819
-
1820
- it "should yield a separate database object for each server" do
1821
- hosts = []
1822
- @db.each_server do |db|
1823
- db.must_be_kind_of(Sequel::Database)
1824
- db.wont_equal @db
1825
- db.opts[:adapter].must_equal :mock
1826
- db.opts[:database].must_equal 2
1827
- hosts << db.opts[:host]
1828
- end
1829
- hosts.sort.must_equal [1, 3, 4]
1830
- end
1831
-
1832
- it "should disconnect and remove entry from Sequel::DATABASES after use" do
1833
- dbs = []
1834
- dcs = []
1835
- @db.each_server do |db|
1836
- dbs << db
1837
- Sequel::DATABASES.must_include(db)
1838
- meta_def(db, :disconnect){dcs << db}
1839
- end
1840
- dbs.each do |db|
1841
- Sequel::DATABASES.wont_include(db)
1842
- end
1843
- dbs.must_equal dcs
1844
- end
1845
- end
1846
-
1847
- describe "Database#raise_error" do
1848
- before do
1849
- @db = Sequel.mock
1850
- end
1851
-
1852
- it "should reraise if the exception class is not in opts[:classes]" do
1853
- e = Class.new(StandardError)
1854
- proc{@db.send(:raise_error, e.new(''), :classes=>[])}.must_raise(e)
1855
- end
1856
-
1857
- it "should convert the exception to a DatabaseError if the exception class is in opts[:classes]" do
1858
- proc{@db.send(:raise_error, Interrupt.new(''), :classes=>[Interrupt])}.must_raise(Sequel::DatabaseError)
1859
- end
1860
-
1861
- it "should convert the exception to a DatabaseError if opts[:classes] if not present" do
1862
- proc{@db.send(:raise_error, Interrupt.new(''))}.must_raise(Sequel::DatabaseError)
1863
- end
1864
-
1865
- it "should convert the exception to a DatabaseDisconnectError if opts[:disconnect] is true" do
1866
- proc{@db.send(:raise_error, Interrupt.new(''), :disconnect=>true)}.must_raise(Sequel::DatabaseDisconnectError)
1867
- end
1868
-
1869
- it "should convert the exception to an appropriate error if exception message matches regexp" do
1870
- def @db.database_error_regexps
1871
- {/foo/ => Sequel::DatabaseDisconnectError, /bar/ => Sequel::ConstraintViolation}
1872
- end
1873
- proc{@db.send(:raise_error, Interrupt.new('foo'))}.must_raise(Sequel::DatabaseDisconnectError)
1874
- proc{@db.send(:raise_error, Interrupt.new('bar'))}.must_raise(Sequel::ConstraintViolation)
1875
- end
1876
- end
1877
-
1878
- describe "Database#typecast_value" do
1879
- before do
1880
- @db = Sequel::Database.new
1881
- end
1882
-
1883
- it "should raise an InvalidValue when given an invalid value" do
1884
- proc{@db.typecast_value(:integer, "13a")}.must_raise(Sequel::InvalidValue)
1885
- proc{@db.typecast_value(:float, "4.e2")}.must_raise(Sequel::InvalidValue)
1886
- proc{@db.typecast_value(:decimal, :invalid_value)}.must_raise(Sequel::InvalidValue)
1887
- proc{@db.typecast_value(:date, Object.new)}.must_raise(Sequel::InvalidValue)
1888
- proc{@db.typecast_value(:date, 'a')}.must_raise(Sequel::InvalidValue)
1889
- proc{@db.typecast_value(:time, Date.new)}.must_raise(Sequel::InvalidValue)
1890
- proc{@db.typecast_value(:datetime, 4)}.must_raise(Sequel::InvalidValue)
1891
- end
1892
-
1893
- it "should handle integers with leading 0 as base 10" do
1894
- @db.typecast_value(:integer, "013").must_equal 13
1895
- @db.typecast_value(:integer, "08").must_equal 8
1896
- @db.typecast_value(:integer, "000013").must_equal 13
1897
- @db.typecast_value(:integer, "000008").must_equal 8
1898
- end
1899
-
1900
- it "should handle integers with leading 0x as base 16" do
1901
- @db.typecast_value(:integer, "0x013").must_equal 19
1902
- @db.typecast_value(:integer, "0x80").must_equal 128
1903
- end
1904
-
1905
- it "should typecast blobs as as Sequel::SQL::Blob" do
1906
- v = @db.typecast_value(:blob, "0x013")
1907
- v.must_be_kind_of(Sequel::SQL::Blob)
1908
- v.must_equal Sequel::SQL::Blob.new("0x013")
1909
- @db.typecast_value(:blob, v).object_id.must_equal v.object_id
1910
- end
1911
-
1912
- it "should typecast boolean values to true, false, or nil" do
1913
- @db.typecast_value(:boolean, false).must_equal false
1914
- @db.typecast_value(:boolean, 0).must_equal false
1915
- @db.typecast_value(:boolean, "0").must_equal false
1916
- @db.typecast_value(:boolean, 'f').must_equal false
1917
- @db.typecast_value(:boolean, 'false').must_equal false
1918
- @db.typecast_value(:boolean, true).must_equal true
1919
- @db.typecast_value(:boolean, 1).must_equal true
1920
- @db.typecast_value(:boolean, '1').must_equal true
1921
- @db.typecast_value(:boolean, 't').must_equal true
1922
- @db.typecast_value(:boolean, 'true').must_equal true
1923
- @db.typecast_value(:boolean, '').must_equal nil
1924
- end
1925
-
1926
- it "should typecast date values to Date" do
1927
- @db.typecast_value(:date, Date.today).must_equal Date.today
1928
- @db.typecast_value(:date, DateTime.now).must_equal Date.today
1929
- @db.typecast_value(:date, Time.now).must_equal Date.today
1930
- @db.typecast_value(:date, Date.today.to_s).must_equal Date.today
1931
- @db.typecast_value(:date, :year=>Date.today.year, :month=>Date.today.month, :day=>Date.today.day).must_equal Date.today
1932
- end
1933
-
1934
- it "should have Sequel.application_to_database_timestamp convert to Sequel.database_timezone" do
1935
- begin
1936
- t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
1937
- t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
1938
- t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
1939
- t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
1940
- Sequel.application_timezone = :utc
1941
- Sequel.database_timezone = :local
1942
- Sequel.application_to_database_timestamp(t).must_equal t4
1943
- Sequel.application_timezone = :local
1944
- Sequel.database_timezone = :utc
1945
- Sequel.application_to_database_timestamp(t2).must_equal t3
1946
- ensure
1947
- Sequel.default_timezone = nil
1948
- end
1949
- end
1950
-
1951
- it "should have Database#to_application_timestamp convert values using the database's timezone" do
1952
- begin
1953
- t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
1954
- t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
1955
- t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
1956
- t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
1957
- Sequel.default_timezone = :utc
1958
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t
1959
- Sequel.database_timezone = :local
1960
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t3
1961
- Sequel.default_timezone = :local
1962
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t2
1963
- Sequel.database_timezone = :utc
1964
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t4
1965
-
1966
- Sequel.default_timezone = :utc
1967
- @db.timezone = :local
1968
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t3
1969
- Sequel.default_timezone = :local
1970
- @db.timezone = :utc
1971
- @db.to_application_timestamp('2011-01-02 03:04:05').must_equal t4
1972
- ensure
1973
- Sequel.default_timezone = nil
1974
- end
1975
- end
1976
-
1977
- it "should typecast datetime values to Sequel.datetime_class with correct timezone handling" do
1978
- t = Time.utc(2011, 1, 2, 3, 4, 5, 500000) # UTC Time
1979
- t2 = Time.mktime(2011, 1, 2, 3, 4, 5, 500000) # Local Time
1980
- t3 = Time.utc(2011, 1, 2, 3, 4, 5, 500000) - (t - t2) # Local Time in UTC Time
1981
- t4 = Time.mktime(2011, 1, 2, 3, 4, 5, 500000) + (t - t2) # UTC Time in Local Time
1982
- secs = defined?(Rational) ? Rational(11, 2) : 5.5
1983
- r1 = defined?(Rational) ? Rational(t2.utc_offset, 86400) : t2.utc_offset/86400.0
1984
- r2 = defined?(Rational) ? Rational((t - t2).to_i, 86400) : (t - t2).to_i/86400.0
1985
- dt = DateTime.civil(2011, 1, 2, 3, 4, secs)
1986
- dt2 = DateTime.civil(2011, 1, 2, 3, 4, secs, r1)
1987
- dt3 = DateTime.civil(2011, 1, 2, 3, 4, secs) - r2
1988
- dt4 = DateTime.civil(2011, 1, 2, 3, 4, secs, r1) + r2
1989
-
1990
- t.must_equal t4
1991
- t2.must_equal t3
1992
- dt.must_equal dt4
1993
- dt2.must_equal dt3
1994
-
1995
- check = proc do |i, o|
1996
- v = @db.typecast_value(:datetime, i)
1997
- v.must_equal o
1998
- if o.is_a?(Time)
1999
- v.utc_offset.must_equal o.utc_offset
2000
- else
2001
- v.offset.must_equal o.offset
2002
- end
2003
- end
2004
- @db.extend_datasets(Module.new{def supports_timestamp_timezones?; true; end})
2005
- begin
2006
- @db.typecast_value(:datetime, dt).must_equal t
2007
- @db.typecast_value(:datetime, dt2).must_equal t2
2008
- @db.typecast_value(:datetime, t).must_equal t
2009
- @db.typecast_value(:datetime, t2).must_equal t2
2010
- @db.typecast_value(:datetime, @db.literal(dt)[1...-1]).must_equal t
2011
- @db.typecast_value(:datetime, dt.strftime('%F %T.%N')).must_equal t2
2012
- @db.typecast_value(:datetime, Date.civil(2011, 1, 2)).must_equal Time.mktime(2011, 1, 2, 0, 0, 0)
2013
- @db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000).must_equal t2
2014
-
2015
- Sequel.datetime_class = DateTime
2016
- @db.typecast_value(:datetime, dt).must_equal dt
2017
- @db.typecast_value(:datetime, dt2).must_equal dt2
2018
- @db.typecast_value(:datetime, t).must_equal dt
2019
- @db.typecast_value(:datetime, t2).must_equal dt2
2020
- @db.typecast_value(:datetime, @db.literal(dt)[1...-1]).must_equal dt
2021
- @db.typecast_value(:datetime, dt.strftime('%F %T.%N')).must_equal dt
2022
- @db.typecast_value(:datetime, Date.civil(2011, 1, 2)).must_equal DateTime.civil(2011, 1, 2, 0, 0, 0)
2023
- @db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000).must_equal dt
2024
-
2025
- Sequel.application_timezone = :utc
2026
- Sequel.typecast_timezone = :local
2027
- Sequel.datetime_class = Time
2028
- check[dt, t]
2029
- check[dt2, t3]
2030
- check[t, t]
2031
- check[t2, t3]
2032
- check[@db.literal(dt)[1...-1], t]
2033
- check[dt.strftime('%F %T.%N'), t3]
2034
- check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
2035
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t3]
2036
-
2037
- Sequel.datetime_class = DateTime
2038
- check[dt, dt]
2039
- check[dt2, dt3]
2040
- check[t, dt]
2041
- check[t2, dt3]
2042
- check[@db.literal(dt)[1...-1], dt]
2043
- check[dt.strftime('%F %T.%N'), dt3]
2044
- check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
2045
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt3]
2046
-
2047
- Sequel.typecast_timezone = :utc
2048
- Sequel.datetime_class = Time
2049
- check[dt, t]
2050
- check[dt2, t3]
2051
- check[t, t]
2052
- check[t2, t3]
2053
- check[@db.literal(dt)[1...-1], t]
2054
- check[dt.strftime('%F %T.%N'), t]
2055
- check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
2056
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t]
2057
-
2058
- Sequel.datetime_class = DateTime
2059
- check[dt, dt]
2060
- check[dt2, dt3]
2061
- check[t, dt]
2062
- check[t2, dt3]
2063
- check[@db.literal(dt)[1...-1], dt]
2064
- check[dt.strftime('%F %T.%N'), dt]
2065
- check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
2066
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt]
2067
-
2068
- Sequel.application_timezone = :local
2069
- Sequel.datetime_class = Time
2070
- check[dt, t4]
2071
- check[dt2, t2]
2072
- check[t, t4]
2073
- check[t2, t2]
2074
- check[@db.literal(dt)[1...-1], t4]
2075
- check[dt.strftime('%F %T.%N'), t4]
2076
- check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
2077
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t4]
2078
-
2079
- Sequel.datetime_class = DateTime
2080
- check[dt, dt4]
2081
- check[dt2, dt2]
2082
- check[t, dt4]
2083
- check[t2, dt2]
2084
- check[@db.literal(dt)[1...-1], dt4]
2085
- check[dt.strftime('%F %T.%N'), dt4]
2086
- check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
2087
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt4]
2088
-
2089
- Sequel.typecast_timezone = :local
2090
- Sequel.datetime_class = Time
2091
- check[dt, t4]
2092
- check[dt2, t2]
2093
- check[t, t4]
2094
- check[t2, t2]
2095
- check[@db.literal(dt)[1...-1], t4]
2096
- check[dt.strftime('%F %T.%N'), t2]
2097
- check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
2098
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t2]
2099
-
2100
- Sequel.datetime_class = DateTime
2101
- check[dt, dt4]
2102
- check[dt2, dt2]
2103
- check[t, dt4]
2104
- check[t2, dt2]
2105
- check[@db.literal(dt)[1...-1], dt4]
2106
- check[dt.strftime('%F %T.%N'), dt2]
2107
- check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
2108
- check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt2]
2109
-
2110
- ensure
2111
- Sequel.default_timezone = nil
2112
- Sequel.datetime_class = Time
2113
- end
2114
- end
2115
-
2116
- it "should handle arrays when typecasting timestamps" do
2117
- begin
2118
- @db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).must_equal Time.local(2011, 10, 11, 12, 13, 14)
2119
- @db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000]).must_equal Time.local(2011, 10, 11, 12, 13, 14, 500000)
2120
-
2121
- Sequel.datetime_class = DateTime
2122
- @db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).must_equal DateTime.civil(2011, 10, 11, 12, 13, 14)
2123
- @db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000]).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
2124
- @db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000, (defined?(Rational) ? Rational(1, 2) : 0.5)]).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
2125
- ensure
2126
- Sequel.datetime_class = Time
2127
- end
2128
- end
2129
-
2130
- it "should handle hashes when typecasting timestamps" do
2131
- begin
2132
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14).must_equal Time.local(2011, 10, 11, 12, 13, 14)
2133
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000).must_equal Time.local(2011, 10, 11, 12, 13, 14, 500000)
2134
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14).must_equal Time.local(2011, 10, 11, 12, 13, 14)
2135
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000).must_equal Time.local(2011, 10, 11, 12, 13, 14, 500000)
2136
-
2137
- Sequel.datetime_class = DateTime
2138
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14).must_equal DateTime.civil(2011, 10, 11, 12, 13, 14)
2139
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
2140
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14).must_equal DateTime.civil(2011, 10, 11, 12, 13, 14)
2141
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
2142
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :offset=>(defined?(Rational) ? Rational(1, 2) : 0.5)).must_equal DateTime.civil(2011, 10, 11, 12, 13, 14, (defined?(Rational) ? Rational(1, 2) : 0.5))
2143
- @db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000, :offset=>(defined?(Rational) ? Rational(1, 2) : 0.5)).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
2144
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'offset'=>(defined?(Rational) ? Rational(1, 2) : 0.5)).must_equal DateTime.civil(2011, 10, 11, 12, 13, 14, (defined?(Rational) ? Rational(1, 2) : 0.5))
2145
- @db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000, 'offset'=>(defined?(Rational) ? Rational(1, 2) : 0.5)).must_equal DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
2146
- ensure
2147
- Sequel.datetime_class = Time
2148
- end
2149
- end
2150
-
2151
- it "should typecast decimal values to BigDecimal" do
2152
- [1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
2153
- v = @db.typecast_value(:decimal, i)
2154
- v.must_be_kind_of(BigDecimal)
2155
- v.must_equal BigDecimal.new('1.0')
2156
- end
2157
- end
2158
-
2159
- it "should typecast float values to Float" do
2160
- [1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
2161
- v = @db.typecast_value(:float, i)
2162
- v.must_be_kind_of(Float)
2163
- v.must_equal 1.0
2164
- end
2165
- end
2166
-
2167
- it "should typecast string values to String" do
2168
- [1.0, '1.0', Sequel.blob('1.0')].each do |i|
2169
- v = @db.typecast_value(:string, i)
2170
- v.must_be_instance_of(String)
2171
- v.must_equal "1.0"
2172
- end
2173
- end
2174
-
2175
- it "should raise errors when typecasting hash and array values to String" do
2176
- [[], {}].each do |i|
2177
- proc{@db.typecast_value(:string, i)}.must_raise(Sequel::InvalidValue)
2178
- end
2179
- end
2180
-
2181
- it "should typecast time values to SQLTime" do
2182
- t = Time.now
2183
- st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3)
2184
- [st, Time.utc(t.year, t.month, t.day, 1, 2, 3), Time.local(t.year, t.month, t.day, 1, 2, 3), '01:02:03', {:hour=>1, :minute=>2, :second=>3}].each do |i|
2185
- v = @db.typecast_value(:time, i)
2186
- v.must_be_instance_of(Sequel::SQLTime)
2187
- v.must_equal st
2188
- end
2189
- end
2190
-
2191
- it "should correctly handle time value conversion to SQLTime with fractional seconds" do
2192
- t = Time.now
2193
- st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3, 500000)
2194
- t = Time.local(t.year, t.month, t.day, 1, 2, 3, 500000)
2195
- @db.typecast_value(:time, t).must_equal st
2196
- end
2197
-
2198
- it "should have an underlying exception class available at wrapped_exception" do
2199
- begin
2200
- @db.typecast_value(:date, 'a')
2201
- true.must_equal false
2202
- rescue Sequel::InvalidValue => e
2203
- e.wrapped_exception.must_be_kind_of(ArgumentError)
2204
- end
2205
- end
2206
-
2207
- it "should include underlying exception class in #inspect" do
2208
- begin
2209
- @db.typecast_value(:date, 'a')
2210
- true.must_equal false
2211
- rescue Sequel::InvalidValue => e
2212
- e.inspect.must_match(/\A#<Sequel::InvalidValue: ArgumentError: .*>\z/)
2213
- end
2214
- end
2215
- end
2216
-
2217
- describe "Database#blank_object?" do
2218
- it "should return whether the object is considered blank" do
2219
- db = Sequel::Database.new
2220
- c = lambda{|meth, value| Class.new{define_method(meth){value}}.new}
2221
-
2222
- db.send(:blank_object?, "").must_equal true
2223
- db.send(:blank_object?, " ").must_equal true
2224
- db.send(:blank_object?, nil).must_equal true
2225
- db.send(:blank_object?, false).must_equal true
2226
- db.send(:blank_object?, []).must_equal true
2227
- db.send(:blank_object?, {}).must_equal true
2228
- db.send(:blank_object?, c[:empty?, true]).must_equal true
2229
- db.send(:blank_object?, c[:blank?, true]).must_equal true
2230
-
2231
- db.send(:blank_object?, " a ").must_equal false
2232
- db.send(:blank_object?, 1).must_equal false
2233
- db.send(:blank_object?, 1.0).must_equal false
2234
- db.send(:blank_object?, true).must_equal false
2235
- db.send(:blank_object?, [1]).must_equal false
2236
- db.send(:blank_object?, {1.0=>2.0}).must_equal false
2237
- db.send(:blank_object?, c[:empty?, false]).must_equal false
2238
- db.send(:blank_object?, c[:blank?, false]).must_equal false
2239
- end
2240
- end
2241
-
2242
- describe "Database#schema_autoincrementing_primary_key?" do
2243
- it "should indicate whether the parsed schema row indicates a primary key" do
2244
- m = Sequel::Database.new.method(:schema_autoincrementing_primary_key?)
2245
- m.call(:primary_key=>true, :auto_increment=>true).must_equal true
2246
- m.call(:primary_key=>true, :auto_increment=>false).must_equal false
2247
- m.call(:primary_key=>false).must_equal false
2248
- end
2249
- end
2250
-
2251
- describe "Database#supports_schema_parsing?" do
2252
- it "should be false by default" do
2253
- Sequel::Database.new.supports_schema_parsing?.must_equal false
2254
- end
2255
-
2256
- it "should be true if the database implements schema_parse_table" do
2257
- db = Sequel::Database.new
2258
- def db.schema_parse_table(*) end
2259
- db.supports_schema_parsing?.must_equal true
2260
- end
2261
- end
2262
-
2263
- describe "Database#supports_foreign_key_parsing?" do
2264
- it "should be false by default" do
2265
- Sequel::Database.new.supports_foreign_key_parsing?.must_equal false
2266
- end
2267
-
2268
- it "should be true if the database implements foreign_key_list" do
2269
- db = Sequel::Database.new
2270
- def db.foreign_key_list(*) end
2271
- db.supports_foreign_key_parsing?.must_equal true
2272
- end
2273
- end
2274
-
2275
- describe "Database#supports_index_parsing?" do
2276
- it "should be false by default" do
2277
- Sequel::Database.new.supports_index_parsing?.must_equal false
2278
- end
2279
-
2280
- it "should be true if the database implements indexes" do
2281
- db = Sequel::Database.new
2282
- def db.indexes(*) end
2283
- db.supports_index_parsing?.must_equal true
2284
- end
2285
- end
2286
-
2287
- describe "Database#supports_table_listing?" do
2288
- it "should be false by default" do
2289
- Sequel::Database.new.supports_table_listing?.must_equal false
2290
- end
2291
-
2292
- it "should be true if the database implements tables" do
2293
- db = Sequel::Database.new
2294
- def db.tables(*) end
2295
- db.supports_table_listing?.must_equal true
2296
- end
2297
- end
2298
-
2299
- describe "Database#supports_view_listing?" do
2300
- it "should be false by default" do
2301
- Sequel::Database.new.supports_view_listing?.must_equal false
2302
- end
2303
-
2304
- it "should be true if the database implements views" do
2305
- db = Sequel::Database.new
2306
- def db.views(*) end
2307
- db.supports_view_listing?.must_equal true
2308
- end
2309
- end
2310
-
2311
- describe "Database#supports_deferrable_constraints?" do
2312
- it "should be false by default" do
2313
- Sequel::Database.new.supports_deferrable_constraints?.must_equal false
2314
- end
2315
- end
2316
-
2317
- describe "Database#supports_deferrable_foreign_key_constraints?" do
2318
- it "should be false by default" do
2319
- Sequel::Database.new.supports_deferrable_foreign_key_constraints?.must_equal false
2320
- end
2321
- end
2322
-
2323
- describe "Database#supports_transactional_ddl?" do
2324
- it "should be false by default" do
2325
- Sequel::Database.new.supports_transactional_ddl?.must_equal false
2326
- end
2327
- end
2328
-
2329
- describe "Database#global_index_namespace?" do
2330
- it "should be true by default" do
2331
- Sequel::Database.new.global_index_namespace?.must_equal true
2332
- end
2333
- end
2334
-
2335
- describe "Database#supports_savepoints?" do
2336
- it "should be false by default" do
2337
- Sequel::Database.new.supports_savepoints?.must_equal false
2338
- end
2339
- end
2340
-
2341
- describe "Database#supports_views_with_check_option?" do
2342
- it "should be false by default" do
2343
- Sequel::Database.new.supports_views_with_check_option?.must_equal false
2344
- end
2345
- end
2346
-
2347
- describe "Database#supports_views_with_local_check_option?" do
2348
- it "should be false by default" do
2349
- Sequel::Database.new.supports_views_with_local_check_option?.must_equal false
2350
- end
2351
- end
2352
-
2353
- describe "Database#supports_savepoints_in_prepared_transactions?" do
2354
- it "should be false by default" do
2355
- Sequel::Database.new.supports_savepoints_in_prepared_transactions?.must_equal false
2356
- end
2357
-
2358
- it "should be true if both savepoints and prepared transactions are supported" do
2359
- db = Sequel::Database.new
2360
- meta_def(db, :supports_savepoints?){true}
2361
- meta_def(db, :supports_prepared_transactions?){true}
2362
- db.supports_savepoints_in_prepared_transactions?.must_equal true
2363
- end
2364
- end
2365
-
2366
- describe "Database#supports_prepared_transactions?" do
2367
- it "should be false by default" do
2368
- Sequel::Database.new.supports_prepared_transactions?.must_equal false
2369
- end
2370
- end
2371
-
2372
- describe "Database#supports_transaction_isolation_levels?" do
2373
- it "should be false by default" do
2374
- Sequel::Database.new.supports_transaction_isolation_levels?.must_equal false
2375
- end
2376
- end
2377
-
2378
- describe "Database#input_identifier_meth" do
2379
- it "should be the input_identifer method of a default dataset for this database" do
2380
- db = Sequel::Database.new
2381
- db.send(:input_identifier_meth).call(:a).must_equal 'a'
2382
- db.identifier_input_method = :upcase
2383
- db.send(:input_identifier_meth).call(:a).must_equal 'A'
2384
- end
2385
- end
2386
-
2387
- describe "Database#output_identifier_meth" do
2388
- it "should be the output_identifer method of a default dataset for this database" do
2389
- db = Sequel::Database.new
2390
- db.send(:output_identifier_meth).call('A').must_equal :A
2391
- db.identifier_output_method = :downcase
2392
- db.send(:output_identifier_meth).call('A').must_equal :a
2393
- end
2394
- end
2395
-
2396
- describe "Database#metadata_dataset" do
2397
- it "should be a dataset with the default settings for identifier_input_method and identifier_output_method" do
2398
- ds = Sequel::Database.new.send(:metadata_dataset)
2399
- ds.literal(:a).must_equal 'A'
2400
- ds.send(:output_identifier, 'A').must_equal :a
2401
- end
2402
- end
2403
-
2404
- describe "Database#column_schema_to_ruby_default" do
2405
- it "should handle converting many default formats" do
2406
- db = Sequel::Database.new
2407
- p = lambda{|d,t| db.send(:column_schema_to_ruby_default, d, t)}
2408
- p[nil, :integer].must_equal nil
2409
- p[1, :integer].must_equal 1
2410
- p['1', :integer].must_equal 1
2411
- p['-1', :integer].must_equal(-1)
2412
- p[1.0, :float].must_equal 1.0
2413
- p['1.0', :float].must_equal 1.0
2414
- p['-1.0', :float].must_equal(-1.0)
2415
- p['1.0', :decimal].must_equal BigDecimal.new('1.0')
2416
- p['-1.0', :decimal].must_equal BigDecimal.new('-1.0')
2417
- p[true, :boolean].must_equal true
2418
- p[false, :boolean].must_equal false
2419
- p['1', :boolean].must_equal true
2420
- p['0', :boolean].must_equal false
2421
- p['true', :boolean].must_equal true
2422
- p['false', :boolean].must_equal false
2423
- p["'t'", :boolean].must_equal true
2424
- p["'f'", :boolean].must_equal false
2425
- p["'a'", :string].must_equal 'a'
2426
- p["'a'", :blob].must_equal Sequel.blob('a')
2427
- p["'a'", :blob].must_be_kind_of(Sequel::SQL::Blob)
2428
- p["''", :string].must_equal ''
2429
- p["'\\a''b'", :string].must_equal "\\a'b"
2430
- p["'NULL'", :string].must_equal "NULL"
2431
- p[Date.today, :date].must_equal Date.today
2432
- p["'2009-10-29'", :date].must_equal Date.new(2009,10,29)
2433
- p["CURRENT_TIMESTAMP", :date].must_equal Sequel::CURRENT_DATE
2434
- p["CURRENT_DATE", :date].must_equal Sequel::CURRENT_DATE
2435
- p["now()", :date].must_equal Sequel::CURRENT_DATE
2436
- p["getdate()", :date].must_equal Sequel::CURRENT_DATE
2437
- p["CURRENT_TIMESTAMP", :datetime].must_equal Sequel::CURRENT_TIMESTAMP
2438
- p["CURRENT_DATE", :datetime].must_equal Sequel::CURRENT_TIMESTAMP
2439
- p["now()", :datetime].must_equal Sequel::CURRENT_TIMESTAMP
2440
- p["getdate()", :datetime].must_equal Sequel::CURRENT_TIMESTAMP
2441
- p["'2009-10-29T10:20:30-07:00'", :datetime].must_equal DateTime.parse('2009-10-29T10:20:30-07:00')
2442
- p["'2009-10-29 10:20:30'", :datetime].must_equal DateTime.parse('2009-10-29 10:20:30')
2443
- p["'10:20:30'", :time].must_equal Time.parse('10:20:30')
2444
- p["NaN", :float].must_equal nil
2445
-
2446
- db = Sequel.mock(:host=>'postgres')
2447
- p["''::text", :string].must_equal ""
2448
- p["'\\a''b'::character varying", :string].must_equal "\\a'b"
2449
- p["'a'::bpchar", :string].must_equal "a"
2450
- p["(-1)", :integer].must_equal(-1)
2451
- p["(-1.0)", :float].must_equal(-1.0)
2452
- p['(-1.0)', :decimal].must_equal BigDecimal.new('-1.0')
2453
- p["'a'::bytea", :blob].must_equal Sequel.blob('a')
2454
- p["'a'::bytea", :blob].must_be_kind_of(Sequel::SQL::Blob)
2455
- p["'2009-10-29'::date", :date].must_equal Date.new(2009,10,29)
2456
- p["'2009-10-29 10:20:30.241343'::timestamp without time zone", :datetime].must_equal DateTime.parse('2009-10-29 10:20:30.241343')
2457
- p["'10:20:30'::time without time zone", :time].must_equal Time.parse('10:20:30')
2458
-
2459
- db = Sequel.mock(:host=>'mysql')
2460
- p["\\a'b", :string].must_equal "\\a'b"
2461
- p["a", :string].must_equal "a"
2462
- p["NULL", :string].must_equal "NULL"
2463
- p["-1", :float].must_equal(-1.0)
2464
- p['-1', :decimal].must_equal BigDecimal.new('-1.0')
2465
- p["2009-10-29", :date].must_equal Date.new(2009,10,29)
2466
- p["2009-10-29 10:20:30", :datetime].must_equal DateTime.parse('2009-10-29 10:20:30')
2467
- p["10:20:30", :time].must_equal Time.parse('10:20:30')
2468
- p["a", :enum].must_equal "a"
2469
- p["a,b", :set].must_equal "a,b"
2470
-
2471
- db = Sequel.mock(:host=>'mssql')
2472
- p["(N'a')", :string].must_equal "a"
2473
- p["((-12))", :integer].must_equal(-12)
2474
- p["((12.1))", :float].must_equal 12.1
2475
- p["((-12.1))", :decimal].must_equal BigDecimal.new('-12.1')
2476
- end
2477
- end
2478
-
2479
- describe "Database extensions" do
2480
- before(:all) do
2481
- class << Sequel
2482
- alias _extension extension
2483
- remove_method :extension
2484
- def extension(*)
2485
- end
2486
- end
2487
- end
2488
- after(:all) do
2489
- class << Sequel
2490
- remove_method :extension
2491
- alias extension _extension
2492
- remove_method :_extension
2493
- end
2494
- end
2495
- before do
2496
- @db = Sequel.mock
2497
- end
2498
- after do
2499
- Sequel::Database.instance_variable_set(:@initialize_hook, Proc.new {|db| })
2500
- end
2501
-
2502
- it "should be able to register an extension with a module have Database#extension extend the module" do
2503
- Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
2504
- @db.extension(:foo).a.must_equal 1
2505
- end
2506
-
2507
- it "should be able to register an extension with a block and have Database#extension call the block" do
2508
- @db.quote_identifiers = false
2509
- Sequel::Database.register_extension(:foo){|db| db.quote_identifiers = true}
2510
- @db.extension(:foo).quote_identifiers?.must_equal true
2511
- end
2512
-
2513
- it "should be able to register an extension with a callable and Database#extension call the callable" do
2514
- @db.quote_identifiers = false
2515
- Sequel::Database.register_extension(:foo, proc{|db| db.quote_identifiers = true})
2516
- @db.extension(:foo).quote_identifiers?.must_equal true
2517
- end
2518
-
2519
- it "should be able to load multiple extensions in the same call" do
2520
- @db.quote_identifiers = false
2521
- @db.identifier_input_method = :downcase
2522
- Sequel::Database.register_extension(:foo, proc{|db| db.quote_identifiers = true})
2523
- Sequel::Database.register_extension(:bar, proc{|db| db.identifier_input_method = nil})
2524
- @db.extension(:foo, :bar)
2525
- @db.quote_identifiers?.must_equal true
2526
- @db.identifier_input_method.must_equal nil
2527
- end
2528
-
2529
- it "should return the receiver" do
2530
- Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
2531
- @db.extension(:foo).must_be_same_as(@db)
2532
- end
2533
-
2534
- it "should raise an Error if registering with both a module and a block" do
2535
- proc{Sequel::Database.register_extension(:foo, Module.new){}}.must_raise(Sequel::Error)
2536
- end
2537
-
2538
- it "should raise an Error if attempting to load an incompatible extension" do
2539
- proc{@db.extension(:foo2)}.must_raise(Sequel::Error)
2540
- end
2541
-
2542
- it "should be able to load an extension into all future Databases with Database.extension" do
2543
- Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
2544
- Sequel::Database.register_extension(:bar, Module.new{def b; 2; end})
2545
- Sequel::Database.extension(:foo, :bar)
2546
- @db.wont_respond_to(:a)
2547
- @db.wont_respond_to(:b)
2548
- Sequel.mock.a.must_equal 1
2549
- Sequel.mock.b.must_equal 2
2550
- end
2551
- end
2552
-
2553
- describe "Database specific exception classes" do
2554
- before do
2555
- @db = Sequel.mock
2556
- class << @db
2557
- attr_accessor :sql_state
2558
-
2559
- def database_exception_sqlstate(exception, opts={})
2560
- @sql_state
2561
- end
2562
- end
2563
- end
2564
-
2565
- it "should use appropriate exception classes for given SQL states" do
2566
- @db.fetch = ArgumentError
2567
- @db.sql_state = '23502'
2568
- proc{@db.get(:a)}.must_raise(Sequel::NotNullConstraintViolation)
2569
- @db.sql_state = '23503'
2570
- proc{@db.get(:a)}.must_raise(Sequel::ForeignKeyConstraintViolation)
2571
- @db.sql_state = '23505'
2572
- proc{@db.get(:a)}.must_raise(Sequel::UniqueConstraintViolation)
2573
- @db.sql_state = '23513'
2574
- proc{@db.get(:a)}.must_raise(Sequel::CheckConstraintViolation)
2575
- @db.sql_state = '40001'
2576
- proc{@db.get(:a)}.must_raise(Sequel::SerializationFailure)
2577
- end
2578
- end
2579
-
2580
- describe "Database.after_initialize" do
2581
- after do
2582
- Sequel::Database.instance_variable_set(:@initialize_hook, Proc.new {|db| })
2583
- end
2584
-
2585
- it "should allow a block to be run after each new instance is created" do
2586
- Sequel::Database.after_initialize{|db| db.sql_log_level = :debug }
2587
- db = Sequel.mock
2588
- db.sql_log_level.must_equal :debug
2589
- end
2590
-
2591
- it "should allow multiple hooks to be registered" do
2592
- Sequel::Database.after_initialize{|db| db.sql_log_level = :debug }
2593
- Sequel::Database.after_initialize{|db| db.loggers << 11 }
2594
-
2595
- db = Sequel.mock
2596
-
2597
- db.sql_log_level.must_equal :debug
2598
- db.loggers.must_include(11)
2599
- end
2600
-
2601
- it "should raise an error if registration is called without a block" do
2602
- proc {
2603
- Sequel::Database.after_initialize
2604
- }.must_raise(Sequel::Error, /must provide block/i)
2605
- end
2606
- end
2607
-
2608
- describe "Database#schema_type_class" do
2609
- it "should return the class or array of classes for the given type symbol" do
2610
- db = Sequel.mock
2611
- {:string=>String, :integer=>Integer, :date=>Date, :datetime=>[Time, DateTime],
2612
- :time=>Sequel::SQLTime, :boolean=>[TrueClass, FalseClass], :float=>Float, :decimal=>BigDecimal,
2613
- :blob=>Sequel::SQL::Blob}.each do |sym, klass|
2614
- db.schema_type_class(sym).must_equal klass
2615
- end
2616
- end
2617
- end
2618
-
2619
- describe "Database#execute_{dui,ddl,insert}" do
2620
- before do
2621
- @db = Sequel::Database.new
2622
- def @db.execute(sql, opts={})
2623
- (@sqls ||= []) << sql
2624
- end
2625
- def @db.sqls
2626
- @sqls
2627
- end
2628
- end
2629
-
2630
- it "should execute the SQL" do
2631
- @db.execute_dui "DELETE FROM table"
2632
- @db.execute_ddl "SET foo"
2633
- @db.execute_insert "INSERT INTO table DEFAULT VALUES"
2634
- @db.sqls.must_equal ["DELETE FROM table", "SET foo", "INSERT INTO table DEFAULT VALUES"]
2635
- end
2636
- end