sequel 4.26.0 → 5.37.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 (692) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +405 -5656
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +232 -157
  5. data/bin/sequel +32 -9
  6. data/doc/advanced_associations.rdoc +252 -188
  7. data/doc/association_basics.rdoc +231 -273
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +75 -48
  10. data/doc/code_order.rdoc +28 -10
  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/mass_assignment.rdoc +74 -31
  16. data/doc/migration.rdoc +72 -46
  17. data/doc/model_dataset_method_design.rdoc +129 -0
  18. data/doc/model_hooks.rdoc +15 -25
  19. data/doc/model_plugins.rdoc +12 -12
  20. data/doc/mssql_stored_procedures.rdoc +3 -3
  21. data/doc/object_model.rdoc +59 -69
  22. data/doc/opening_databases.rdoc +84 -94
  23. data/doc/postgresql.rdoc +268 -38
  24. data/doc/prepared_statements.rdoc +29 -24
  25. data/doc/querying.rdoc +184 -164
  26. data/doc/reflection.rdoc +5 -6
  27. data/doc/release_notes/5.0.0.txt +159 -0
  28. data/doc/release_notes/5.1.0.txt +31 -0
  29. data/doc/release_notes/5.10.0.txt +84 -0
  30. data/doc/release_notes/5.11.0.txt +83 -0
  31. data/doc/release_notes/5.12.0.txt +141 -0
  32. data/doc/release_notes/5.13.0.txt +27 -0
  33. data/doc/release_notes/5.14.0.txt +63 -0
  34. data/doc/release_notes/5.15.0.txt +39 -0
  35. data/doc/release_notes/5.16.0.txt +110 -0
  36. data/doc/release_notes/5.17.0.txt +31 -0
  37. data/doc/release_notes/5.18.0.txt +69 -0
  38. data/doc/release_notes/5.19.0.txt +28 -0
  39. data/doc/release_notes/5.2.0.txt +33 -0
  40. data/doc/release_notes/5.20.0.txt +89 -0
  41. data/doc/release_notes/5.21.0.txt +87 -0
  42. data/doc/release_notes/5.22.0.txt +48 -0
  43. data/doc/release_notes/5.23.0.txt +56 -0
  44. data/doc/release_notes/5.24.0.txt +56 -0
  45. data/doc/release_notes/5.25.0.txt +32 -0
  46. data/doc/release_notes/5.26.0.txt +35 -0
  47. data/doc/release_notes/5.27.0.txt +21 -0
  48. data/doc/release_notes/5.28.0.txt +16 -0
  49. data/doc/release_notes/5.29.0.txt +22 -0
  50. data/doc/release_notes/5.3.0.txt +121 -0
  51. data/doc/release_notes/5.30.0.txt +20 -0
  52. data/doc/release_notes/5.31.0.txt +148 -0
  53. data/doc/release_notes/5.32.0.txt +46 -0
  54. data/doc/release_notes/5.33.0.txt +24 -0
  55. data/doc/release_notes/5.34.0.txt +40 -0
  56. data/doc/release_notes/5.35.0.txt +56 -0
  57. data/doc/release_notes/5.36.0.txt +60 -0
  58. data/doc/release_notes/5.37.0.txt +30 -0
  59. data/doc/release_notes/5.4.0.txt +80 -0
  60. data/doc/release_notes/5.5.0.txt +61 -0
  61. data/doc/release_notes/5.6.0.txt +31 -0
  62. data/doc/release_notes/5.7.0.txt +108 -0
  63. data/doc/release_notes/5.8.0.txt +170 -0
  64. data/doc/release_notes/5.9.0.txt +99 -0
  65. data/doc/schema_modification.rdoc +102 -77
  66. data/doc/security.rdoc +160 -87
  67. data/doc/sharding.rdoc +74 -47
  68. data/doc/sql.rdoc +135 -122
  69. data/doc/testing.rdoc +34 -18
  70. data/doc/thread_safety.rdoc +2 -4
  71. data/doc/transactions.rdoc +101 -19
  72. data/doc/validations.rdoc +64 -51
  73. data/doc/virtual_rows.rdoc +90 -109
  74. data/lib/sequel.rb +3 -1
  75. data/lib/sequel/adapters/ado.rb +154 -22
  76. data/lib/sequel/adapters/ado/access.rb +21 -21
  77. data/lib/sequel/adapters/ado/mssql.rb +8 -15
  78. data/lib/sequel/adapters/amalgalite.rb +17 -25
  79. data/lib/sequel/adapters/ibmdb.rb +52 -58
  80. data/lib/sequel/adapters/jdbc.rb +149 -127
  81. data/lib/sequel/adapters/jdbc/db2.rb +32 -40
  82. data/lib/sequel/adapters/jdbc/derby.rb +56 -58
  83. data/lib/sequel/adapters/jdbc/h2.rb +40 -30
  84. data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
  85. data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
  86. data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
  87. data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
  88. data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
  89. data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
  90. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
  91. data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
  92. data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
  93. data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
  94. data/lib/sequel/adapters/mock.rb +104 -113
  95. data/lib/sequel/adapters/mysql.rb +42 -61
  96. data/lib/sequel/adapters/mysql2.rb +126 -35
  97. data/lib/sequel/adapters/odbc.rb +21 -28
  98. data/lib/sequel/adapters/odbc/db2.rb +3 -1
  99. data/lib/sequel/adapters/odbc/mssql.rb +11 -15
  100. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  101. data/lib/sequel/adapters/oracle.rb +62 -68
  102. data/lib/sequel/adapters/postgres.rb +257 -311
  103. data/lib/sequel/adapters/postgresql.rb +3 -1
  104. data/lib/sequel/adapters/shared/access.rb +75 -79
  105. data/lib/sequel/adapters/shared/db2.rb +96 -74
  106. data/lib/sequel/adapters/shared/mssql.rb +258 -213
  107. data/lib/sequel/adapters/shared/mysql.rb +284 -216
  108. data/lib/sequel/adapters/shared/oracle.rb +175 -60
  109. data/lib/sequel/adapters/shared/postgres.rb +829 -383
  110. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
  111. data/lib/sequel/adapters/shared/sqlite.rb +382 -159
  112. data/lib/sequel/adapters/sqlanywhere.rb +53 -38
  113. data/lib/sequel/adapters/sqlite.rb +111 -105
  114. data/lib/sequel/adapters/tinytds.rb +38 -46
  115. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
  116. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
  117. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  118. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  119. data/lib/sequel/adapters/utils/replace.rb +3 -4
  120. data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
  121. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  122. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  123. data/lib/sequel/ast_transformer.rb +13 -89
  124. data/lib/sequel/connection_pool.rb +54 -26
  125. data/lib/sequel/connection_pool/sharded_single.rb +19 -12
  126. data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
  127. data/lib/sequel/connection_pool/single.rb +21 -12
  128. data/lib/sequel/connection_pool/threaded.rb +137 -119
  129. data/lib/sequel/core.rb +352 -320
  130. data/lib/sequel/database.rb +19 -2
  131. data/lib/sequel/database/connecting.rb +70 -55
  132. data/lib/sequel/database/dataset.rb +15 -5
  133. data/lib/sequel/database/dataset_defaults.rb +20 -102
  134. data/lib/sequel/database/features.rb +20 -4
  135. data/lib/sequel/database/logging.rb +25 -7
  136. data/lib/sequel/database/misc.rb +132 -118
  137. data/lib/sequel/database/query.rb +51 -28
  138. data/lib/sequel/database/schema_generator.rb +188 -75
  139. data/lib/sequel/database/schema_methods.rb +161 -92
  140. data/lib/sequel/database/transactions.rb +260 -58
  141. data/lib/sequel/dataset.rb +28 -12
  142. data/lib/sequel/dataset/actions.rb +354 -170
  143. data/lib/sequel/dataset/dataset_module.rb +46 -0
  144. data/lib/sequel/dataset/features.rb +81 -34
  145. data/lib/sequel/dataset/graph.rb +82 -58
  146. data/lib/sequel/dataset/misc.rb +139 -47
  147. data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
  148. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  149. data/lib/sequel/dataset/query.rb +428 -214
  150. data/lib/sequel/dataset/sql.rb +446 -339
  151. data/lib/sequel/deprecated.rb +14 -2
  152. data/lib/sequel/exceptions.rb +48 -16
  153. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  154. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  155. data/lib/sequel/extensions/_pretty_table.rb +10 -9
  156. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  157. data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
  158. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  159. data/lib/sequel/extensions/blank.rb +2 -0
  160. data/lib/sequel/extensions/caller_logging.rb +79 -0
  161. data/lib/sequel/extensions/columns_introspection.rb +9 -4
  162. data/lib/sequel/extensions/connection_expiration.rb +99 -0
  163. data/lib/sequel/extensions/connection_validator.rb +26 -13
  164. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  165. data/lib/sequel/extensions/constraint_validations.rb +93 -38
  166. data/lib/sequel/extensions/core_extensions.rb +45 -53
  167. data/lib/sequel/extensions/core_refinements.rb +44 -46
  168. data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
  169. data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
  170. data/lib/sequel/extensions/date_arithmetic.rb +42 -16
  171. data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
  172. data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
  173. data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
  174. data/lib/sequel/extensions/error_sql.rb +7 -3
  175. data/lib/sequel/extensions/escaped_like.rb +100 -0
  176. data/lib/sequel/extensions/eval_inspect.rb +14 -15
  177. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  178. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  179. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  180. data/lib/sequel/extensions/from_block.rb +2 -31
  181. data/lib/sequel/extensions/graph_each.rb +19 -6
  182. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  183. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  184. data/lib/sequel/extensions/index_caching.rb +109 -0
  185. data/lib/sequel/extensions/inflector.rb +8 -4
  186. data/lib/sequel/extensions/integer64.rb +32 -0
  187. data/lib/sequel/extensions/looser_typecasting.rb +19 -9
  188. data/lib/sequel/extensions/migration.rb +132 -80
  189. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
  190. data/lib/sequel/extensions/named_timezones.rb +88 -23
  191. data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
  192. data/lib/sequel/extensions/null_dataset.rb +12 -8
  193. data/lib/sequel/extensions/pagination.rb +35 -28
  194. data/lib/sequel/extensions/pg_array.rb +227 -316
  195. data/lib/sequel/extensions/pg_array_ops.rb +19 -7
  196. data/lib/sequel/extensions/pg_enum.rb +69 -24
  197. data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
  198. data/lib/sequel/extensions/pg_hstore.rb +50 -59
  199. data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
  200. data/lib/sequel/extensions/pg_inet.rb +34 -15
  201. data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
  202. data/lib/sequel/extensions/pg_interval.rb +26 -26
  203. data/lib/sequel/extensions/pg_json.rb +422 -141
  204. data/lib/sequel/extensions/pg_json_ops.rb +248 -9
  205. data/lib/sequel/extensions/pg_loose_count.rb +5 -1
  206. data/lib/sequel/extensions/pg_range.rb +162 -146
  207. data/lib/sequel/extensions/pg_range_ops.rb +10 -5
  208. data/lib/sequel/extensions/pg_row.rb +53 -87
  209. data/lib/sequel/extensions/pg_row_ops.rb +36 -13
  210. data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
  211. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  212. data/lib/sequel/extensions/pretty_table.rb +4 -0
  213. data/lib/sequel/extensions/query.rb +12 -7
  214. data/lib/sequel/extensions/round_timestamps.rb +6 -9
  215. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  216. data/lib/sequel/extensions/s.rb +59 -0
  217. data/lib/sequel/extensions/schema_caching.rb +14 -1
  218. data/lib/sequel/extensions/schema_dumper.rb +83 -55
  219. data/lib/sequel/extensions/select_remove.rb +8 -4
  220. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  221. data/lib/sequel/extensions/server_block.rb +50 -17
  222. data/lib/sequel/extensions/server_logging.rb +61 -0
  223. data/lib/sequel/extensions/split_array_nil.rb +8 -4
  224. data/lib/sequel/extensions/sql_comments.rb +96 -0
  225. data/lib/sequel/extensions/sql_expr.rb +4 -1
  226. data/lib/sequel/extensions/string_agg.rb +181 -0
  227. data/lib/sequel/extensions/string_date_time.rb +2 -0
  228. data/lib/sequel/extensions/symbol_aref.rb +53 -0
  229. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  230. data/lib/sequel/extensions/symbol_as.rb +23 -0
  231. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  232. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  233. data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
  234. data/lib/sequel/extensions/to_dot.rb +15 -5
  235. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  236. data/lib/sequel/model.rb +36 -126
  237. data/lib/sequel/model/associations.rb +850 -257
  238. data/lib/sequel/model/base.rb +652 -764
  239. data/lib/sequel/model/dataset_module.rb +13 -10
  240. data/lib/sequel/model/default_inflections.rb +3 -1
  241. data/lib/sequel/model/errors.rb +3 -3
  242. data/lib/sequel/model/exceptions.rb +12 -12
  243. data/lib/sequel/model/inflections.rb +8 -19
  244. data/lib/sequel/model/plugins.rb +111 -0
  245. data/lib/sequel/plugins/accessed_columns.rb +2 -0
  246. data/lib/sequel/plugins/active_model.rb +32 -7
  247. data/lib/sequel/plugins/after_initialize.rb +3 -1
  248. data/lib/sequel/plugins/association_dependencies.rb +27 -18
  249. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  250. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  251. data/lib/sequel/plugins/association_pks.rb +181 -83
  252. data/lib/sequel/plugins/association_proxies.rb +33 -9
  253. data/lib/sequel/plugins/auto_validations.rb +58 -23
  254. data/lib/sequel/plugins/before_after_save.rb +8 -0
  255. data/lib/sequel/plugins/blacklist_security.rb +23 -12
  256. data/lib/sequel/plugins/boolean_readers.rb +9 -6
  257. data/lib/sequel/plugins/boolean_subsets.rb +64 -0
  258. data/lib/sequel/plugins/caching.rb +27 -16
  259. data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
  260. data/lib/sequel/plugins/column_conflicts.rb +18 -3
  261. data/lib/sequel/plugins/column_select.rb +9 -5
  262. data/lib/sequel/plugins/columns_updated.rb +42 -0
  263. data/lib/sequel/plugins/composition.rb +36 -24
  264. data/lib/sequel/plugins/constraint_validations.rb +37 -16
  265. data/lib/sequel/plugins/csv_serializer.rb +58 -35
  266. data/lib/sequel/plugins/dataset_associations.rb +60 -18
  267. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  268. data/lib/sequel/plugins/defaults_setter.rb +74 -13
  269. data/lib/sequel/plugins/delay_add_association.rb +4 -1
  270. data/lib/sequel/plugins/dirty.rb +65 -24
  271. data/lib/sequel/plugins/eager_each.rb +27 -3
  272. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  273. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  274. data/lib/sequel/plugins/error_splitter.rb +19 -12
  275. data/lib/sequel/plugins/finder.rb +246 -0
  276. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  277. data/lib/sequel/plugins/force_encoding.rb +9 -12
  278. data/lib/sequel/plugins/hook_class_methods.rb +39 -54
  279. data/lib/sequel/plugins/input_transformer.rb +20 -10
  280. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  281. data/lib/sequel/plugins/insert_returning_select.rb +4 -2
  282. data/lib/sequel/plugins/instance_filters.rb +12 -8
  283. data/lib/sequel/plugins/instance_hooks.rb +36 -17
  284. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  285. data/lib/sequel/plugins/inverted_subsets.rb +24 -13
  286. data/lib/sequel/plugins/json_serializer.rb +123 -47
  287. data/lib/sequel/plugins/lazy_attributes.rb +20 -14
  288. data/lib/sequel/plugins/list.rb +40 -26
  289. data/lib/sequel/plugins/many_through_many.rb +28 -12
  290. data/lib/sequel/plugins/modification_detection.rb +17 -5
  291. data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
  292. data/lib/sequel/plugins/nested_attributes.rb +55 -28
  293. data/lib/sequel/plugins/optimistic_locking.rb +5 -3
  294. data/lib/sequel/plugins/pg_array_associations.rb +52 -18
  295. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
  296. data/lib/sequel/plugins/pg_row.rb +7 -51
  297. data/lib/sequel/plugins/prepared_statements.rb +53 -72
  298. data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
  299. data/lib/sequel/plugins/rcte_tree.rb +43 -63
  300. data/lib/sequel/plugins/serialization.rb +37 -44
  301. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
  302. data/lib/sequel/plugins/sharding.rb +17 -10
  303. data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
  304. data/lib/sequel/plugins/singular_table_names.rb +2 -0
  305. data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
  306. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  307. data/lib/sequel/plugins/split_values.rb +13 -6
  308. data/lib/sequel/plugins/static_cache.rb +79 -53
  309. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  310. data/lib/sequel/plugins/string_stripper.rb +5 -3
  311. data/lib/sequel/plugins/subclasses.rb +20 -2
  312. data/lib/sequel/plugins/subset_conditions.rb +48 -0
  313. data/lib/sequel/plugins/table_select.rb +4 -2
  314. data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
  315. data/lib/sequel/plugins/throw_failures.rb +110 -0
  316. data/lib/sequel/plugins/timestamps.rb +22 -8
  317. data/lib/sequel/plugins/touch.rb +21 -8
  318. data/lib/sequel/plugins/tree.rb +57 -30
  319. data/lib/sequel/plugins/typecast_on_load.rb +14 -4
  320. data/lib/sequel/plugins/unlimited_update.rb +3 -7
  321. data/lib/sequel/plugins/update_or_create.rb +6 -4
  322. data/lib/sequel/plugins/update_primary_key.rb +3 -1
  323. data/lib/sequel/plugins/update_refresh.rb +28 -15
  324. data/lib/sequel/plugins/uuid.rb +70 -0
  325. data/lib/sequel/plugins/validate_associated.rb +20 -0
  326. data/lib/sequel/plugins/validation_class_methods.rb +40 -19
  327. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  328. data/lib/sequel/plugins/validation_helpers.rb +49 -31
  329. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  330. data/lib/sequel/plugins/xml_serializer.rb +31 -30
  331. data/lib/sequel/sql.rb +479 -329
  332. data/lib/sequel/timezones.rb +62 -32
  333. data/lib/sequel/version.rb +10 -3
  334. metadata +177 -477
  335. data/Rakefile +0 -165
  336. data/doc/active_record.rdoc +0 -912
  337. data/doc/release_notes/1.0.txt +0 -38
  338. data/doc/release_notes/1.1.txt +0 -143
  339. data/doc/release_notes/1.3.txt +0 -101
  340. data/doc/release_notes/1.4.0.txt +0 -53
  341. data/doc/release_notes/1.5.0.txt +0 -155
  342. data/doc/release_notes/2.0.0.txt +0 -298
  343. data/doc/release_notes/2.1.0.txt +0 -271
  344. data/doc/release_notes/2.10.0.txt +0 -328
  345. data/doc/release_notes/2.11.0.txt +0 -215
  346. data/doc/release_notes/2.12.0.txt +0 -534
  347. data/doc/release_notes/2.2.0.txt +0 -253
  348. data/doc/release_notes/2.3.0.txt +0 -88
  349. data/doc/release_notes/2.4.0.txt +0 -106
  350. data/doc/release_notes/2.5.0.txt +0 -137
  351. data/doc/release_notes/2.6.0.txt +0 -157
  352. data/doc/release_notes/2.7.0.txt +0 -166
  353. data/doc/release_notes/2.8.0.txt +0 -171
  354. data/doc/release_notes/2.9.0.txt +0 -97
  355. data/doc/release_notes/3.0.0.txt +0 -221
  356. data/doc/release_notes/3.1.0.txt +0 -406
  357. data/doc/release_notes/3.10.0.txt +0 -286
  358. data/doc/release_notes/3.11.0.txt +0 -254
  359. data/doc/release_notes/3.12.0.txt +0 -304
  360. data/doc/release_notes/3.13.0.txt +0 -210
  361. data/doc/release_notes/3.14.0.txt +0 -118
  362. data/doc/release_notes/3.15.0.txt +0 -78
  363. data/doc/release_notes/3.16.0.txt +0 -45
  364. data/doc/release_notes/3.17.0.txt +0 -58
  365. data/doc/release_notes/3.18.0.txt +0 -120
  366. data/doc/release_notes/3.19.0.txt +0 -67
  367. data/doc/release_notes/3.2.0.txt +0 -268
  368. data/doc/release_notes/3.20.0.txt +0 -41
  369. data/doc/release_notes/3.21.0.txt +0 -87
  370. data/doc/release_notes/3.22.0.txt +0 -39
  371. data/doc/release_notes/3.23.0.txt +0 -172
  372. data/doc/release_notes/3.24.0.txt +0 -420
  373. data/doc/release_notes/3.25.0.txt +0 -88
  374. data/doc/release_notes/3.26.0.txt +0 -88
  375. data/doc/release_notes/3.27.0.txt +0 -82
  376. data/doc/release_notes/3.28.0.txt +0 -304
  377. data/doc/release_notes/3.29.0.txt +0 -459
  378. data/doc/release_notes/3.3.0.txt +0 -192
  379. data/doc/release_notes/3.30.0.txt +0 -135
  380. data/doc/release_notes/3.31.0.txt +0 -146
  381. data/doc/release_notes/3.32.0.txt +0 -202
  382. data/doc/release_notes/3.33.0.txt +0 -157
  383. data/doc/release_notes/3.34.0.txt +0 -671
  384. data/doc/release_notes/3.35.0.txt +0 -144
  385. data/doc/release_notes/3.36.0.txt +0 -245
  386. data/doc/release_notes/3.37.0.txt +0 -338
  387. data/doc/release_notes/3.38.0.txt +0 -234
  388. data/doc/release_notes/3.39.0.txt +0 -237
  389. data/doc/release_notes/3.4.0.txt +0 -325
  390. data/doc/release_notes/3.40.0.txt +0 -73
  391. data/doc/release_notes/3.41.0.txt +0 -155
  392. data/doc/release_notes/3.42.0.txt +0 -74
  393. data/doc/release_notes/3.43.0.txt +0 -105
  394. data/doc/release_notes/3.44.0.txt +0 -152
  395. data/doc/release_notes/3.45.0.txt +0 -179
  396. data/doc/release_notes/3.46.0.txt +0 -122
  397. data/doc/release_notes/3.47.0.txt +0 -270
  398. data/doc/release_notes/3.48.0.txt +0 -477
  399. data/doc/release_notes/3.5.0.txt +0 -510
  400. data/doc/release_notes/3.6.0.txt +0 -366
  401. data/doc/release_notes/3.7.0.txt +0 -179
  402. data/doc/release_notes/3.8.0.txt +0 -151
  403. data/doc/release_notes/3.9.0.txt +0 -233
  404. data/doc/release_notes/4.0.0.txt +0 -262
  405. data/doc/release_notes/4.1.0.txt +0 -85
  406. data/doc/release_notes/4.10.0.txt +0 -226
  407. data/doc/release_notes/4.11.0.txt +0 -147
  408. data/doc/release_notes/4.12.0.txt +0 -105
  409. data/doc/release_notes/4.13.0.txt +0 -169
  410. data/doc/release_notes/4.14.0.txt +0 -68
  411. data/doc/release_notes/4.15.0.txt +0 -56
  412. data/doc/release_notes/4.16.0.txt +0 -36
  413. data/doc/release_notes/4.17.0.txt +0 -38
  414. data/doc/release_notes/4.18.0.txt +0 -36
  415. data/doc/release_notes/4.19.0.txt +0 -45
  416. data/doc/release_notes/4.2.0.txt +0 -129
  417. data/doc/release_notes/4.20.0.txt +0 -79
  418. data/doc/release_notes/4.21.0.txt +0 -94
  419. data/doc/release_notes/4.22.0.txt +0 -72
  420. data/doc/release_notes/4.23.0.txt +0 -65
  421. data/doc/release_notes/4.24.0.txt +0 -99
  422. data/doc/release_notes/4.25.0.txt +0 -181
  423. data/doc/release_notes/4.26.0.txt +0 -44
  424. data/doc/release_notes/4.3.0.txt +0 -40
  425. data/doc/release_notes/4.4.0.txt +0 -92
  426. data/doc/release_notes/4.5.0.txt +0 -34
  427. data/doc/release_notes/4.6.0.txt +0 -30
  428. data/doc/release_notes/4.7.0.txt +0 -103
  429. data/doc/release_notes/4.8.0.txt +0 -175
  430. data/doc/release_notes/4.9.0.txt +0 -190
  431. data/lib/sequel/adapters/cubrid.rb +0 -142
  432. data/lib/sequel/adapters/do.rb +0 -156
  433. data/lib/sequel/adapters/do/mysql.rb +0 -64
  434. data/lib/sequel/adapters/do/postgres.rb +0 -42
  435. data/lib/sequel/adapters/do/sqlite3.rb +0 -40
  436. data/lib/sequel/adapters/jdbc/as400.rb +0 -82
  437. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
  438. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
  439. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
  440. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
  441. data/lib/sequel/adapters/odbc/progress.rb +0 -8
  442. data/lib/sequel/adapters/shared/cubrid.rb +0 -243
  443. data/lib/sequel/adapters/shared/firebird.rb +0 -245
  444. data/lib/sequel/adapters/shared/informix.rb +0 -52
  445. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
  446. data/lib/sequel/adapters/shared/progress.rb +0 -38
  447. data/lib/sequel/adapters/swift.rb +0 -158
  448. data/lib/sequel/adapters/swift/mysql.rb +0 -47
  449. data/lib/sequel/adapters/swift/postgres.rb +0 -45
  450. data/lib/sequel/adapters/swift/sqlite.rb +0 -47
  451. data/lib/sequel/adapters/utils/pg_types.rb +0 -68
  452. data/lib/sequel/dataset/mutation.rb +0 -109
  453. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
  454. data/lib/sequel/extensions/filter_having.rb +0 -59
  455. data/lib/sequel/extensions/hash_aliases.rb +0 -45
  456. data/lib/sequel/extensions/meta_def.rb +0 -31
  457. data/lib/sequel/extensions/query_literals.rb +0 -80
  458. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
  459. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
  460. data/lib/sequel/extensions/set_overrides.rb +0 -72
  461. data/lib/sequel/no_core_ext.rb +0 -1
  462. data/lib/sequel/plugins/association_autoreloading.rb +0 -7
  463. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
  464. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
  465. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
  466. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
  467. data/lib/sequel/plugins/schema.rb +0 -80
  468. data/lib/sequel/plugins/scissors.rb +0 -33
  469. data/spec/adapters/db2_spec.rb +0 -160
  470. data/spec/adapters/firebird_spec.rb +0 -411
  471. data/spec/adapters/informix_spec.rb +0 -100
  472. data/spec/adapters/mssql_spec.rb +0 -706
  473. data/spec/adapters/mysql_spec.rb +0 -1287
  474. data/spec/adapters/oracle_spec.rb +0 -313
  475. data/spec/adapters/postgres_spec.rb +0 -3725
  476. data/spec/adapters/spec_helper.rb +0 -43
  477. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  478. data/spec/adapters/sqlite_spec.rb +0 -653
  479. data/spec/bin_spec.rb +0 -254
  480. data/spec/core/connection_pool_spec.rb +0 -1016
  481. data/spec/core/database_spec.rb +0 -2531
  482. data/spec/core/dataset_spec.rb +0 -5098
  483. data/spec/core/deprecated_spec.rb +0 -70
  484. data/spec/core/expression_filters_spec.rb +0 -1243
  485. data/spec/core/mock_adapter_spec.rb +0 -462
  486. data/spec/core/object_graph_spec.rb +0 -303
  487. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  488. data/spec/core/schema_generator_spec.rb +0 -179
  489. data/spec/core/schema_spec.rb +0 -1659
  490. data/spec/core/spec_helper.rb +0 -34
  491. data/spec/core/version_spec.rb +0 -7
  492. data/spec/core_extensions_spec.rb +0 -699
  493. data/spec/extensions/accessed_columns_spec.rb +0 -51
  494. data/spec/extensions/active_model_spec.rb +0 -123
  495. data/spec/extensions/after_initialize_spec.rb +0 -24
  496. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  497. data/spec/extensions/association_dependencies_spec.rb +0 -117
  498. data/spec/extensions/association_pks_spec.rb +0 -365
  499. data/spec/extensions/association_proxies_spec.rb +0 -86
  500. data/spec/extensions/auto_validations_spec.rb +0 -192
  501. data/spec/extensions/blacklist_security_spec.rb +0 -88
  502. data/spec/extensions/blank_spec.rb +0 -69
  503. data/spec/extensions/boolean_readers_spec.rb +0 -93
  504. data/spec/extensions/caching_spec.rb +0 -270
  505. data/spec/extensions/class_table_inheritance_spec.rb +0 -420
  506. data/spec/extensions/column_conflicts_spec.rb +0 -60
  507. data/spec/extensions/column_select_spec.rb +0 -108
  508. data/spec/extensions/columns_introspection_spec.rb +0 -91
  509. data/spec/extensions/composition_spec.rb +0 -242
  510. data/spec/extensions/connection_validator_spec.rb +0 -120
  511. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
  512. data/spec/extensions/constraint_validations_spec.rb +0 -325
  513. data/spec/extensions/core_refinements_spec.rb +0 -519
  514. data/spec/extensions/csv_serializer_spec.rb +0 -173
  515. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  516. data/spec/extensions/dataset_associations_spec.rb +0 -311
  517. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  518. data/spec/extensions/date_arithmetic_spec.rb +0 -150
  519. data/spec/extensions/defaults_setter_spec.rb +0 -101
  520. data/spec/extensions/delay_add_association_spec.rb +0 -52
  521. data/spec/extensions/dirty_spec.rb +0 -180
  522. data/spec/extensions/eager_each_spec.rb +0 -42
  523. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  524. data/spec/extensions/error_splitter_spec.rb +0 -18
  525. data/spec/extensions/error_sql_spec.rb +0 -20
  526. data/spec/extensions/eval_inspect_spec.rb +0 -73
  527. data/spec/extensions/filter_having_spec.rb +0 -40
  528. data/spec/extensions/force_encoding_spec.rb +0 -114
  529. data/spec/extensions/from_block_spec.rb +0 -21
  530. data/spec/extensions/graph_each_spec.rb +0 -109
  531. data/spec/extensions/hash_aliases_spec.rb +0 -24
  532. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  533. data/spec/extensions/inflector_spec.rb +0 -183
  534. data/spec/extensions/input_transformer_spec.rb +0 -54
  535. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  536. data/spec/extensions/instance_filters_spec.rb +0 -79
  537. data/spec/extensions/instance_hooks_spec.rb +0 -276
  538. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  539. data/spec/extensions/json_serializer_spec.rb +0 -291
  540. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  541. data/spec/extensions/list_spec.rb +0 -267
  542. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  543. data/spec/extensions/many_through_many_spec.rb +0 -2172
  544. data/spec/extensions/meta_def_spec.rb +0 -21
  545. data/spec/extensions/migration_spec.rb +0 -712
  546. data/spec/extensions/modification_detection_spec.rb +0 -80
  547. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  548. data/spec/extensions/named_timezones_spec.rb +0 -108
  549. data/spec/extensions/nested_attributes_spec.rb +0 -697
  550. data/spec/extensions/null_dataset_spec.rb +0 -85
  551. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  552. data/spec/extensions/pagination_spec.rb +0 -118
  553. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  554. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  555. data/spec/extensions/pg_array_spec.rb +0 -395
  556. data/spec/extensions/pg_enum_spec.rb +0 -92
  557. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  558. data/spec/extensions/pg_hstore_spec.rb +0 -206
  559. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  560. data/spec/extensions/pg_inet_spec.rb +0 -52
  561. data/spec/extensions/pg_interval_spec.rb +0 -76
  562. data/spec/extensions/pg_json_ops_spec.rb +0 -229
  563. data/spec/extensions/pg_json_spec.rb +0 -218
  564. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  565. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  566. data/spec/extensions/pg_range_spec.rb +0 -404
  567. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  568. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  569. data/spec/extensions/pg_row_spec.rb +0 -360
  570. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  571. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  572. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  573. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  574. data/spec/extensions/prepared_statements_spec.rb +0 -103
  575. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  576. data/spec/extensions/pretty_table_spec.rb +0 -92
  577. data/spec/extensions/query_literals_spec.rb +0 -183
  578. data/spec/extensions/query_spec.rb +0 -102
  579. data/spec/extensions/rcte_tree_spec.rb +0 -392
  580. data/spec/extensions/round_timestamps_spec.rb +0 -43
  581. data/spec/extensions/schema_caching_spec.rb +0 -41
  582. data/spec/extensions/schema_dumper_spec.rb +0 -789
  583. data/spec/extensions/schema_spec.rb +0 -117
  584. data/spec/extensions/scissors_spec.rb +0 -26
  585. data/spec/extensions/select_remove_spec.rb +0 -38
  586. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  587. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  588. data/spec/extensions/serialization_spec.rb +0 -362
  589. data/spec/extensions/server_block_spec.rb +0 -90
  590. data/spec/extensions/set_overrides_spec.rb +0 -61
  591. data/spec/extensions/sharding_spec.rb +0 -198
  592. data/spec/extensions/shared_caching_spec.rb +0 -175
  593. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  594. data/spec/extensions/singular_table_names_spec.rb +0 -22
  595. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  596. data/spec/extensions/spec_helper.rb +0 -71
  597. data/spec/extensions/split_array_nil_spec.rb +0 -24
  598. data/spec/extensions/split_values_spec.rb +0 -22
  599. data/spec/extensions/sql_expr_spec.rb +0 -60
  600. data/spec/extensions/static_cache_spec.rb +0 -361
  601. data/spec/extensions/string_date_time_spec.rb +0 -95
  602. data/spec/extensions/string_stripper_spec.rb +0 -68
  603. data/spec/extensions/subclasses_spec.rb +0 -66
  604. data/spec/extensions/table_select_spec.rb +0 -71
  605. data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
  606. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  607. data/spec/extensions/timestamps_spec.rb +0 -175
  608. data/spec/extensions/to_dot_spec.rb +0 -154
  609. data/spec/extensions/touch_spec.rb +0 -203
  610. data/spec/extensions/tree_spec.rb +0 -274
  611. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  612. data/spec/extensions/unlimited_update_spec.rb +0 -20
  613. data/spec/extensions/update_or_create_spec.rb +0 -87
  614. data/spec/extensions/update_primary_key_spec.rb +0 -100
  615. data/spec/extensions/update_refresh_spec.rb +0 -53
  616. data/spec/extensions/validate_associated_spec.rb +0 -52
  617. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  618. data/spec/extensions/validation_helpers_spec.rb +0 -541
  619. data/spec/extensions/xml_serializer_spec.rb +0 -207
  620. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  621. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  622. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  623. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  624. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  625. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  626. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  627. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  628. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  629. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  630. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  631. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  632. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  633. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  634. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  635. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  636. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  637. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  638. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  639. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  640. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  641. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  642. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  643. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  644. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  645. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  646. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  647. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  648. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  649. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  650. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  651. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  652. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  653. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  654. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  655. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  656. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  657. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  658. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  659. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  660. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  661. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  662. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  663. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  664. data/spec/guards_helper.rb +0 -55
  665. data/spec/integration/associations_test.rb +0 -2454
  666. data/spec/integration/database_test.rb +0 -113
  667. data/spec/integration/dataset_test.rb +0 -1808
  668. data/spec/integration/eager_loader_test.rb +0 -687
  669. data/spec/integration/migrator_test.rb +0 -240
  670. data/spec/integration/model_test.rb +0 -226
  671. data/spec/integration/plugin_test.rb +0 -2240
  672. data/spec/integration/prepared_statement_test.rb +0 -467
  673. data/spec/integration/schema_test.rb +0 -817
  674. data/spec/integration/spec_helper.rb +0 -48
  675. data/spec/integration/timezone_test.rb +0 -86
  676. data/spec/integration/transaction_test.rb +0 -374
  677. data/spec/integration/type_test.rb +0 -133
  678. data/spec/model/association_reflection_spec.rb +0 -525
  679. data/spec/model/associations_spec.rb +0 -4426
  680. data/spec/model/base_spec.rb +0 -759
  681. data/spec/model/class_dataset_methods_spec.rb +0 -146
  682. data/spec/model/dataset_methods_spec.rb +0 -149
  683. data/spec/model/eager_loading_spec.rb +0 -2137
  684. data/spec/model/hooks_spec.rb +0 -604
  685. data/spec/model/inflector_spec.rb +0 -26
  686. data/spec/model/model_spec.rb +0 -982
  687. data/spec/model/plugins_spec.rb +0 -299
  688. data/spec/model/record_spec.rb +0 -2147
  689. data/spec/model/spec_helper.rb +0 -46
  690. data/spec/model/validations_spec.rb +0 -193
  691. data/spec/sequel_coverage.rb +0 -15
  692. data/spec/spec_config.rb +0 -10
@@ -1,113 +0,0 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
-
3
- describe Sequel::Database do
4
- before do
5
- @db = DB
6
- end
7
-
8
- it "should provide disconnect functionality" do
9
- @db.disconnect
10
- @db.pool.size.must_equal 0
11
- @db.test_connection
12
- @db.pool.size.must_equal 1
13
- end
14
-
15
- it "should provide disconnect functionality after preparing a statement" do
16
- @db.create_table!(:items){Integer :i}
17
- @db[:items].prepare(:first, :a).call
18
- @db.disconnect
19
- @db.pool.size.must_equal 0
20
- @db.drop_table?(:items)
21
- end
22
-
23
- it "should raise Sequel::DatabaseError on invalid SQL" do
24
- proc{@db << "S"}.must_raise(Sequel::DatabaseError)
25
- end
26
-
27
- it "should have Sequel::DatabaseError#sql give the SQL causing the error" do
28
- (@db << "SELECT") rescue (e = $!)
29
- e.sql.must_equal "SELECT"
30
- end if ENV['SEQUEL_ERROR_SQL']
31
-
32
- describe "constraint violations" do
33
- before do
34
- @db.drop_table?(:test2, :test)
35
- end
36
- after do
37
- @db.drop_table?(:test2, :test)
38
- end
39
-
40
- cspecify "should raise Sequel::UniqueConstraintViolation when a unique constraint is violated", [:jdbc, :sqlite], [:db2] do
41
- @db.create_table!(:test){String :a, :unique=>true, :null=>false}
42
- @db[:test].insert('1')
43
- proc{@db[:test].insert('1')}.must_raise(Sequel::UniqueConstraintViolation)
44
- @db[:test].insert('2')
45
- proc{@db[:test].update(:a=>'1')}.must_raise(Sequel::UniqueConstraintViolation)
46
- end
47
-
48
- cspecify "should raise Sequel::UniqueConstraintViolation when a unique constraint is violated for composite primary keys", [:jdbc, :sqlite], [:db2] do
49
- @db.create_table!(:test){String :a; String :b; primary_key [:a, :b]}
50
- @db[:test].insert(:a=>'1', :b=>'2')
51
- proc{@db[:test].insert(:a=>'1', :b=>'2')}.must_raise(Sequel::UniqueConstraintViolation)
52
- @db[:test].insert(:a=>'3', :b=>'4')
53
- proc{@db[:test].update(:a=>'1', :b=>'2')}.must_raise(Sequel::UniqueConstraintViolation)
54
- end
55
-
56
- cspecify "should raise Sequel::CheckConstraintViolation when a check constraint is violated", :mysql, [:db2], [proc{|db| db.sqlite_version < 30802}, :sqlite] do
57
- @db.create_table!(:test){String :a; check Sequel.~(:a=>'1')}
58
- proc{@db[:test].insert('1')}.must_raise(Sequel::CheckConstraintViolation)
59
- @db[:test].insert('2')
60
- proc{@db[:test].insert('1')}.must_raise(Sequel::CheckConstraintViolation)
61
- end
62
-
63
- cspecify "should raise Sequel::ForeignKeyConstraintViolation when a foreign key constraint is violated", [:jdbc, :sqlite], [:db2] do
64
- @db.create_table!(:test, :engine=>:InnoDB){primary_key :id}
65
- @db.create_table!(:test2, :engine=>:InnoDB){foreign_key :tid, :test}
66
- proc{@db[:test2].insert(:tid=>1)}.must_raise(Sequel::ForeignKeyConstraintViolation)
67
- @db[:test].insert
68
- @db[:test2].insert(:tid=>1)
69
- proc{@db[:test2].where(:tid=>1).update(:tid=>3)}.must_raise(Sequel::ForeignKeyConstraintViolation)
70
- proc{@db[:test].where(:id=>1).delete}.must_raise(Sequel::ForeignKeyConstraintViolation)
71
- end
72
-
73
- cspecify "should raise Sequel::NotNullConstraintViolation when a not null constraint is violated", [:jdbc, :sqlite], [:db2] do
74
- @db.create_table!(:test){Integer :a, :null=>false}
75
- proc{@db[:test].insert(:a=>nil)}.must_raise(Sequel::NotNullConstraintViolation)
76
- unless @db.database_type == :mysql
77
- # Broken mysql silently changes NULL here to 0, and doesn't raise an exception.
78
- @db[:test].insert(2)
79
- proc{@db[:test].update(:a=>nil)}.must_raise(Sequel::NotNullConstraintViolation)
80
- end
81
- end
82
- end
83
-
84
- it "should store underlying wrapped exception in Sequel::DatabaseError" do
85
- begin
86
- @db << "SELECT"
87
- rescue Sequel::DatabaseError=>e
88
- if defined?(Java::JavaLang::Exception)
89
- (e.wrapped_exception.is_a?(Exception) || e.wrapped_exception.is_a?(Java::JavaLang::Exception)).must_equal true
90
- else
91
- e.wrapped_exception.must_be_kind_of(Exception)
92
- end
93
- end
94
- end
95
-
96
- it "should not have the connection pool swallow non-StandardError based exceptions" do
97
- proc{@db.pool.hold{raise Interrupt, "test"}}.must_raise(Interrupt)
98
- end
99
-
100
- it "should be able to disconnect connections more than once without exceptions" do
101
- conn = @db.synchronize{|c| c}
102
- @db.disconnect
103
- @db.disconnect_connection(conn)
104
- @db.disconnect_connection(conn)
105
- end
106
-
107
- cspecify "should provide ability to check connections for validity", [:do, :postgres] do
108
- conn = @db.synchronize{|c| c}
109
- @db.valid_connection?(conn).must_equal true
110
- @db.disconnect
111
- @db.valid_connection?(conn).must_equal false
112
- end
113
- end
@@ -1,1808 +0,0 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
-
3
- describe "Simple Dataset operations" do
4
- before do
5
- @db = DB
6
- @db.create_table!(:items) do
7
- primary_key :id
8
- Integer :number
9
- end
10
- @ds = @db[:items]
11
- @ds.insert(:number=>10)
12
- end
13
- after do
14
- @db.drop_table?(:items)
15
- end
16
-
17
- it "should support sequential primary keys" do
18
- @ds << {:number=>20}
19
- @ds << {:number=>30}
20
- @ds.order(:number).all.must_equal [
21
- {:id => 1, :number=>10},
22
- {:id => 2, :number=>20},
23
- {:id => 3, :number=>30} ]
24
- end
25
-
26
- it "should support sequential primary keys with a Bignum" do
27
- @db.create_table!(:items) do
28
- primary_key :id, :type=>Bignum
29
- Integer :number
30
- end
31
- @ds << {:number=>20}
32
- @ds << {:number=>30}
33
- @ds.order(:number).all.must_equal [{:id => 1, :number=>20}, {:id => 2, :number=>30}]
34
- end
35
-
36
- cspecify "should insert with a primary key specified", :db2, :mssql do
37
- @ds.insert(:id=>100, :number=>20)
38
- @ds.count.must_equal 2
39
- @ds.order(:id).all.must_equal [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
40
- end
41
-
42
- it "should have insert return primary key value" do
43
- @ds.insert(:number=>20).must_equal 2
44
- @ds.filter(:id=>2).first[:number].must_equal 20
45
- end
46
-
47
- it "should have insert work correctly with static SQL" do
48
- @db["INSERT INTO #{@ds.literal(:items)} (#{@ds.literal(:number)}) VALUES (20)"].insert
49
- @ds.filter(:id=>2).first[:number].must_equal 20
50
- end
51
-
52
- it "should have insert_multiple return primary key values" do
53
- @ds.extension(:sequel_3_dataset_methods).insert_multiple([{:number=>20}, {:number=>30}]).must_equal [2, 3]
54
- @ds.filter(:id=>2).get(:number).must_equal 20
55
- @ds.filter(:id=>3).get(:number).must_equal 30
56
- end
57
-
58
- it "should join correctly" do
59
- @ds.join(:items___b, :id=>:id).select_all(:items).all.must_equal [{:id=>1, :number=>10}]
60
- end
61
-
62
- it "should handle LATERAL subqueries correctly" do
63
- @ds << {:number=>20}
64
- @ds.from(:items___i, @ds.where(:items__number=>:i__number).lateral).select_order_map([:i__number___n, :t1__number]).must_equal [[10, 10], [20, 20]]
65
- @ds.from(:items___i).cross_join(@ds.where(:items__number=>:i__number).lateral).select_order_map([:i__number___n, :t1__number]).must_equal [[10, 10], [20, 20]]
66
- @ds.from(:items___i).join(@ds.where(:items__number=>:i__number).lateral, 1=>1).select_order_map([:i__number___n, :t1__number]).must_equal [[10, 10], [20, 20]]
67
- @ds.from(:items___i).join(@ds.where(:items__number=>:i__number).lateral, 1=>0).select_order_map([:i__number___n, :t1__number]).must_equal []
68
- @ds.from(:items___i).left_join(@ds.from(:items___i2).where(:i2__number=>:i__number).lateral, 1=>1).select_order_map([:i__number___n, :t1__number]).must_equal [[10, 10], [20, 20]]
69
- @ds.from(:items___i).left_join(@ds.from(:items___i2).where(:i2__number=>:i__number).lateral, 1=>0).select_order_map([:i__number___n, :t1__number]).must_equal [[10, nil], [20, nil]]
70
- end if DB.dataset.supports_lateral_subqueries?
71
-
72
- it "should correctly deal with qualified columns and subselects" do
73
- @ds.from_self(:alias=>:a).select(:a__id, Sequel.qualify(:a, :number)).all.must_equal [{:id=>1, :number=>10}]
74
- @ds.join(@ds.as(:a), :id=>:id).select(:a__id, Sequel.qualify(:a, :number)).all.must_equal [{:id=>1, :number=>10}]
75
- end
76
-
77
- it "should graph correctly" do
78
- a = [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
79
- pr = proc{|t| @ds.graph(t, {:id=>:id}, :table_alias=>:b).extension(:graph_each).all.must_equal a}
80
- pr[:items]
81
- pr[:items___foo]
82
- pr[Sequel.identifier(:items)]
83
- pr[Sequel.identifier('items')]
84
- pr[Sequel.as(:items, :foo)]
85
- pr[Sequel.as(Sequel.identifier('items'), 'foo')]
86
- end
87
-
88
- it "should graph correctly with a subselect" do
89
- @ds.from_self(:alias=>:items).graph(@ds.from_self, {:id=>:id}, :table_alias=>:b).extension(:graph_each).all.must_equal [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
90
- end
91
-
92
- cspecify "should have insert work correctly when inserting a row with all NULL values", :hsqldb do
93
- @db.create_table!(:items) do
94
- String :name
95
- Integer :number
96
- end
97
- @ds.insert
98
- @ds.all.must_equal [{:name=>nil, :number=>nil}]
99
- end
100
-
101
- it "should delete correctly" do
102
- @ds.filter(1=>1).delete.must_equal 1
103
- @ds.count.must_equal 0
104
- end
105
-
106
- it "should update correctly" do
107
- @ds.update(:number=>Sequel.expr(:number)+1).must_equal 1
108
- @ds.all.must_equal [{:id=>1, :number=>11}]
109
- end
110
-
111
- cspecify "should have update return the number of matched rows", [:do, :mysql], [:ado] do
112
- @ds.update(:number=>:number).must_equal 1
113
- @ds.filter(:id=>1).update(:number=>:number).must_equal 1
114
- @ds.filter(:id=>2).update(:number=>:number).must_equal 0
115
- @ds.all.must_equal [{:id=>1, :number=>10}]
116
- end
117
-
118
- it "should iterate over records as they come in" do
119
- called = false
120
- @ds.each{|row| called = true; row.must_equal(:id=>1, :number=>10)}
121
- called.must_equal true
122
- end
123
-
124
- it "should support iterating over large numbers of records with paged_each" do
125
- (2..100).each{|i| @ds.insert(:number=>i*10)}
126
-
127
- [:offset, :filter].each do |strategy|
128
- rows = []
129
- @ds.order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
130
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
131
-
132
- rows = []
133
- @ds.order(:number).paged_each(:rows_per_fetch=>3, :strategy=>strategy){|row| rows << row}
134
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
135
-
136
- rows = []
137
- @ds.order(:number, :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
138
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
139
-
140
- rows = []
141
- @ds.reverse_order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
142
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}}.reverse)
143
-
144
- rows = []
145
- @ds.order(Sequel.desc(:number), :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
146
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}}.reverse)
147
- end
148
-
149
- rows = []
150
- @ds.order(:number).limit(50, 25).paged_each(:rows_per_fetch=>3){|row| rows << row}
151
- rows.must_equal((26..75).map{|i| {:id=>i, :number=>i*10}})
152
-
153
- rows = []
154
- @ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5){|row| rows << row}
155
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
156
-
157
- rows = []
158
- @ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5, :strategy=>:filter, :filter_values=>proc{|row, _| [row[:number] * 2]}){|row| rows << row}
159
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
160
-
161
- if DB.adapter_scheme == :jdbc
162
- # check retrival with varying fetch sizes
163
- array = (1..100).to_a
164
- [1, 2, 5, 10, 33, 50, 100, 1000].each do |i|
165
- @ds.with_fetch_size(i).select_order_map(:id).must_equal array
166
- end
167
- end
168
- end
169
-
170
- it "should fetch all results correctly" do
171
- @ds.all.must_equal [{:id=>1, :number=>10}]
172
- end
173
-
174
- it "should fetch a single row correctly" do
175
- @ds.first.must_equal(:id=>1, :number=>10)
176
- end
177
-
178
- it "should have distinct work with limit" do
179
- @ds.limit(1).distinct.all.must_equal [{:id=>1, :number=>10}]
180
- end
181
-
182
- it "should fetch correctly with a limit" do
183
- @ds.order(:id).limit(2).all.must_equal [{:id=>1, :number=>10}]
184
- @ds.insert(:number=>20)
185
- @ds.order(:id).limit(1).all.must_equal [{:id=>1, :number=>10}]
186
- @ds.order(:id).limit(2).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
187
- end
188
-
189
- it "should fetch correctly with a limit and offset" do
190
- @ds.order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10}]
191
- @ds.order(:id).limit(2, 1).all.must_equal []
192
- @ds.insert(:number=>20)
193
- @ds.order(:id).limit(1, 1).all.must_equal [{:id=>2, :number=>20}]
194
- @ds.order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
195
- @ds.order(:id).limit(2, 1).all.must_equal [{:id=>2, :number=>20}]
196
- end
197
-
198
- it "should fetch correctly with just offset" do
199
- @ds.order(:id).offset(0).all.must_equal [{:id=>1, :number=>10}]
200
- @ds.order(:id).offset(1).all.must_equal []
201
- @ds.insert(:number=>20)
202
- @ds.order(:id).offset(0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
203
- @ds.order(:id).offset(1).all.must_equal [{:id=>2, :number=>20}]
204
- @ds.order(:id).offset(2).all.must_equal []
205
- end
206
-
207
- it "should fetch correctly with a limit and offset using seperate methods" do
208
- @ds.order(:id).limit(2).offset(0).all.must_equal [{:id=>1, :number=>10}]
209
- @ds.order(:id).limit(2).offset(1).all.must_equal []
210
- @ds.insert(:number=>20)
211
- @ds.order(:id).limit(1).offset(1).all.must_equal [{:id=>2, :number=>20}]
212
- @ds.order(:id).limit(2).offset(0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
213
- @ds.order(:id).limit(2).offset(1).all.must_equal [{:id=>2, :number=>20}]
214
- end
215
-
216
- it "should provide correct columns when using a limit and offset" do
217
- ds = @ds.order(:id).limit(1, 1)
218
- ds.all
219
- ds.columns.must_equal [:id, :number]
220
- @ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
221
- end
222
-
223
- it "should fetch correctly with a limit and offset for different combinations of from and join tables" do
224
- @db.create_table!(:items2){primary_key :id2; Integer :number2}
225
- @db[:items2].insert(:number2=>10)
226
- @ds.from(:items, :items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
227
- @ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
228
- @ds.cross_join(:items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
229
- @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
230
- @ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10, :id3=>1, :number3=>10}]
231
-
232
- @ds.from(:items, :items2).order(:id).limit(2, 1).all.must_equal []
233
- @ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.must_equal []
234
- @ds.cross_join(:items2).order(:id).limit(2, 1).all.must_equal []
235
- @ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.must_equal []
236
- @ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.must_equal []
237
- @db.drop_table(:items2)
238
- end
239
-
240
- it "should fetch correctly with a limit and offset without an order" do
241
- @ds.limit(2, 1).all.must_equal []
242
- @ds.join(:items___i, :id=>:id).select(:items__id___s, :i__id___id2).limit(2, 1).all.must_equal []
243
- @ds.join(:items___i, :id=>:id).select(:items__id).limit(2, 1).all.must_equal []
244
- @ds.join(:items___i, :id=>:id).select(Sequel.qualify(:items, :id)).limit(2, 1).all.must_equal []
245
- @ds.join(:items___i, :id=>:id).select(Sequel.qualify(:items, :id).as(:s)).limit(2, 1).all.must_equal []
246
- end
247
-
248
- it "should be orderable by column number" do
249
- @ds.insert(:number=>20)
250
- @ds.insert(:number=>10)
251
- @ds.order(2, 1).select_map([:id, :number]).must_equal [[1, 10], [3, 10], [2, 20]]
252
- end
253
-
254
- it "should fetch correctly with a limit in an IN subselect" do
255
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.must_equal [{:id=>1, :number=>10}]
256
- @ds.insert(:number=>20)
257
- @ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.must_equal [{:id=>1, :number=>10}]
258
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
259
- end
260
-
261
- it "should fetch correctly with a limit and offset in an IN subselect" do
262
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.must_equal [{:id=>1, :number=>10}]
263
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.must_equal []
264
- @ds.insert(:number=>20)
265
- @ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.must_equal [{:id=>2, :number=>20}]
266
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
267
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.must_equal [{:id=>2, :number=>20}]
268
- end
269
-
270
- it "should fetch correctly when using limit and offset in a from_self" do
271
- @ds.insert(:number=>20)
272
- ds = @ds.order(:id).limit(1, 1).from_self
273
- ds.all.must_equal [{:number=>20, :id=>2}]
274
- ds.columns.must_equal [:id, :number]
275
- @ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
276
- end
277
-
278
- it "should fetch correctly when using nested limit and offset in a from_self" do
279
- @ds.insert(:number=>20)
280
- @ds.insert(:number=>30)
281
- ds = @ds.order(:id).limit(2, 1).from_self.reverse_order(:number).limit(1, 1)
282
- ds.all.must_equal [{:number=>20, :id=>2}]
283
- ds.columns.must_equal [:id, :number]
284
- @ds.order(:id).limit(2, 1).from_self.reverse_order(:number).limit(1, 1).columns.must_equal [:id, :number]
285
-
286
- ds = @ds.order(:id).limit(3, 1).from_self.limit(2, 1).from_self.limit(1, 1)
287
- ds.all.must_equal []
288
- ds.columns.must_equal [:id, :number]
289
-
290
- @ds.insert(:number=>40)
291
- ds = @ds.order(:id).limit(3, 1).from_self.reverse_order(:number).limit(2, 1).from_self.reverse_order(:id).limit(1, 1)
292
- ds.all.must_equal [{:number=>20, :id=>2}]
293
- ds.columns.must_equal [:id, :number]
294
- end
295
-
296
- it "should alias columns correctly" do
297
- @ds.select(:id___x, :number___n).first.must_equal(:x=>1, :n=>10)
298
- end
299
-
300
- it "should support table aliases with column aliases" do
301
- DB.from(@ds.as(:i, [:x, :n])).first.must_equal(:x=>1, :n=>10)
302
- end if DB.dataset.supports_derived_column_lists?
303
-
304
- it "should handle true/false properly" do
305
- @ds.filter(Sequel::TRUE).select_map(:number).must_equal [10]
306
- @ds.filter(Sequel::FALSE).select_map(:number).must_equal []
307
- @ds.filter(true).select_map(:number).must_equal [10]
308
- @ds.filter(false).select_map(:number).must_equal []
309
- end
310
- end
311
-
312
- describe "Simple dataset operations with nasty table names" do
313
- before do
314
- @db = DB
315
- @table = :"i`t' [e]\"m\\s"
316
- @qi = @db.quote_identifiers?
317
- @db.quote_identifiers = true
318
- end
319
- after do
320
- @db.quote_identifiers = @qi
321
- end
322
-
323
- cspecify "should work correctly", :oracle, :sqlanywhere, [:jdbc, :mssql] do
324
- @db.create_table!(@table) do
325
- primary_key :id
326
- Integer :number
327
- end
328
- @ds = @db[@table]
329
- @ds.insert(:number=>10).must_equal 1
330
- @ds.all.must_equal [{:id=>1, :number=>10}]
331
- @ds.update(:number=>20).must_equal 1
332
- @ds.all.must_equal [{:id=>1, :number=>20}]
333
- @ds.delete.must_equal 1
334
- @ds.count.must_equal 0
335
- @db.drop_table?(@table)
336
- end
337
- end
338
-
339
- describe Sequel::Dataset do
340
- before do
341
- DB.create_table!(:test) do
342
- String :name
343
- Integer :value
344
- end
345
- @d = DB[:test]
346
- end
347
- after do
348
- DB.drop_table?(:test)
349
- end
350
-
351
- it "should return the correct record count" do
352
- @d.count.must_equal 0
353
- @d << {:name => 'abc', :value => 123}
354
- @d << {:name => 'abc', :value => 456}
355
- @d << {:name => 'def', :value => 789}
356
- @d.count.must_equal 3
357
- end
358
-
359
- it "should handle functions with identifier names correctly" do
360
- @d << {:name => 'abc', :value => 6}
361
- @d.get{sum.function(:value)}.must_equal 6
362
- end
363
-
364
- it "should handle aggregate methods on limited datasets correctly" do
365
- @d << {:name => 'abc', :value => 6}
366
- @d << {:name => 'bcd', :value => 12}
367
- @d << {:name => 'def', :value => 18}
368
- @d = @d.order(:name).limit(2)
369
- @d.count.must_equal 2
370
- @d.avg(:value).to_i.must_equal 9
371
- @d.min(:value).to_i.must_equal 6
372
- @d.reverse.min(:value).to_i.must_equal 12
373
- @d.max(:value).to_i.must_equal 12
374
- @d.sum(:value).to_i.must_equal 18
375
- @d.interval(:value).to_i.must_equal 6
376
- end
377
-
378
- it "should return the correct records" do
379
- @d.to_a.must_equal []
380
- @d << {:name => 'abc', :value => 123}
381
- @d << {:name => 'abc', :value => 456}
382
- @d << {:name => 'def', :value => 789}
383
-
384
- @d.order(:value).to_a.must_equal [
385
- {:name => 'abc', :value => 123},
386
- {:name => 'abc', :value => 456},
387
- {:name => 'def', :value => 789}
388
- ]
389
- end
390
-
391
- it "should update records correctly" do
392
- @d << {:name => 'abc', :value => 123}
393
- @d << {:name => 'abc', :value => 456}
394
- @d << {:name => 'def', :value => 789}
395
- @d.filter(:name => 'abc').update(:value => 530)
396
- @d[:name => 'def'][:value].must_equal 789
397
- @d.filter(:value => 530).count.must_equal 2
398
- end
399
-
400
- it "should delete records correctly" do
401
- @d << {:name => 'abc', :value => 123}
402
- @d << {:name => 'abc', :value => 456}
403
- @d << {:name => 'def', :value => 789}
404
- @d.filter(:name => 'abc').delete
405
- @d.count.must_equal 1
406
- @d.first[:name].must_equal 'def'
407
- end
408
-
409
- it "should be able to truncate the table" do
410
- @d << {:name => 'abc', :value => 123}
411
- @d << {:name => 'abc', :value => 456}
412
- @d << {:name => 'def', :value => 789}
413
- @d.count.must_equal 3
414
- @d.truncate.must_equal nil
415
- @d.count.must_equal 0
416
- end
417
-
418
- it "should be able to literalize booleans" do
419
- @d.literal(true)
420
- @d.literal(false)
421
- end
422
- end
423
-
424
- describe Sequel::Database do
425
- it "should correctly escape strings" do
426
- ["\\\n",
427
- "\\\\\n",
428
- "\\\r\n",
429
- "\\\\\r\n",
430
- "\\\\\n\n",
431
- "\\\\\r\n\r\n",
432
- "\\dingo",
433
- "\\'dingo",
434
- "\\\\''dingo",
435
- ].each do |str|
436
- DB.get(Sequel.cast(str, String)).must_equal str
437
- str = "1#{str}1"
438
- DB.get(Sequel.cast(str, String)).must_equal str
439
- str = "#{str}#{str}"
440
- DB.get(Sequel.cast(str, String)).must_equal str
441
- end
442
- end
443
-
444
- cspecify "should properly escape binary data", [:odbc], [:jdbc, :hsqldb], :oracle do
445
- DB.get(Sequel.cast(Sequel.blob("\1\2\3"), File).as(:a)).must_equal "\1\2\3"
446
- end
447
-
448
- cspecify "should properly handle empty blobs", [:jdbc, :hsqldb], :oracle do
449
- DB.get(Sequel.cast(Sequel.blob(""), File).as(:a)).must_equal ""
450
- end
451
-
452
- cspecify "should properly escape identifiers", :db2, :oracle, :sqlanywhere do
453
- DB.create_table(:"\\'\"[]"){Integer :id}
454
- DB.drop_table(:"\\'\"[]")
455
- end
456
-
457
- it "should have a working table_exists?" do
458
- t = :basdfdsafsaddsaf
459
- DB.drop_table?(t)
460
- DB.table_exists?(t).must_equal false
461
- DB.create_table(t){Integer :a}
462
- begin
463
- DB.table_exists?(t).must_equal true
464
- ensure
465
- DB.drop_table(t)
466
- end
467
- end
468
- end
469
-
470
- describe Sequel::Dataset do
471
- before do
472
- DB.create_table! :items do
473
- primary_key :id
474
- Integer :value
475
- end
476
- @d = DB[:items]
477
- @d << {:value => 123}
478
- @d << {:value => 456}
479
- @d << {:value => 789}
480
- end
481
- after do
482
- DB.drop_table?(:items)
483
- end
484
-
485
- it "should correctly return avg" do
486
- @d.avg(:value).to_i.must_equal 456
487
- end
488
-
489
- it "should correctly return sum" do
490
- @d.sum(:value).to_i.must_equal 1368
491
- end
492
-
493
- it "should correctly return max" do
494
- @d.max(:value).to_i.must_equal 789
495
- end
496
-
497
- it "should correctly return min" do
498
- @d.min(:value).to_i.must_equal 123
499
- end
500
- end
501
-
502
- describe "Simple Dataset operations" do
503
- before do
504
- DB.create_table!(:items) do
505
- Integer :number
506
- TrueClass :flag
507
- end
508
- @ds = DB[:items]
509
- end
510
- after do
511
- DB.drop_table?(:items)
512
- end
513
-
514
- it "should deal with boolean conditions correctly" do
515
- @ds.insert(:number=>1, :flag=>true)
516
- @ds.insert(:number=>2, :flag=>false)
517
- @ds.insert(:number=>3, :flag=>nil)
518
- @ds.order!(:number)
519
- @ds.filter(:flag=>true).map(:number).must_equal [1]
520
- @ds.filter(:flag=>false).map(:number).must_equal [2]
521
- @ds.filter(:flag=>nil).map(:number).must_equal [3]
522
- @ds.exclude(:flag=>true).map(:number).must_equal [2, 3]
523
- @ds.exclude(:flag=>false).map(:number).must_equal [1, 3]
524
- @ds.exclude(:flag=>nil).map(:number).must_equal [1, 2]
525
- end
526
- end
527
-
528
- describe "Simple Dataset operations in transactions" do
529
- before do
530
- DB.create_table!(:items) do
531
- primary_key :id
532
- integer :number
533
- end
534
- @ds = DB[:items]
535
- end
536
- after do
537
- DB.drop_table?(:items)
538
- end
539
-
540
- cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
541
- DB.transaction do
542
- @ds.insert(:id=>100, :number=>20)
543
- @ds.count.must_equal 1
544
- @ds.order(:id).all.must_equal [{:id=>100, :number=>20}]
545
- end
546
- end
547
-
548
- it "should have insert return primary key value inside a transaction" do
549
- DB.transaction do
550
- @ds.insert(:number=>20).must_equal 1
551
- @ds.count.must_equal 1
552
- @ds.order(:id).all.must_equal [{:id=>1, :number=>20}]
553
- end
554
- end
555
-
556
- it "should support for_update" do
557
- DB.transaction{@ds.for_update.all.must_equal []}
558
- end
559
- end
560
-
561
- describe "Dataset UNION, EXCEPT, and INTERSECT" do
562
- before do
563
- DB.create_table!(:i1){integer :number}
564
- DB.create_table!(:i2){integer :number}
565
- @ds1 = DB[:i1]
566
- @ds1.insert(:number=>10)
567
- @ds1.insert(:number=>20)
568
- @ds2 = DB[:i2]
569
- @ds2.insert(:number=>10)
570
- @ds2.insert(:number=>30)
571
- end
572
- after do
573
- DB.drop_table?(:i1, :i2, :i3)
574
- end
575
-
576
- it "should give the correct results for simple UNION, EXCEPT, and INTERSECT" do
577
- @ds1.union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30'
578
- if @ds1.supports_intersect_except?
579
- @ds1.except(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
580
- @ds1.intersect(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
581
- end
582
- end
583
-
584
- cspecify "should give the correct results for UNION, EXCEPT, and INTERSECT when used with ordering and limits", :mssql do
585
- @ds1.insert(:number=>8)
586
- @ds2.insert(:number=>9)
587
- @ds1.insert(:number=>38)
588
- @ds2.insert(:number=>39)
589
-
590
- @ds1.reverse_order(:number).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
591
- @ds1.union(@ds2.reverse_order(:number)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
592
-
593
- @ds1.reverse_order(:number).limit(1).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 30 38 39'
594
- @ds2.reverse_order(:number).limit(1).union(@ds1).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 38 39'
595
-
596
- @ds1.union(@ds2.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 38'
597
- @ds2.union(@ds1.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 30 39'
598
-
599
- @ds1.union(@ds2).limit(2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9'
600
- @ds2.union(@ds1).reverse_order(:number).limit(2).map{|x| x[:number].to_s}.must_equal %w'39 38'
601
-
602
- @ds1.reverse_order(:number).limit(2).union(@ds2.reverse_order(:number).limit(2)).order(:number).limit(3).map{|x| x[:number].to_s}.must_equal %w'20 30 38'
603
- @ds2.order(:number).limit(2).union(@ds1.order(:number).limit(2)).reverse_order(:number).limit(3).map{|x| x[:number].to_s}.must_equal %w'10 9 8'
604
- end
605
-
606
- it "should give the correct results for compound UNION, EXCEPT, and INTERSECT" do
607
- DB.create_table!(:i3){integer :number}
608
- @ds3 = DB[:i3]
609
- @ds3.insert(:number=>10)
610
- @ds3.insert(:number=>40)
611
-
612
- @ds1.union(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30 40'
613
- @ds1.union(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30 40'
614
- if @ds1.supports_intersect_except?
615
- @ds1.union(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'20 30'
616
- @ds1.union(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30'
617
- @ds1.union(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 '
618
- @ds1.union(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20'
619
-
620
- @ds1.except(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 40'
621
- @ds1.except(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
622
- @ds1.except(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
623
- @ds1.except(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20'
624
- @ds1.except(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w''
625
- @ds1.except(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
626
-
627
- @ds1.intersect(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 40'
628
- @ds1.intersect(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
629
- @ds1.intersect(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w''
630
- @ds1.intersect(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w''
631
- @ds1.intersect(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
632
- @ds1.intersect(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
633
- end
634
- end
635
- end
636
-
637
- if DB.dataset.supports_cte?
638
- describe "Common Table Expressions" do
639
- before(:all) do
640
- @db = DB
641
- @db.create_table!(:i1){Integer :id; Integer :parent_id}
642
- @ds = @db[:i1]
643
- @ds.insert(:id=>1)
644
- @ds.insert(:id=>2)
645
- @ds.insert(:id=>3, :parent_id=>1)
646
- @ds.insert(:id=>4, :parent_id=>1)
647
- @ds.insert(:id=>5, :parent_id=>3)
648
- @ds.insert(:id=>6, :parent_id=>5)
649
- end
650
- after(:all) do
651
- @db.drop_table?(:i1)
652
- end
653
-
654
- it "should give correct results for WITH" do
655
- @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).must_equal [1, 2]
656
- end
657
-
658
- cspecify "should give correct results for recursive WITH", :db2 do
659
- ds = @db[:t].select(:i___id, :pi___parent_id).with_recursive(:t, @ds.filter(:parent_id=>nil), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi]).order(:id)
660
- ds.all.must_equal [{:parent_id=>nil, :id=>1}, {:parent_id=>nil, :id=>2}, {:parent_id=>1, :id=>3}, {:parent_id=>1, :id=>4}, {:parent_id=>3, :id=>5}, {:parent_id=>5, :id=>6}]
661
- ps = @db[:t].select(:i___id, :pi___parent_id).with_recursive(:t, @ds.filter(:parent_id=>:$n), @ds.join(:t, :i=>:parent_id).filter(:t__i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi]).order(:id).prepare(:select, :cte_sel)
662
- ps.call(:n=>1).must_equal [{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}, {:id=>5, :parent_id=>3}, {:id=>6, :parent_id=>5}]
663
- ps.call(:n=>3).must_equal [{:id=>5, :parent_id=>3}, {:id=>6, :parent_id=>5}]
664
- ps.call(:n=>5).must_equal [{:id=>6, :parent_id=>5}]
665
- end
666
-
667
- it "should support joining a dataset with a CTE" do
668
- @ds.inner_join(@db[:t].with(:t, @ds.filter(:parent_id=>nil)), :id => :id).select(:i1__id).order(:i1__id).map(:id).must_equal [1,2]
669
- @db[:t].with(:t, @ds).inner_join(@db[:s].with(:s, @ds.filter(:parent_id=>nil)), :id => :id).select(:t__id).order(:t__id).map(:id).must_equal [1,2]
670
- end
671
-
672
- it "should support a subselect in the FROM clause with a CTE" do
673
- @ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
674
- @db[:t].with(:t, @ds).from_self.select_order_map(:id).must_equal [1,2,3,4,5,6]
675
- end
676
-
677
- it "should support using a CTE inside a CTE" do
678
- @db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
679
- @db[:s].with_recursive(:s, @db[:t].with(:t, @ds), @db[:t2].with(:t2, @ds)).select_order_map(:id).must_equal [1,1,2,2,3,3,4,4,5,5,6,6]
680
- end
681
-
682
- it "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
683
- @ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
684
- if @ds.supports_intersect_except?
685
- @ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
686
- @ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal []
687
- end
688
- end
689
- end
690
- end
691
-
692
- if DB.dataset.supports_cte?(:update) # Assume INSERT and DELETE support as well
693
- describe "Common Table Expressions in INSERT/UPDATE/DELETE" do
694
- before do
695
- @db = DB
696
- @db.create_table!(:i1){Integer :id}
697
- @ds = @db[:i1]
698
- @ds2 = @ds.with(:t, @ds)
699
- @ds.insert(:id=>1)
700
- @ds.insert(:id=>2)
701
- end
702
- after do
703
- @db.drop_table?(:i1)
704
- end
705
-
706
- it "should give correct results for WITH" do
707
- @ds2.insert(@db[:t])
708
- @ds.select_order_map(:id).must_equal [1, 1, 2, 2]
709
- @ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>Sequel.+(:id, 1))
710
- @ds.select_order_map(:id).must_equal [1, 1, 3, 3]
711
- @ds2.filter(:id=>@db[:t].select{max(id)}).delete
712
- @ds.select_order_map(:id).must_equal [1, 1]
713
- end
714
- end
715
- end
716
-
717
- if DB.dataset.supports_returning?(:insert)
718
- describe "RETURNING clauses in INSERT" do
719
- before do
720
- @db = DB
721
- @db.create_table!(:i1){Integer :id; Integer :foo}
722
- @ds = @db[:i1]
723
- end
724
- after do
725
- @db.drop_table?(:i1)
726
- end
727
-
728
- it "should give correct results" do
729
- h = {}
730
- @ds.returning(:foo).insert(1, 2){|r| h = r}
731
- h.must_equal(:foo=>2)
732
- @ds.returning(:id).insert(3, 4){|r| h = r}
733
- h.must_equal(:id=>3)
734
- @ds.returning.insert(5, 6){|r| h = r}
735
- h.must_equal(:id=>5, :foo=>6)
736
- @ds.returning(:id___foo, :foo___id).insert(7, 8){|r| h = r}
737
- h.must_equal(:id=>8, :foo=>7)
738
- end
739
- end
740
- end
741
-
742
- if DB.dataset.supports_returning?(:update) # Assume DELETE support as well
743
- describe "RETURNING clauses in UPDATE/DELETE" do
744
- before do
745
- @db = DB
746
- @db.create_table!(:i1){Integer :id; Integer :foo}
747
- @ds = @db[:i1]
748
- @ds.insert(1, 2)
749
- end
750
- after do
751
- @db.drop_table?(:i1)
752
- end
753
-
754
- it "should give correct results" do
755
- h = []
756
- @ds.returning(:foo).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
757
- h.must_equal [{:foo=>4}]
758
- h.clear
759
- @ds.returning(:id).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
760
- h.must_equal [{:id=>3}]
761
- h.clear
762
- @ds.returning.update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
763
- h.must_equal [{:id=>4, :foo=>16}]
764
- h.clear
765
- @ds.returning(:id___foo, :foo___id).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
766
- h.must_equal [{:id=>32, :foo=>5}]
767
- h.clear
768
-
769
- @ds.returning.delete{|r| h << r}
770
- h.must_equal [{:id=>5, :foo=>32}]
771
- h.clear
772
- @ds.returning.delete{|r| h << r}
773
- h.must_equal []
774
- end
775
- end
776
- end
777
-
778
- if DB.dataset.supports_window_functions?
779
- describe "Window Functions" do
780
- before(:all) do
781
- @db = DB
782
- @db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
783
- @ds = @db[:i1].order(:id)
784
- @ds.insert(:id=>1, :group_id=>1, :amount=>1)
785
- @ds.insert(:id=>2, :group_id=>1, :amount=>10)
786
- @ds.insert(:id=>3, :group_id=>1, :amount=>100)
787
- @ds.insert(:id=>4, :group_id=>2, :amount=>1000)
788
- @ds.insert(:id=>5, :group_id=>2, :amount=>10000)
789
- @ds.insert(:id=>6, :group_id=>2, :amount=>100000)
790
- end
791
- after(:all) do
792
- @db.drop_table?(:i1)
793
- end
794
-
795
- it "should give correct results for aggregate window functions" do
796
- @ds.select(:id){sum(:amount).over(:partition=>:group_id).as(:sum)}.all.
797
- must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
798
- @ds.select(:id){sum(:amount).over.as(:sum)}.all.
799
- must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
800
- end
801
-
802
- it "should give correct results for ranking window functions with orders" do
803
- @ds.select(:id){rank{}.over(:partition=>:group_id, :order=>:id).as(:rank)}.all.
804
- must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>1, :id=>4}, {:rank=>2, :id=>5}, {:rank=>3, :id=>6}]
805
- @ds.select(:id){rank{}.over(:order=>id).as(:rank)}.all.
806
- must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>4, :id=>4}, {:rank=>5, :id=>5}, {:rank=>6, :id=>6}]
807
- end
808
-
809
- it "should give correct results for aggregate window functions with orders" do
810
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id).as(:sum)}.all.
811
- must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
812
- @ds.select(:id){sum(:amount).over(:order=>:id).as(:sum)}.all.
813
- must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
814
- end
815
-
816
- it "should give correct results for aggregate window functions with frames" do
817
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:all).as(:sum)}.all.
818
- must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
819
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:all).as(:sum)}.all.
820
- must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
821
-
822
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:rows).as(:sum)}.all.
823
- must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
824
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:rows).as(:sum)}.all.
825
- must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
826
- end
827
- end
828
- end
829
-
830
- describe Sequel::SQL::Constants do
831
- before do
832
- @db = DB
833
- @ds = @db[:constants]
834
- @c = proc do |v|
835
- case v
836
- when Time
837
- v
838
- when DateTime, String
839
- Time.parse(v.to_s)
840
- else
841
- v
842
- end
843
- end
844
- @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
845
- end
846
- after do
847
- @db.drop_table?(:constants)
848
- end
849
-
850
- cspecify "should have working CURRENT_DATE", [:jdbc, :sqlite], :oracle do
851
- @db.create_table!(:constants){Date :d}
852
- @ds.insert(:d=>Sequel::CURRENT_DATE)
853
- d = @c2[@ds.get(:d)]
854
- d.must_be_kind_of(Date)
855
- d.to_s.must_equal Date.today.to_s
856
- end
857
-
858
- cspecify "should have working CURRENT_TIME", [:jdbc, :sqlite], [:mysql2] do
859
- @db.create_table!(:constants){Time :t, :only_time=>true}
860
- @ds.insert(:t=>Sequel::CURRENT_TIME)
861
- (Time.now - @c[@ds.get(:t)]).must_be_close_to 0, 60
862
- end
863
-
864
- cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite], [:swift] do
865
- @db.create_table!(:constants){DateTime :ts}
866
- @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
867
- (Time.now - @c[@ds.get(:ts)]).must_be_close_to 0, 60
868
- end
869
-
870
- cspecify "should have working CURRENT_TIMESTAMP when used as a column default", [:jdbc, :sqlite], [:swift] do
871
- @db.create_table!(:constants){DateTime :ts, :default=>Sequel::CURRENT_TIMESTAMP}
872
- @ds.insert
873
- (Time.now - @c[@ds.get(:ts)]).must_be_close_to 0, 60
874
- end
875
- end
876
-
877
- describe "Sequel::Dataset#import and #multi_insert" do
878
- before(:all) do
879
- @db = DB
880
- @db.create_table!(:imp){Integer :i}
881
- @ids = @db[:imp].order(:i)
882
- end
883
- before do
884
- @ids.delete
885
- end
886
- after(:all) do
887
- @db.drop_table?(:imp)
888
- end
889
-
890
- it "should import with multi_insert and an array of hashes" do
891
- @ids.multi_insert([{:i=>10}, {:i=>20}])
892
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
893
- end
894
-
895
- it "should import with an array of arrays of values" do
896
- @ids.import([:i], [[10], [20]])
897
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
898
- end
899
-
900
- it "should import with a dataset" do
901
- @db.create_table!(:exp2){Integer :i}
902
- @db[:exp2].import([:i], [[10], [20]])
903
- @ids.import([:i], @db[:exp2])
904
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
905
- @db.drop_table(:exp2)
906
- end
907
-
908
- it "should have import work with the :slice_size option" do
909
- @ids.import([:i], [[10], [20], [30]], :slice_size=>1)
910
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
911
- @ids.delete
912
- @ids.import([:i], [[10], [20], [30]], :slice_size=>2)
913
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
914
- @ids.delete
915
- @ids.import([:i], [[10], [20], [30]], :slice_size=>3)
916
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
917
- end
918
-
919
- it "should import many rows at once" do
920
- @ids.import([:i], (1..1000).to_a.map{|x| [x]})
921
- @ids.select_order_map(:i).must_equal((1..1000).to_a)
922
- end
923
- end
924
-
925
- describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
926
- before do
927
- @db = DB
928
- @db.create_table!(:imp){primary_key :id; Integer :i}
929
- @ds = @db[:imp]
930
- end
931
- after do
932
- @db.drop_table?(:imp)
933
- end
934
-
935
- it "should return primary key values" do
936
- @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).must_equal [1, 2, 3]
937
- @ds.import([:i], [[40], [50], [60]], :return=>:primary_key).must_equal [4, 5, 6]
938
- @ds.order(:id).map([:id, :i]).must_equal [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
939
- end
940
-
941
- it "should return primary key values when :slice is used" do
942
- @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).must_equal [1, 2, 3]
943
- @ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).must_equal [4, 5, 6]
944
- @ds.order(:id).map([:id, :i]).must_equal [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
945
- end
946
- end
947
-
948
- describe "Sequel::Dataset convenience methods" do
949
- before(:all) do
950
- @db = DB
951
- @db.create_table!(:a){Integer :a; Integer :b; Integer :c}
952
- @ds = @db[:a]
953
- @ds.insert(1, 3, 5)
954
- @ds.insert(1, 3, 6)
955
- @ds.insert(1, 4, 5)
956
- @ds.insert(2, 3, 5)
957
- @ds.insert(2, 4, 6)
958
- end
959
- after(:all) do
960
- @db.drop_table?(:a)
961
- end
962
-
963
- it "#group_rollup should include hierarchy of groupings" do
964
- @ds.group_by(:a).group_rollup.select_map([:a, Sequel.function(:sum, :b).cast(Integer).as(:b), Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, 17, 27], [1, 10, 16], [2, 7, 11]]
965
- @ds.group_by(:a, :b).group_rollup.select_map([:a, :b, Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, nil, 27], [1, nil, 16], [1, 3, 11], [1, 4, 5], [2, nil, 11], [2, 3, 5], [2, 4, 6]]
966
- end if DB.dataset.supports_group_rollup?
967
-
968
- it "#group_cube should include all combinations of groupings" do
969
- @ds.group_by(:a).group_cube.select_map([:a, Sequel.function(:sum, :b).cast(Integer).as(:b), Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, 17, 27], [1, 10, 16], [2, 7, 11]]
970
- @ds.group_by(:a, :b).group_cube.select_map([:a, :b, Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, nil, 27], [nil, 3, 16], [nil, 4, 11], [1, nil, 16], [1, 3, 11], [1, 4, 5], [2, nil, 11], [2, 3, 5], [2, 4, 6]]
971
- end if DB.dataset.supports_group_cube?
972
-
973
- it "#grouping_sets should include sets specified in group" do
974
- @ds.group_by(:a, []).grouping_sets.select_map([:a, Sequel.function(:sum, :b).cast(Integer).as(:b), Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, 17, 27], [1, 10, 16], [2, 7, 11]]
975
- @ds.group_by([:a, :b], :a, :b, []).grouping_sets.select_map([:a, :b, Sequel.function(:sum, :c).cast(Integer).as(:c)]).sort_by{|x| x.map(&:to_i)}.must_equal [[nil, nil, 27], [nil, 3, 16], [nil, 4, 11], [1, nil, 16], [1, 3, 11], [1, 4, 5], [2, nil, 11], [2, 3, 5], [2, 4, 6]]
976
- end if DB.dataset.supports_grouping_sets?
977
- end
978
-
979
- describe "Sequel::Dataset convenience methods" do
980
- before(:all) do
981
- @db = DB
982
- @db.create_table!(:a){Integer :a; Integer :b}
983
- @ds = @db[:a].order(:a)
984
- end
985
- before do
986
- @ds.delete
987
- end
988
- after(:all) do
989
- @db.drop_table?(:a)
990
- end
991
-
992
- it "#[]= should update matching rows" do
993
- @ds.insert(20, 10)
994
- @ds.extension(:sequel_3_dataset_methods)[:a=>20] = {:b=>30}
995
- @ds.all.must_equal [{:a=>20, :b=>30}]
996
- end
997
-
998
- it "#empty? should return whether the dataset returns no rows" do
999
- @ds.empty?.must_equal true
1000
- @ds.insert(20, 10)
1001
- @ds.empty?.must_equal false
1002
- end
1003
-
1004
- it "#empty? should work correctly for datasets with limits" do
1005
- ds = @ds.limit(1)
1006
- ds.empty?.must_equal true
1007
- ds.insert(20, 10)
1008
- ds.empty?.must_equal false
1009
- end
1010
-
1011
- it "#empty? should work correctly for datasets with limits and offsets" do
1012
- ds = @ds.limit(1, 1)
1013
- ds.empty?.must_equal true
1014
- ds.insert(20, 10)
1015
- ds.empty?.must_equal true
1016
- ds.insert(20, 10)
1017
- ds.empty?.must_equal false
1018
- end
1019
-
1020
- it "#group_and_count should return a grouping by count" do
1021
- @ds.group_and_count(:a).order{count(:a)}.all.must_equal []
1022
- @ds.insert(20, 10)
1023
- @ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>1}]
1024
- @ds.insert(20, 30)
1025
- @ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>2}]
1026
- @ds.insert(30, 30)
1027
- @ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>30, :count=>1}, {:a=>20, :count=>2}]
1028
- end
1029
-
1030
- it "#group_and_count should support column aliases" do
1031
- @ds.group_and_count(:a___c).order{count(:a)}.all.must_equal []
1032
- @ds.insert(20, 10)
1033
- @ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>1}]
1034
- @ds.insert(20, 30)
1035
- @ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>2}]
1036
- @ds.insert(30, 30)
1037
- @ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>30, :count=>1}, {:c=>20, :count=>2}]
1038
- end
1039
-
1040
- it "#range should return the range between the maximum and minimum values" do
1041
- @ds = @ds.unordered
1042
- @ds.insert(20, 10)
1043
- @ds.insert(30, 10)
1044
- @ds.range(:a).must_equal(20..30)
1045
- @ds.range(:b).must_equal(10..10)
1046
- end
1047
-
1048
- it "#interval should return the different between the maximum and minimum values" do
1049
- @ds = @ds.unordered
1050
- @ds.insert(20, 10)
1051
- @ds.insert(30, 10)
1052
- @ds.interval(:a).to_i.must_equal 10
1053
- @ds.interval(:b).to_i.must_equal 0
1054
- end
1055
- end
1056
-
1057
- describe "Sequel::Dataset main SQL methods" do
1058
- before(:all) do
1059
- @db = DB
1060
- @db.create_table!(:d){Integer :a; Integer :b}
1061
- @ds = @db[:d].order(:a)
1062
- end
1063
- before do
1064
- @ds.delete
1065
- end
1066
- after(:all) do
1067
- @db.drop_table?(:d)
1068
- end
1069
-
1070
- it "#exists should return a usable exists clause" do
1071
- @ds.filter(@db[:d___c].filter(:c__a=>:d__b).exists).all.must_equal []
1072
- @ds.insert(20, 30)
1073
- @ds.insert(10, 20)
1074
- @ds.filter(@db[:d___c].filter(:c__a=>:d__b).exists).all.must_equal [{:a=>10, :b=>20}]
1075
- end
1076
-
1077
- it "#filter and #exclude should work with placeholder strings" do
1078
- @ds.insert(20, 30)
1079
- @ds.filter("a > ?", 15).all.must_equal [{:a=>20, :b=>30}]
1080
- @ds.exclude("b < ?", 15).all.must_equal [{:a=>20, :b=>30}]
1081
- @ds.filter("b < ?", 15).invert.all.must_equal [{:a=>20, :b=>30}]
1082
- end
1083
-
1084
- it "#and and #or should work correctly" do
1085
- @ds.insert(20, 30)
1086
- @ds.filter(:a=>20).and(:b=>30).all.must_equal [{:a=>20, :b=>30}]
1087
- @ds.filter(:a=>20).and(:b=>15).all.must_equal []
1088
- @ds.filter(:a=>20).or(:b=>15).all.must_equal [{:a=>20, :b=>30}]
1089
- @ds.filter(:a=>10).or(:b=>15).all.must_equal []
1090
- end
1091
-
1092
- it "#select_group should work correctly" do
1093
- @ds.unordered!
1094
- @ds.select_group(:a).all.must_equal []
1095
- @ds.insert(20, 30)
1096
- @ds.select_group(:a).all.must_equal [{:a=>20}]
1097
- @ds.select_group(:b).all.must_equal [{:b=>30}]
1098
- @ds.insert(20, 40)
1099
- @ds.select_group(:a).all.must_equal [{:a=>20}]
1100
- @ds.order(:b).select_group(:b).all.must_equal [{:b=>30}, {:b=>40}]
1101
- end
1102
-
1103
- it "#select_group should work correctly when aliasing" do
1104
- @ds.unordered!
1105
- @ds.insert(20, 30)
1106
- @ds.select_group(:b___c).all.must_equal [{:c=>30}]
1107
- end
1108
-
1109
- it "#having should work correctly" do
1110
- @ds.unordered!
1111
- @ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
1112
- @ds.insert(20, 30)
1113
- @ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
1114
- @ds.insert(40, 20)
1115
- @ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.must_equal [{:b=>20, :c=>40}]
1116
- end
1117
-
1118
- cspecify "#having should work without a previous group", :sqlite do
1119
- @ds.unordered!
1120
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
1121
- @ds.insert(20, 30)
1122
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
1123
- @ds.insert(40, 20)
1124
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.must_equal [{:c=>40}]
1125
- end
1126
- end
1127
-
1128
- describe "Sequel::Dataset convenience methods" do
1129
- before(:all) do
1130
- @db = DB
1131
- @db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
1132
- @ds = @db[:a].order(:a)
1133
- end
1134
- before do
1135
- @ds.delete
1136
- @ds.insert(1, 2, 3, 4)
1137
- @ds.insert(5, 6, 7, 8)
1138
- end
1139
- after(:all) do
1140
- @db.drop_table?(:a)
1141
- end
1142
-
1143
- it "should have working #map" do
1144
- @ds.map(:a).must_equal [1, 5]
1145
- @ds.map(:b).must_equal [2, 6]
1146
- @ds.map([:a, :b]).must_equal [[1, 2], [5, 6]]
1147
- end
1148
-
1149
- it "should have working #to_hash" do
1150
- @ds.to_hash(:a).must_equal(1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8})
1151
- @ds.to_hash(:b).must_equal(2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8})
1152
- @ds.to_hash([:a, :b]).must_equal([1, 2]=>{:a=>1, :b=>2, :c=>3, :d=>4}, [5, 6]=>{:a=>5, :b=>6, :c=>7, :d=>8})
1153
-
1154
- @ds.to_hash(:a, :b).must_equal(1=>2, 5=>6)
1155
- @ds.to_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
1156
- @ds.to_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
1157
- @ds.to_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
1158
- end
1159
-
1160
- it "should have working #to_hash_groups" do
1161
- ds = @ds.order(*@ds.columns)
1162
- ds.insert(1, 2, 3, 9)
1163
- ds.to_hash_groups(:a).must_equal(1=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 5=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
1164
- ds.to_hash_groups(:b).must_equal(2=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 6=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
1165
- ds.to_hash_groups([:a, :b]).must_equal([1, 2]=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], [5, 6]=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
1166
-
1167
- ds.to_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
1168
- ds.to_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
1169
- ds.to_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
1170
- ds.to_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
1171
- end
1172
-
1173
- it "should have working #select_map" do
1174
- @ds.select_map(:a).must_equal [1, 5]
1175
- @ds.select_map(:b).must_equal [2, 6]
1176
- @ds.select_map([:a]).must_equal [[1], [5]]
1177
- @ds.select_map([:a, :b]).must_equal [[1, 2], [5, 6]]
1178
-
1179
- @ds.select_map(:a___e).must_equal [1, 5]
1180
- @ds.select_map(:b___e).must_equal [2, 6]
1181
- @ds.select_map([:a___e, :b___f]).must_equal [[1, 2], [5, 6]]
1182
- @ds.select_map([:a__a___e, :a__b___f]).must_equal [[1, 2], [5, 6]]
1183
- @ds.select_map([Sequel.expr(:a__a).as(:e), Sequel.expr(:a__b).as(:f)]).must_equal [[1, 2], [5, 6]]
1184
- @ds.select_map([Sequel.qualify(:a, :a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
1185
- @ds.select_map([Sequel.identifier(:a).qualify(:a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
1186
- end
1187
-
1188
- it "should have working #select_order_map" do
1189
- @ds.select_order_map(:a).must_equal [1, 5]
1190
- @ds.select_order_map(Sequel.desc(:a__b)).must_equal [6, 2]
1191
- @ds.select_order_map(Sequel.desc(:a__b___e)).must_equal [6, 2]
1192
- @ds.select_order_map(Sequel.qualify(:a, :b).as(:e)).must_equal [2, 6]
1193
- @ds.select_order_map([:a]).must_equal [[1], [5]]
1194
- @ds.select_order_map([Sequel.desc(:a), :b]).must_equal [[5, 6], [1, 2]]
1195
-
1196
- @ds.select_order_map(:a___e).must_equal [1, 5]
1197
- @ds.select_order_map(:b___e).must_equal [2, 6]
1198
- @ds.select_order_map([Sequel.desc(:a___e), :b___f]).must_equal [[5, 6], [1, 2]]
1199
- @ds.select_order_map([Sequel.desc(:a__a___e), :a__b___f]).must_equal [[5, 6], [1, 2]]
1200
- @ds.select_order_map([Sequel.desc(:a__a), Sequel.expr(:a__b).as(:f)]).must_equal [[5, 6], [1, 2]]
1201
- @ds.select_order_map([Sequel.qualify(:a, :a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
1202
- @ds.select_order_map([Sequel.identifier(:a).qualify(:a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
1203
- end
1204
-
1205
- it "should have working #select_hash" do
1206
- @ds.select_hash(:a, :b).must_equal(1=>2, 5=>6)
1207
- @ds.select_hash(:a__a___e, :b).must_equal(1=>2, 5=>6)
1208
- @ds.select_hash(Sequel.expr(:a__a).as(:e), :b).must_equal(1=>2, 5=>6)
1209
- @ds.select_hash(Sequel.qualify(:a, :a).as(:e), :b).must_equal(1=>2, 5=>6)
1210
- @ds.select_hash(Sequel.identifier(:a).qualify(:a).as(:e), :b).must_equal(1=>2, 5=>6)
1211
- @ds.select_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
1212
- @ds.select_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
1213
- @ds.select_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
1214
- end
1215
-
1216
- it "should have working #select_hash_groups" do
1217
- ds = @ds.order(*@ds.columns)
1218
- ds.insert(1, 2, 3, 9)
1219
- ds.select_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
1220
- ds.select_hash_groups(:a__a___e, :d).must_equal(1=>[4, 9], 5=>[8])
1221
- ds.select_hash_groups(Sequel.expr(:a__a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1222
- ds.select_hash_groups(Sequel.qualify(:a, :a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1223
- ds.select_hash_groups(Sequel.identifier(:a).qualify(:a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1224
- ds.select_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
1225
- ds.select_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
1226
- ds.select_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
1227
- end
1228
- end
1229
-
1230
- describe "Sequel::Dataset DSL support" do
1231
- before(:all) do
1232
- @db = DB
1233
- @db.create_table!(:a){Integer :a; Integer :b}
1234
- @ds = @db[:a].order(:a)
1235
- end
1236
- before do
1237
- @ds.delete
1238
- end
1239
- after(:all) do
1240
- @db.drop_table?(:a)
1241
- end
1242
-
1243
- it "should work with standard mathematical operators" do
1244
- @ds.insert(20, 10)
1245
- @ds.get{a + b}.to_i.must_equal 30
1246
- @ds.get{a - b}.to_i.must_equal 10
1247
- @ds.get{a * b}.to_i.must_equal 200
1248
- @ds.get{a / b}.to_i.must_equal 2
1249
- end
1250
-
1251
- cspecify "should work with bitwise shift operators", :derby do
1252
- @ds.insert(3, 2)
1253
- @ds.get{a.sql_number << b}.to_i.must_equal 12
1254
- @ds.get{a.sql_number >> b}.to_i.must_equal 0
1255
- @ds.get{a.sql_number << b << 1}.to_i.must_equal 24
1256
- @ds.delete
1257
- @ds.insert(3, 1)
1258
- @ds.get{a.sql_number << b}.to_i.must_equal 6
1259
- @ds.get{a.sql_number >> b}.to_i.must_equal 1
1260
- @ds.get{a.sql_number >> b >> 1}.to_i.must_equal 0
1261
- end
1262
-
1263
- cspecify "should work with bitwise AND and OR operators", :derby do
1264
- @ds.insert(3, 5)
1265
- @ds.get{a.sql_number | b}.to_i.must_equal 7
1266
- @ds.get{a.sql_number & b}.to_i.must_equal 1
1267
- @ds.get{a.sql_number | b | 8}.to_i.must_equal 15
1268
- @ds.get{a.sql_number & b & 8}.to_i.must_equal 0
1269
- end
1270
-
1271
- it "should work with the bitwise compliment operator" do
1272
- @ds.insert(-3, 3)
1273
- @ds.get{~a.sql_number}.to_i.must_equal 2
1274
- @ds.get{~b.sql_number}.to_i.must_equal(-4)
1275
- end
1276
-
1277
- cspecify "should work with the bitwise xor operator", :derby do
1278
- @ds.insert(3, 5)
1279
- @ds.get{a.sql_number ^ b}.to_i.must_equal 6
1280
- @ds.get{a.sql_number ^ b ^ 1}.to_i.must_equal 7
1281
- end
1282
-
1283
- it "should work with the modulus operator" do
1284
- @ds.insert(3, 5)
1285
- @ds.get{a.sql_number % 4}.to_i.must_equal 3
1286
- @ds.get{b.sql_number % 4}.to_i.must_equal 1
1287
- @ds.get{a.sql_number % 4 % 2}.to_i.must_equal 1
1288
- end
1289
-
1290
- it "should work with inequality operators" do
1291
- @ds.insert(10, 11)
1292
- @ds.insert(11, 11)
1293
- @ds.insert(20, 19)
1294
- @ds.insert(20, 20)
1295
- @ds.filter{a > b}.select_order_map(:a).must_equal [20]
1296
- @ds.filter{a >= b}.select_order_map(:a).must_equal [11, 20, 20]
1297
- @ds.filter{a < b}.select_order_map(:a).must_equal [10]
1298
- @ds.filter{a <= b}.select_order_map(:a).must_equal [10, 11, 20]
1299
- end
1300
-
1301
- it "should work with casting and string concatentation" do
1302
- @ds.insert(20, 20)
1303
- @ds.get{Sequel.cast(a, String).sql_string + Sequel.cast(b, String)}.must_equal '2020'
1304
- end
1305
-
1306
- it "should work with ordering" do
1307
- @ds.insert(10, 20)
1308
- @ds.insert(20, 10)
1309
- @ds.order(:a, :b).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
1310
- @ds.order(Sequel.asc(:a), Sequel.asc(:b)).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
1311
- @ds.order(Sequel.desc(:a), Sequel.desc(:b)).all.must_equal [{:a=>20, :b=>10}, {:a=>10, :b=>20}]
1312
- end
1313
-
1314
- it "should work with qualifying" do
1315
- @ds.insert(10, 20)
1316
- @ds.get(:a__b).must_equal 20
1317
- @ds.get{a__b}.must_equal 20
1318
- @ds.get(Sequel.qualify(:a, :b)).must_equal 20
1319
- end
1320
-
1321
- it "should work with aliasing" do
1322
- @ds.insert(10, 20)
1323
- @ds.get(:a__b___c).must_equal 20
1324
- @ds.get{a__b.as(c)}.must_equal 20
1325
- @ds.get(Sequel.qualify(:a, :b).as(:c)).must_equal 20
1326
- @ds.get(Sequel.as(:b, :c)).must_equal 20
1327
- end
1328
-
1329
- it "should work with selecting all columns of a table" do
1330
- @ds.insert(20, 10)
1331
- @ds.select_all(:a).all.must_equal [{:a=>20, :b=>10}]
1332
- end
1333
-
1334
- it "should work with ranges as hash values" do
1335
- @ds.insert(20, 10)
1336
- @ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
1337
- @ds.filter(:a=>(25..30)).all.must_equal []
1338
- @ds.filter(:a=>(10..15)).all.must_equal []
1339
- @ds.exclude(:a=>(10..30)).all.must_equal []
1340
- @ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
1341
- @ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
1342
- end
1343
-
1344
- it "should work with nil as hash value" do
1345
- @ds.insert(20, nil)
1346
- @ds.filter(:a=>nil).all.must_equal []
1347
- @ds.filter(:b=>nil).all.must_equal [{:a=>20, :b=>nil}]
1348
- @ds.exclude(:b=>nil).all.must_equal []
1349
- @ds.exclude(:a=>nil).all.must_equal [{:a=>20, :b=>nil}]
1350
- end
1351
-
1352
- it "should work with arrays as hash values" do
1353
- @ds.insert(20, 10)
1354
- @ds.filter(:a=>[10]).all.must_equal []
1355
- @ds.filter(:a=>[20, 10]).all.must_equal [{:a=>20, :b=>10}]
1356
- @ds.exclude(:a=>[10]).all.must_equal [{:a=>20, :b=>10}]
1357
- @ds.exclude(:a=>[20, 10]).all.must_equal []
1358
- end
1359
-
1360
- it "should work with ranges as hash values" do
1361
- @ds.insert(20, 10)
1362
- @ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
1363
- @ds.filter(:a=>(25..30)).all.must_equal []
1364
- @ds.filter(:a=>(10..15)).all.must_equal []
1365
- @ds.exclude(:a=>(10..30)).all.must_equal []
1366
- @ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
1367
- @ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
1368
- end
1369
-
1370
- it "should work with CASE statements" do
1371
- @ds.insert(20, 10)
1372
- @ds.filter(Sequel.case({{:a=>20}=>20}, 0) > 0).all.must_equal [{:a=>20, :b=>10}]
1373
- @ds.filter(Sequel.case({{:a=>15}=>20}, 0) > 0).all.must_equal []
1374
- @ds.filter(Sequel.case({20=>20}, 0, :a) > 0).all.must_equal [{:a=>20, :b=>10}]
1375
- @ds.filter(Sequel.case({15=>20}, 0, :a) > 0).all.must_equal []
1376
- end
1377
-
1378
- it "should work with multiple value arrays" do
1379
- @ds.insert(20, 10)
1380
- @ds.quote_identifiers = false
1381
- @ds.filter([:a, :b]=>[[20, 10]]).all.must_equal [{:a=>20, :b=>10}]
1382
- @ds.filter([:a, :b]=>[[10, 20]]).all.must_equal []
1383
- @ds.filter([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal [{:a=>20, :b=>10}]
1384
- @ds.filter([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal []
1385
-
1386
- @ds.exclude([:a, :b]=>[[20, 10]]).all.must_equal []
1387
- @ds.exclude([:a, :b]=>[[10, 20]]).all.must_equal [{:a=>20, :b=>10}]
1388
- @ds.exclude([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal []
1389
- @ds.exclude([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal [{:a=>20, :b=>10}]
1390
- end
1391
-
1392
- it "should work with IN/NOT in with datasets" do
1393
- @ds.insert(20, 10)
1394
- ds = @ds.unordered
1395
- @ds.quote_identifiers = false
1396
-
1397
- @ds.filter(:a=>ds.select(:a)).all.must_equal [{:a=>20, :b=>10}]
1398
- @ds.filter(:a=>ds.select(:a).where(:a=>15)).all.must_equal []
1399
- @ds.exclude(:a=>ds.select(:a)).all.must_equal []
1400
- @ds.exclude(:a=>ds.select(:a).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
1401
-
1402
- @ds.filter([:a, :b]=>ds.select(:a, :b)).all.must_equal [{:a=>20, :b=>10}]
1403
- @ds.filter([:a, :b]=>ds.select(:b, :a)).all.must_equal []
1404
- @ds.exclude([:a, :b]=>ds.select(:a, :b)).all.must_equal []
1405
- @ds.exclude([:a, :b]=>ds.select(:b, :a)).all.must_equal [{:a=>20, :b=>10}]
1406
-
1407
- @ds.filter([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal []
1408
- @ds.exclude([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
1409
- end
1410
-
1411
- it "should work empty arrays" do
1412
- @ds.insert(20, 10)
1413
- @ds.filter(:a=>[]).all.must_equal []
1414
- @ds.exclude(:a=>[]).all.must_equal [{:a=>20, :b=>10}]
1415
- @ds.filter([:a, :b]=>[]).all.must_equal []
1416
- @ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>20, :b=>10}]
1417
- end
1418
-
1419
- it "should work empty arrays with nulls" do
1420
- @ds = @ds.extension(:empty_array_consider_nulls)
1421
- @ds.insert(nil, nil)
1422
- @ds.filter(:a=>[]).all.must_equal []
1423
- @ds.exclude(:a=>[]).all.must_equal []
1424
- @ds.filter([:a, :b]=>[]).all.must_equal []
1425
- @ds.exclude([:a, :b]=>[]).all.must_equal []
1426
-
1427
- unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1428
- # Some databases don't like boolean results in the select list
1429
- pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1430
- pr[@ds.get(Sequel.expr(:a=>[]))].must_equal nil
1431
- pr[@ds.get(~Sequel.expr(:a=>[]))].must_equal nil
1432
- pr[@ds.get(Sequel.expr([:a, :b]=>[]))].must_equal nil
1433
- pr[@ds.get(~Sequel.expr([:a, :b]=>[]))].must_equal nil
1434
- end
1435
- end
1436
-
1437
- it "should work empty arrays with nulls and the empty_array_ignore_nulls extension" do
1438
- ds = @ds
1439
- ds.insert(nil, nil)
1440
- ds.filter(:a=>[]).all.must_equal []
1441
- ds.exclude(:a=>[]).all.must_equal [{:a=>nil, :b=>nil}]
1442
- ds.filter([:a, :b]=>[]).all.must_equal []
1443
- ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>nil, :b=>nil}]
1444
-
1445
- unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1446
- # Some databases don't like boolean results in the select list
1447
- pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1448
- pr[ds.get(Sequel.expr(:a=>[]))].must_equal false
1449
- pr[ds.get(~Sequel.expr(:a=>[]))].must_equal true
1450
- pr[ds.get(Sequel.expr([:a, :b]=>[]))].must_equal false
1451
- pr[ds.get(~Sequel.expr([:a, :b]=>[]))].must_equal true
1452
- end
1453
- end
1454
-
1455
- it "should work multiple conditions" do
1456
- @ds.insert(20, 10)
1457
- @ds.filter(:a=>20, :b=>10).all.must_equal [{:a=>20, :b=>10}]
1458
- @ds.filter([[:a, 20], [:b, 10]]).all.must_equal [{:a=>20, :b=>10}]
1459
- @ds.filter({:a=>20}, {:b=>10}).all.must_equal [{:a=>20, :b=>10}]
1460
- @ds.filter(Sequel.|({:a=>20}, {:b=>5})).all.must_equal [{:a=>20, :b=>10}]
1461
- @ds.filter(Sequel.~(:a=>10)).all.must_equal [{:a=>20, :b=>10}]
1462
- end
1463
- end
1464
-
1465
- describe "SQL Extract Function" do
1466
- before do
1467
- @db = DB
1468
- @db.create_table!(:a){DateTime :a}
1469
- @ds = @db[:a].order(:a)
1470
- end
1471
- after do
1472
- @db.drop_table?(:a)
1473
- end
1474
-
1475
- it "should return the part of the datetime asked for" do
1476
- t = Time.now
1477
- def @ds.supports_timestamp_timezones?() false end
1478
- @ds.insert(t)
1479
- @ds.get{a.extract(:year)}.must_equal t.year
1480
- @ds.get{a.extract(:month)}.must_equal t.month
1481
- @ds.get{a.extract(:day)}.must_equal t.day
1482
- @ds.get{a.extract(:hour)}.must_equal t.hour
1483
- @ds.get{a.extract(:minute)}.must_equal t.min
1484
- @ds.get{a.extract(:second)}.to_i.must_equal t.sec
1485
- end
1486
- end
1487
-
1488
- describe "Dataset string methods" do
1489
- before(:all) do
1490
- @db = DB
1491
- csc = {}
1492
- cic = {}
1493
- csc[:collate] = @db.dataset_class::CASE_SENSITIVE_COLLATION if defined? @db.dataset_class::CASE_SENSITIVE_COLLATION
1494
- cic[:collate] = @db.dataset_class::CASE_INSENSITIVE_COLLATION if defined? @db.dataset_class::CASE_INSENSITIVE_COLLATION
1495
- @db.create_table!(:a) do
1496
- String :a, csc
1497
- String :b, cic
1498
- end
1499
- @ds = @db[:a].order(:a)
1500
- end
1501
- before do
1502
- @ds.delete
1503
- end
1504
- after(:all) do
1505
- @db.drop_table?(:a)
1506
- end
1507
-
1508
- it "#grep should return matching rows" do
1509
- @ds.insert('foo', 'bar')
1510
- @ds.grep(:a, 'foo').all.must_equal [{:a=>'foo', :b=>'bar'}]
1511
- @ds.grep(:b, 'foo').all.must_equal []
1512
- @ds.grep(:b, 'bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
1513
- @ds.grep(:a, 'bar').all.must_equal []
1514
- @ds.grep([:a, :b], %w'foo bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
1515
- @ds.grep([:a, :b], %w'boo far').all.must_equal []
1516
- end
1517
-
1518
- it "#grep should work with :all_patterns and :all_columns options" do
1519
- @ds.insert('foo bar', ' ')
1520
- @ds.insert('foo d', 'bar')
1521
- @ds.insert('foo e', ' ')
1522
- @ds.insert(' ', 'bar')
1523
- @ds.insert('foo f', 'baz')
1524
- @ds.insert('foo baz', 'bar baz')
1525
- @ds.insert('foo boo', 'boo foo')
1526
-
1527
- @ds.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true).all.must_equal [{:a=>'foo bar', :b=>' '}, {:a=>'foo baz', :b=>'bar baz'}, {:a=>'foo d', :b=>'bar'}]
1528
- @ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.must_equal []
1529
-
1530
- @ds.grep([:a, :b], %w'%bar% %foo%', :all_columns=>true).all.must_equal [{:a=>"foo baz", :b=>"bar baz"}, {:a=>"foo boo", :b=>"boo foo"}, {:a=>"foo d", :b=>"bar"}]
1531
- @ds.grep([:a, :b], %w'%baz%', :all_columns=>true).all.must_equal [{:a=>'foo baz', :b=>'bar baz'}]
1532
-
1533
- @ds.grep([:a, :b], %w'%baz% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal []
1534
- @ds.grep([:a, :b], %w'%boo% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal [{:a=>'foo boo', :b=>'boo foo'}]
1535
- end
1536
-
1537
- it "#like should return matching rows" do
1538
- @ds.insert('foo', 'bar')
1539
- @ds.filter(Sequel.expr(:a).like('foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1540
- @ds.filter(Sequel.expr(:a).like('bar')).all.must_equal []
1541
- @ds.filter(Sequel.expr(:a).like('foo', 'bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1542
- @ds.exclude(Sequel.expr(:a).like('foo')).all.must_equal []
1543
- @ds.exclude(Sequel.expr(:a).like('bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1544
- @ds.exclude(Sequel.expr(:a).like('foo', 'bar')).all.must_equal []
1545
- end
1546
-
1547
- it "#like should be case sensitive" do
1548
- @ds.insert('foo', 'bar')
1549
- @ds.filter(Sequel.expr(:a).like('Foo')).all.must_equal []
1550
- @ds.filter(Sequel.expr(:b).like('baR')).all.must_equal []
1551
- @ds.filter(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal []
1552
- @ds.exclude(Sequel.expr(:a).like('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1553
- @ds.exclude(Sequel.expr(:b).like('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1554
- @ds.exclude(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1555
- end
1556
-
1557
- it "#ilike should return matching rows, in a case insensitive manner" do
1558
- @ds.insert('foo', 'bar')
1559
- @ds.filter(Sequel.expr(:a).ilike('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1560
- @ds.filter(Sequel.expr(:a).ilike('baR')).all.must_equal []
1561
- @ds.filter(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1562
- @ds.exclude(Sequel.expr(:a).ilike('Foo')).all.must_equal []
1563
- @ds.exclude(Sequel.expr(:a).ilike('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1564
- @ds.exclude(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal []
1565
- end
1566
-
1567
- it "#escape_like should escape any metacharacters" do
1568
- @ds.insert('foo', 'bar')
1569
- @ds.insert('foo.', 'bar..')
1570
- @ds.insert('foo\\..', 'bar\\..')
1571
- @ds.insert('foo\\_', 'bar\\%')
1572
- @ds.insert('foo_', 'bar%')
1573
- @ds.insert('foo_.', 'bar%.')
1574
- @ds.insert('foo_..', 'bar%..')
1575
- @ds.insert('[f#*?oo_]', '[bar%]')
1576
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('foo_'))).select_order_map(:a).must_equal ['foo_']
1577
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('bar%'))).select_order_map(:b).must_equal ['bar%']
1578
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('foo\\_'))).select_order_map(:a).must_equal ['foo\\_']
1579
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('bar\\%'))).select_order_map(:b).must_equal ['bar\\%']
1580
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('[f#*?oo_]'))).select_order_map(:a).must_equal ['[f#*?oo_]']
1581
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('[bar%]'))).select_order_map(:b).must_equal ['[bar%]']
1582
- @ds.filter(Sequel.expr(:b).like("#{@ds.escape_like('bar%')}_")).select_order_map(:b).must_equal ['bar%.']
1583
- @ds.filter(Sequel.expr(:b).like("#{@ds.escape_like('bar%')}%")).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1584
-
1585
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('Foo_'))).select_order_map(:a).must_equal ['foo_']
1586
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('Bar%'))).select_order_map(:b).must_equal ['bar%']
1587
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('Foo\\_'))).select_order_map(:a).must_equal ['foo\\_']
1588
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('Bar\\%'))).select_order_map(:b).must_equal ['bar\\%']
1589
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('[F#*?oo_]'))).select_order_map(:a).must_equal ['[f#*?oo_]']
1590
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('[Bar%]'))).select_order_map(:b).must_equal ['[bar%]']
1591
- @ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}_")).select_order_map(:b).must_equal ['bar%.']
1592
- @ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}%")).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1593
- end
1594
-
1595
- if DB.dataset.supports_regexp?
1596
- it "#like with regexp return matching rows" do
1597
- @ds.insert('foo', 'bar')
1598
- @ds.filter(Sequel.expr(:a).like(/fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1599
- @ds.filter(Sequel.expr(:a).like(/fo$/)).all.must_equal []
1600
- @ds.filter(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1601
- @ds.exclude(Sequel.expr(:a).like(/fo/)).all.must_equal []
1602
- @ds.exclude(Sequel.expr(:a).like(/fo$/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1603
- @ds.exclude(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal []
1604
- end
1605
-
1606
- it "#like with regexp should be case sensitive if regexp is case sensitive" do
1607
- @ds.insert('foo', 'bar')
1608
- @ds.filter(Sequel.expr(:a).like(/Fo/)).all.must_equal []
1609
- @ds.filter(Sequel.expr(:b).like(/baR/)).all.must_equal []
1610
- @ds.filter(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal []
1611
- @ds.exclude(Sequel.expr(:a).like(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1612
- @ds.exclude(Sequel.expr(:b).like(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1613
- @ds.exclude(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1614
-
1615
- @ds.filter(Sequel.expr(:a).like(/Fo/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1616
- @ds.filter(Sequel.expr(:b).like(/baR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1617
- @ds.filter(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1618
- @ds.exclude(Sequel.expr(:a).like(/Fo/i)).all.must_equal []
1619
- @ds.exclude(Sequel.expr(:b).like(/baR/i)).all.must_equal []
1620
- @ds.exclude(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal []
1621
- end
1622
-
1623
- it "#ilike with regexp should return matching rows, in a case insensitive manner" do
1624
- @ds.insert('foo', 'bar')
1625
- @ds.filter(Sequel.expr(:a).ilike(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1626
- @ds.filter(Sequel.expr(:b).ilike(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1627
- @ds.filter(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1628
- @ds.exclude(Sequel.expr(:a).ilike(/Fo/)).all.must_equal []
1629
- @ds.exclude(Sequel.expr(:b).ilike(/baR/)).all.must_equal []
1630
- @ds.exclude(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal []
1631
- end
1632
- end
1633
-
1634
- it "should work with strings created with Sequel.join" do
1635
- @ds.insert('foo', 'bar')
1636
- @ds.get(Sequel.join([:a, "bar"])).must_equal 'foobar'
1637
- @ds.get(Sequel.join(["foo", :b], ' ')).must_equal 'foo bar'
1638
- end
1639
- end
1640
-
1641
- describe "Dataset identifier methods" do
1642
- before(:all) do
1643
- class ::String
1644
- def uprev
1645
- upcase.reverse
1646
- end
1647
- end
1648
- @db = DB
1649
- @db.create_table!(:a){Integer :ab}
1650
- @db[:a].insert(1)
1651
- end
1652
- before do
1653
- @ds = @db[:a].order(:ab)
1654
- end
1655
- after(:all) do
1656
- @db.drop_table?(:a)
1657
- end
1658
-
1659
- it "#identifier_output_method should change how identifiers are output" do
1660
- @ds.identifier_output_method = :upcase
1661
- @ds.first.must_equal(:AB=>1)
1662
- @ds.identifier_output_method = :uprev
1663
- @ds.first.must_equal(:BA=>1)
1664
- end
1665
-
1666
- it "should work with a nil identifier_output_method" do
1667
- @ds.identifier_output_method = nil
1668
- [{:ab=>1}, {:AB=>1}].must_include(@ds.first)
1669
- end
1670
-
1671
- it "should work when not quoting identifiers" do
1672
- @ds.quote_identifiers = false
1673
- @ds.first.must_equal(:ab=>1)
1674
- end
1675
- end
1676
-
1677
- describe "Dataset defaults and overrides" do
1678
- before(:all) do
1679
- @db = DB
1680
- @db.create_table!(:a){Integer :a}
1681
- @ds = @db[:a].order(:a).extension(:set_overrides)
1682
- end
1683
- before do
1684
- @ds.delete
1685
- end
1686
- after(:all) do
1687
- @db.drop_table?(:a)
1688
- end
1689
-
1690
- it "#set_defaults should set defaults that can be overridden" do
1691
- @ds = @ds.set_defaults(:a=>10)
1692
- @ds.insert
1693
- @ds.insert(:a=>20)
1694
- @ds.all.must_equal [{:a=>10}, {:a=>20}]
1695
- end
1696
-
1697
- it "#set_overrides should set defaults that cannot be overridden" do
1698
- @ds = @ds.set_overrides(:a=>10)
1699
- @ds.insert
1700
- @ds.insert(:a=>20)
1701
- @ds.all.must_equal [{:a=>10}, {:a=>10}]
1702
- end
1703
- end
1704
-
1705
- if DB.dataset.supports_modifying_joins?
1706
- describe "Modifying joined datasets" do
1707
- before do
1708
- @db = DB
1709
- @db.create_table!(:a){Integer :a; Integer :d}
1710
- @db.create_table!(:b){Integer :b; Integer :e}
1711
- @db.create_table!(:c){Integer :c; Integer :f}
1712
- @ds = @db.from(:a, :b).join(:c, {:c=>Sequel.identifier(:e)}, :qualify=>:symbol).where(:d=>:b, :f=>6)
1713
- @db[:a].insert(1, 2)
1714
- @db[:a].insert(3, 4)
1715
- @db[:b].insert(2, 5)
1716
- @db[:c].insert(5, 6)
1717
- @db[:b].insert(4, 7)
1718
- @db[:c].insert(7, 8)
1719
- end
1720
- after do
1721
- @db.drop_table?(:a, :b, :c)
1722
- end
1723
-
1724
- it "#update should allow updating joined datasets" do
1725
- @ds.update(:a=>10)
1726
- @ds.all.must_equal [{:c=>5, :b=>2, :a=>10, :d=>2, :e=>5, :f=>6}]
1727
- @db[:a].order(:a).all.must_equal [{:a=>3, :d=>4}, {:a=>10, :d=>2}]
1728
- @db[:b].order(:b).all.must_equal [{:b=>2, :e=>5}, {:b=>4, :e=>7}]
1729
- @db[:c].order(:c).all.must_equal [{:c=>5, :f=>6}, {:c=>7, :f=>8}]
1730
- end
1731
-
1732
- it "#delete should allow deleting from joined datasets" do
1733
- @ds.delete
1734
- @ds.all.must_equal []
1735
- @db[:a].order(:a).all.must_equal [{:a=>3, :d=>4}]
1736
- @db[:b].order(:b).all.must_equal [{:b=>2, :e=>5}, {:b=>4, :e=>7}]
1737
- @db[:c].order(:c).all.must_equal [{:c=>5, :f=>6}, {:c=>7, :f=>8}]
1738
- end
1739
- end
1740
- end
1741
-
1742
- describe "Emulated functions" do
1743
- before(:all) do
1744
- @db = DB
1745
- @db.create_table!(:a){String :a}
1746
- @ds = @db[:a]
1747
- end
1748
- after(:all) do
1749
- @db.drop_table?(:a)
1750
- end
1751
- after do
1752
- @ds.delete
1753
- end
1754
-
1755
- it "Sequel.char_length should return the length of characters in the string" do
1756
- @ds.get(Sequel.char_length(:a)).must_equal nil
1757
- @ds.insert(:a=>'foo')
1758
- @ds.get(Sequel.char_length(:a)).must_equal 3
1759
- # Check behavior with leading/trailing blanks
1760
- @ds.update(:a=>' foo22 ')
1761
- @ds.get(Sequel.char_length(:a)).must_equal 7
1762
- end
1763
-
1764
- it "Sequel.trim should return the string with spaces trimmed from both sides" do
1765
- @ds.get(Sequel.trim(:a)).must_equal nil
1766
- @ds.insert(:a=>'foo')
1767
- @ds.get(Sequel.trim(:a)).must_equal 'foo'
1768
- # Check behavior with leading/trailing blanks
1769
- @ds.update(:a=>' foo22 ')
1770
- @ds.get(Sequel.trim(:a)).must_equal 'foo22'
1771
- end
1772
- end
1773
-
1774
- describe "Dataset replace" do
1775
- before do
1776
- DB.create_table!(:items){Integer :id, :unique=>true; Integer :value}
1777
- sqls = []
1778
- DB.loggers << Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new
1779
-
1780
- @d = DB[:items]
1781
- sqls.clear
1782
- end
1783
-
1784
- after do
1785
- DB.drop_table?(:items)
1786
- end
1787
-
1788
- it "should use support arrays, datasets, and multiple values" do
1789
- @d.replace([1, 2])
1790
- @d.all.must_equal [{:id=>1, :value=>2}]
1791
- @d.replace(1, 2)
1792
- @d.all.must_equal [{:id=>1, :value=>2}]
1793
- @d.replace(@d)
1794
- @d.all.must_equal [{:id=>1, :value=>2}]
1795
- end
1796
-
1797
- it "should create a record if the condition is not met" do
1798
- @d.replace(:id => 111, :value => 333)
1799
- @d.all.must_equal [{:id => 111, :value => 333}]
1800
- end
1801
-
1802
- it "should update a record if the condition is met" do
1803
- @d << {:id => 111}
1804
- @d.all.must_equal [{:id => 111, :value => nil}]
1805
- @d.replace(:id => 111, :value => 333)
1806
- @d.all.must_equal [{:id => 111, :value => 333}]
1807
- end
1808
- end if DB.dataset.supports_replace?