sequel 5.20.0 → 5.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (511) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +398 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +80 -16
  7. data/doc/cheat_sheet.rdoc +6 -5
  8. data/doc/code_order.rdoc +10 -12
  9. data/doc/dataset_filtering.rdoc +17 -2
  10. data/doc/fork_safety.rdoc +84 -0
  11. data/doc/migration.rdoc +11 -5
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +10 -2
  15. data/doc/postgresql.rdoc +82 -3
  16. data/doc/querying.rdoc +4 -4
  17. data/doc/release_notes/5.21.0.txt +87 -0
  18. data/doc/release_notes/5.22.0.txt +48 -0
  19. data/doc/release_notes/5.23.0.txt +56 -0
  20. data/doc/release_notes/5.24.0.txt +56 -0
  21. data/doc/release_notes/5.25.0.txt +32 -0
  22. data/doc/release_notes/5.26.0.txt +35 -0
  23. data/doc/release_notes/5.27.0.txt +21 -0
  24. data/doc/release_notes/5.28.0.txt +16 -0
  25. data/doc/release_notes/5.29.0.txt +22 -0
  26. data/doc/release_notes/5.30.0.txt +20 -0
  27. data/doc/release_notes/5.31.0.txt +148 -0
  28. data/doc/release_notes/5.32.0.txt +46 -0
  29. data/doc/release_notes/5.33.0.txt +24 -0
  30. data/doc/release_notes/5.34.0.txt +40 -0
  31. data/doc/release_notes/5.35.0.txt +56 -0
  32. data/doc/release_notes/5.36.0.txt +60 -0
  33. data/doc/release_notes/5.37.0.txt +30 -0
  34. data/doc/release_notes/5.38.0.txt +28 -0
  35. data/doc/release_notes/5.39.0.txt +19 -0
  36. data/doc/release_notes/5.40.0.txt +40 -0
  37. data/doc/release_notes/5.41.0.txt +25 -0
  38. data/doc/release_notes/5.42.0.txt +136 -0
  39. data/doc/release_notes/5.43.0.txt +98 -0
  40. data/doc/release_notes/5.44.0.txt +32 -0
  41. data/doc/release_notes/5.45.0.txt +34 -0
  42. data/doc/release_notes/5.46.0.txt +87 -0
  43. data/doc/release_notes/5.47.0.txt +59 -0
  44. data/doc/release_notes/5.48.0.txt +14 -0
  45. data/doc/release_notes/5.49.0.txt +59 -0
  46. data/doc/sharding.rdoc +2 -0
  47. data/doc/sql.rdoc +13 -1
  48. data/doc/testing.rdoc +20 -7
  49. data/doc/transactions.rdoc +0 -8
  50. data/doc/validations.rdoc +1 -1
  51. data/doc/virtual_rows.rdoc +1 -1
  52. data/lib/sequel/adapters/ado/access.rb +1 -1
  53. data/lib/sequel/adapters/ado.rb +43 -35
  54. data/lib/sequel/adapters/ibmdb.rb +2 -2
  55. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  56. data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
  57. data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
  58. data/lib/sequel/adapters/jdbc.rb +24 -6
  59. data/lib/sequel/adapters/mysql.rb +1 -1
  60. data/lib/sequel/adapters/mysql2.rb +2 -3
  61. data/lib/sequel/adapters/odbc.rb +8 -6
  62. data/lib/sequel/adapters/oracle.rb +5 -4
  63. data/lib/sequel/adapters/postgres.rb +15 -9
  64. data/lib/sequel/adapters/shared/access.rb +6 -6
  65. data/lib/sequel/adapters/shared/mssql.rb +66 -21
  66. data/lib/sequel/adapters/shared/mysql.rb +27 -10
  67. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  68. data/lib/sequel/adapters/shared/postgres.rb +271 -32
  69. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  70. data/lib/sequel/adapters/shared/sqlite.rb +161 -19
  71. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  72. data/lib/sequel/adapters/sqlite.rb +1 -1
  73. data/lib/sequel/adapters/tinytds.rb +15 -2
  74. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
  75. data/lib/sequel/ast_transformer.rb +6 -0
  76. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  77. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  78. data/lib/sequel/connection_pool/single.rb +1 -1
  79. data/lib/sequel/connection_pool/threaded.rb +2 -2
  80. data/lib/sequel/core.rb +333 -319
  81. data/lib/sequel/database/connecting.rb +3 -4
  82. data/lib/sequel/database/logging.rb +7 -1
  83. data/lib/sequel/database/misc.rb +31 -12
  84. data/lib/sequel/database/query.rb +3 -1
  85. data/lib/sequel/database/schema_generator.rb +53 -51
  86. data/lib/sequel/database/schema_methods.rb +38 -23
  87. data/lib/sequel/database/transactions.rb +17 -18
  88. data/lib/sequel/dataset/actions.rb +14 -9
  89. data/lib/sequel/dataset/features.rb +16 -0
  90. data/lib/sequel/dataset/misc.rb +2 -2
  91. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  92. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  93. data/lib/sequel/dataset/query.rb +26 -9
  94. data/lib/sequel/dataset/sql.rb +76 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/deprecated.rb +3 -1
  97. data/lib/sequel/exceptions.rb +2 -0
  98. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  99. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  100. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  101. data/lib/sequel/extensions/blank.rb +8 -0
  102. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  103. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  104. data/lib/sequel/extensions/connection_validator.rb +2 -2
  105. data/lib/sequel/extensions/core_refinements.rb +2 -0
  106. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  107. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  108. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  109. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  110. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  111. data/lib/sequel/extensions/index_caching.rb +9 -7
  112. data/lib/sequel/extensions/inflector.rb +9 -1
  113. data/lib/sequel/extensions/integer64.rb +2 -0
  114. data/lib/sequel/extensions/migration.rb +11 -3
  115. data/lib/sequel/extensions/named_timezones.rb +56 -8
  116. data/lib/sequel/extensions/pagination.rb +1 -1
  117. data/lib/sequel/extensions/pg_array.rb +5 -0
  118. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  119. data/lib/sequel/extensions/pg_enum.rb +11 -3
  120. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  121. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  122. data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
  123. data/lib/sequel/extensions/pg_inet.rb +15 -5
  124. data/lib/sequel/extensions/pg_interval.rb +36 -8
  125. data/lib/sequel/extensions/pg_json.rb +387 -123
  126. data/lib/sequel/extensions/pg_json_ops.rb +238 -0
  127. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  128. data/lib/sequel/extensions/pg_range.rb +17 -9
  129. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  130. data/lib/sequel/extensions/pg_row.rb +4 -2
  131. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  132. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  133. data/lib/sequel/extensions/query.rb +3 -0
  134. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  135. data/lib/sequel/extensions/s.rb +2 -0
  136. data/lib/sequel/extensions/schema_dumper.rb +24 -7
  137. data/lib/sequel/extensions/server_block.rb +18 -7
  138. data/lib/sequel/extensions/sql_comments.rb +2 -2
  139. data/lib/sequel/extensions/string_agg.rb +1 -1
  140. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  141. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  142. data/lib/sequel/extensions/to_dot.rb +9 -3
  143. data/lib/sequel/model/associations.rb +356 -117
  144. data/lib/sequel/model/base.rb +107 -68
  145. data/lib/sequel/model/errors.rb +10 -1
  146. data/lib/sequel/model/inflections.rb +1 -1
  147. data/lib/sequel/model/plugins.rb +9 -3
  148. data/lib/sequel/model.rb +3 -1
  149. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  150. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  151. data/lib/sequel/plugins/association_pks.rb +60 -18
  152. data/lib/sequel/plugins/association_proxies.rb +8 -2
  153. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  154. data/lib/sequel/plugins/auto_validations.rb +39 -5
  155. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  156. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  157. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  158. data/lib/sequel/plugins/caching.rb +3 -0
  159. data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
  160. data/lib/sequel/plugins/column_encryption.rb +728 -0
  161. data/lib/sequel/plugins/composition.rb +7 -2
  162. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  163. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  164. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  165. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  166. data/lib/sequel/plugins/dirty.rb +60 -22
  167. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  168. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  169. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  170. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  171. data/lib/sequel/plugins/json_serializer.rb +57 -35
  172. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  173. data/lib/sequel/plugins/many_through_many.rb +108 -9
  174. data/lib/sequel/plugins/nested_attributes.rb +15 -3
  175. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  176. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
  177. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  178. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  179. data/lib/sequel/plugins/rcte_tree.rb +43 -35
  180. data/lib/sequel/plugins/serialization.rb +8 -3
  181. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  182. data/lib/sequel/plugins/sharding.rb +11 -5
  183. data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
  184. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  185. data/lib/sequel/plugins/static_cache.rb +9 -4
  186. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  187. data/lib/sequel/plugins/string_stripper.rb +1 -1
  188. data/lib/sequel/plugins/subclasses.rb +2 -0
  189. data/lib/sequel/plugins/throw_failures.rb +1 -1
  190. data/lib/sequel/plugins/timestamps.rb +1 -1
  191. data/lib/sequel/plugins/tree.rb +9 -4
  192. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  193. data/lib/sequel/plugins/unused_associations.rb +521 -0
  194. data/lib/sequel/plugins/update_or_create.rb +1 -1
  195. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  196. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  197. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  198. data/lib/sequel/sql.rb +20 -5
  199. data/lib/sequel/timezones.rb +63 -17
  200. data/lib/sequel/version.rb +1 -1
  201. metadata +113 -381
  202. data/Rakefile +0 -151
  203. data/doc/release_notes/4.0.0.txt +0 -262
  204. data/doc/release_notes/4.1.0.txt +0 -85
  205. data/doc/release_notes/4.10.0.txt +0 -226
  206. data/doc/release_notes/4.11.0.txt +0 -147
  207. data/doc/release_notes/4.12.0.txt +0 -105
  208. data/doc/release_notes/4.13.0.txt +0 -169
  209. data/doc/release_notes/4.14.0.txt +0 -68
  210. data/doc/release_notes/4.15.0.txt +0 -56
  211. data/doc/release_notes/4.16.0.txt +0 -36
  212. data/doc/release_notes/4.17.0.txt +0 -38
  213. data/doc/release_notes/4.18.0.txt +0 -36
  214. data/doc/release_notes/4.19.0.txt +0 -45
  215. data/doc/release_notes/4.2.0.txt +0 -129
  216. data/doc/release_notes/4.20.0.txt +0 -79
  217. data/doc/release_notes/4.21.0.txt +0 -94
  218. data/doc/release_notes/4.22.0.txt +0 -72
  219. data/doc/release_notes/4.23.0.txt +0 -65
  220. data/doc/release_notes/4.24.0.txt +0 -99
  221. data/doc/release_notes/4.25.0.txt +0 -181
  222. data/doc/release_notes/4.26.0.txt +0 -44
  223. data/doc/release_notes/4.27.0.txt +0 -78
  224. data/doc/release_notes/4.28.0.txt +0 -57
  225. data/doc/release_notes/4.29.0.txt +0 -41
  226. data/doc/release_notes/4.3.0.txt +0 -40
  227. data/doc/release_notes/4.30.0.txt +0 -37
  228. data/doc/release_notes/4.31.0.txt +0 -57
  229. data/doc/release_notes/4.32.0.txt +0 -132
  230. data/doc/release_notes/4.33.0.txt +0 -88
  231. data/doc/release_notes/4.34.0.txt +0 -86
  232. data/doc/release_notes/4.35.0.txt +0 -130
  233. data/doc/release_notes/4.36.0.txt +0 -116
  234. data/doc/release_notes/4.37.0.txt +0 -50
  235. data/doc/release_notes/4.38.0.txt +0 -67
  236. data/doc/release_notes/4.39.0.txt +0 -127
  237. data/doc/release_notes/4.4.0.txt +0 -92
  238. data/doc/release_notes/4.40.0.txt +0 -179
  239. data/doc/release_notes/4.41.0.txt +0 -77
  240. data/doc/release_notes/4.42.0.txt +0 -221
  241. data/doc/release_notes/4.43.0.txt +0 -87
  242. data/doc/release_notes/4.44.0.txt +0 -125
  243. data/doc/release_notes/4.45.0.txt +0 -370
  244. data/doc/release_notes/4.46.0.txt +0 -404
  245. data/doc/release_notes/4.47.0.txt +0 -56
  246. data/doc/release_notes/4.48.0.txt +0 -293
  247. data/doc/release_notes/4.49.0.txt +0 -222
  248. data/doc/release_notes/4.5.0.txt +0 -34
  249. data/doc/release_notes/4.6.0.txt +0 -30
  250. data/doc/release_notes/4.7.0.txt +0 -103
  251. data/doc/release_notes/4.8.0.txt +0 -175
  252. data/doc/release_notes/4.9.0.txt +0 -190
  253. data/spec/adapter_spec.rb +0 -4
  254. data/spec/adapters/db2_spec.rb +0 -170
  255. data/spec/adapters/mssql_spec.rb +0 -804
  256. data/spec/adapters/mysql_spec.rb +0 -1065
  257. data/spec/adapters/oracle_spec.rb +0 -371
  258. data/spec/adapters/postgres_spec.rb +0 -4125
  259. data/spec/adapters/spec_helper.rb +0 -44
  260. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  261. data/spec/adapters/sqlite_spec.rb +0 -652
  262. data/spec/bin_spec.rb +0 -278
  263. data/spec/core/connection_pool_spec.rb +0 -1250
  264. data/spec/core/database_spec.rb +0 -2865
  265. data/spec/core/dataset_spec.rb +0 -5515
  266. data/spec/core/deprecated_spec.rb +0 -70
  267. data/spec/core/expression_filters_spec.rb +0 -1455
  268. data/spec/core/mock_adapter_spec.rb +0 -722
  269. data/spec/core/object_graph_spec.rb +0 -336
  270. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  271. data/spec/core/schema_generator_spec.rb +0 -214
  272. data/spec/core/schema_spec.rb +0 -1826
  273. data/spec/core/spec_helper.rb +0 -24
  274. data/spec/core/version_spec.rb +0 -14
  275. data/spec/core_extensions_spec.rb +0 -763
  276. data/spec/core_model_spec.rb +0 -2
  277. data/spec/core_spec.rb +0 -1
  278. data/spec/deprecation_helper.rb +0 -30
  279. data/spec/extensions/accessed_columns_spec.rb +0 -51
  280. data/spec/extensions/active_model_spec.rb +0 -99
  281. data/spec/extensions/after_initialize_spec.rb +0 -28
  282. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  283. data/spec/extensions/association_dependencies_spec.rb +0 -125
  284. data/spec/extensions/association_pks_spec.rb +0 -423
  285. data/spec/extensions/association_proxies_spec.rb +0 -100
  286. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  287. data/spec/extensions/auto_validations_spec.rb +0 -229
  288. data/spec/extensions/blacklist_security_spec.rb +0 -95
  289. data/spec/extensions/blank_spec.rb +0 -69
  290. data/spec/extensions/boolean_readers_spec.rb +0 -93
  291. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  292. data/spec/extensions/caching_spec.rb +0 -273
  293. data/spec/extensions/caller_logging_spec.rb +0 -52
  294. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  295. data/spec/extensions/column_conflicts_spec.rb +0 -75
  296. data/spec/extensions/column_select_spec.rb +0 -129
  297. data/spec/extensions/columns_introspection_spec.rb +0 -90
  298. data/spec/extensions/columns_updated_spec.rb +0 -35
  299. data/spec/extensions/composition_spec.rb +0 -248
  300. data/spec/extensions/connection_expiration_spec.rb +0 -151
  301. data/spec/extensions/connection_validator_spec.rb +0 -144
  302. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  303. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  304. data/spec/extensions/constraint_validations_spec.rb +0 -439
  305. data/spec/extensions/core_refinements_spec.rb +0 -528
  306. data/spec/extensions/csv_serializer_spec.rb +0 -183
  307. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  308. data/spec/extensions/dataset_associations_spec.rb +0 -365
  309. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  310. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  311. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  312. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  313. data/spec/extensions/defaults_setter_spec.rb +0 -150
  314. data/spec/extensions/delay_add_association_spec.rb +0 -73
  315. data/spec/extensions/dirty_spec.rb +0 -189
  316. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  317. data/spec/extensions/eager_each_spec.rb +0 -62
  318. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  319. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  320. data/spec/extensions/error_splitter_spec.rb +0 -18
  321. data/spec/extensions/error_sql_spec.rb +0 -20
  322. data/spec/extensions/escaped_like_spec.rb +0 -40
  323. data/spec/extensions/eval_inspect_spec.rb +0 -81
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -291
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -864
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -111
  348. data/spec/extensions/nested_attributes_spec.rb +0 -767
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
  356. data/spec/extensions/pg_enum_spec.rb +0 -118
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -519
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -177
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -870
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -63
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -471
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/throw_failures_spec.rb +0 -74
  411. data/spec/extensions/timestamps_spec.rb +0 -209
  412. data/spec/extensions/to_dot_spec.rb +0 -153
  413. data/spec/extensions/touch_spec.rb +0 -226
  414. data/spec/extensions/tree_spec.rb +0 -334
  415. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  416. data/spec/extensions/unlimited_update_spec.rb +0 -21
  417. data/spec/extensions/update_or_create_spec.rb +0 -83
  418. data/spec/extensions/update_primary_key_spec.rb +0 -105
  419. data/spec/extensions/update_refresh_spec.rb +0 -59
  420. data/spec/extensions/uuid_spec.rb +0 -101
  421. data/spec/extensions/validate_associated_spec.rb +0 -52
  422. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  423. data/spec/extensions/validation_contexts_spec.rb +0 -31
  424. data/spec/extensions/validation_helpers_spec.rb +0 -525
  425. data/spec/extensions/whitelist_security_spec.rb +0 -157
  426. data/spec/extensions/xml_serializer_spec.rb +0 -213
  427. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  428. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  429. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  431. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  432. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  433. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  434. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  436. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  437. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  438. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  439. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  440. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  441. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  443. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  444. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  446. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  447. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  448. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  449. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  450. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  451. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  452. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  453. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  457. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  458. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  459. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  460. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  461. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  462. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  466. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  468. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  469. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  471. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  473. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  474. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  475. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  476. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  478. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  479. data/spec/guards_helper.rb +0 -59
  480. data/spec/integration/associations_test.rb +0 -2597
  481. data/spec/integration/database_test.rb +0 -113
  482. data/spec/integration/dataset_test.rb +0 -1981
  483. data/spec/integration/eager_loader_test.rb +0 -687
  484. data/spec/integration/migrator_test.rb +0 -262
  485. data/spec/integration/model_test.rb +0 -203
  486. data/spec/integration/plugin_test.rb +0 -2396
  487. data/spec/integration/prepared_statement_test.rb +0 -405
  488. data/spec/integration/schema_test.rb +0 -889
  489. data/spec/integration/spec_helper.rb +0 -65
  490. data/spec/integration/timezone_test.rb +0 -86
  491. data/spec/integration/transaction_test.rb +0 -603
  492. data/spec/integration/type_test.rb +0 -127
  493. data/spec/model/association_reflection_spec.rb +0 -803
  494. data/spec/model/associations_spec.rb +0 -4738
  495. data/spec/model/base_spec.rb +0 -875
  496. data/spec/model/class_dataset_methods_spec.rb +0 -146
  497. data/spec/model/dataset_methods_spec.rb +0 -198
  498. data/spec/model/eager_loading_spec.rb +0 -2377
  499. data/spec/model/hooks_spec.rb +0 -370
  500. data/spec/model/inflector_spec.rb +0 -26
  501. data/spec/model/model_spec.rb +0 -956
  502. data/spec/model/plugins_spec.rb +0 -429
  503. data/spec/model/record_spec.rb +0 -2118
  504. data/spec/model/spec_helper.rb +0 -46
  505. data/spec/model/validations_spec.rb +0 -220
  506. data/spec/model_no_assoc_spec.rb +0 -1
  507. data/spec/model_spec.rb +0 -1
  508. data/spec/plugin_spec.rb +0 -1
  509. data/spec/sequel_coverage.rb +0 -15
  510. data/spec/sequel_warning.rb +0 -4
  511. data/spec/spec_config.rb +0 -12
@@ -1,1981 +0,0 @@
1
- require_relative "spec_helper"
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.insert(:number=>20)
19
- @ds.insert(: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.insert(:number=>20)
32
- @ds.insert(: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 support ordering considering NULLS" do
43
- @ds.insert(:number=>20)
44
- @ds.insert(:number=>nil)
45
- @ds.order(Sequel[:number].asc(:nulls=>:first)).select_map(:number).must_equal [nil, 10, 20]
46
- @ds.order(Sequel[:number].asc(:nulls=>:last)).select_map(:number).must_equal [10, 20, nil]
47
- @ds.order(Sequel[:number].desc(:nulls=>:first)).select_map(:number).must_equal [nil, 20, 10]
48
- @ds.order(Sequel[:number].desc(:nulls=>:last)).select_map(:number).must_equal [20, 10, nil]
49
- end
50
-
51
- it "should have insert return primary key value" do
52
- @ds.insert(:number=>20).must_equal 2
53
- @ds.filter(:id=>2).first[:number].must_equal 20
54
- end
55
-
56
- it "should have insert work correctly with static SQL" do
57
- @db["INSERT INTO #{@ds.literal(:items)} (#{@ds.literal(:number)}) VALUES (20)"].insert
58
- @ds.filter(:id=>2).first[:number].must_equal 20
59
- end
60
-
61
- it "should join correctly" do
62
- @ds.join(Sequel[:items].as(:b), :id=>:id).select_all(:items).all.must_equal [{:id=>1, :number=>10}]
63
- end
64
-
65
- it "should handle LATERAL subqueries correctly" do
66
- @ds.insert(:number=>20)
67
- @ds.from(Sequel[:items].as(:i), @ds.where(Sequel[:items][:number]=>Sequel[:i][:number]).lateral).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal [[10, 10], [20, 20]]
68
- @ds.from(Sequel[:items].as(:i)).cross_join(@ds.where(Sequel[:items][:number]=>Sequel[:i][:number]).lateral).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal [[10, 10], [20, 20]]
69
- @ds.from(Sequel[:items].as(:i)).join(@ds.where(Sequel[:items][:number]=>Sequel[:i][:number]).lateral, 1=>1).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal [[10, 10], [20, 20]]
70
- @ds.from(Sequel[:items].as(:i)).join(@ds.where(Sequel[:items][:number]=>Sequel[:i][:number]).lateral, 1=>0).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal []
71
- @ds.from(Sequel[:items].as(:i)).left_join(@ds.from(Sequel[:items].as(:i2)).where(Sequel[:i2][:number]=>Sequel[:i][:number]).lateral, 1=>1).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal [[10, 10], [20, 20]]
72
- @ds.from(Sequel[:items].as(:i)).left_join(@ds.from(Sequel[:items].as(:i2)).where(Sequel[:i2][:number]=>Sequel[:i][:number]).lateral, 1=>0).select_order_map([Sequel[:i][:number].as(:n), Sequel[:t1][:number]]).must_equal [[10, nil], [20, nil]]
73
- end if DB.dataset.supports_lateral_subqueries?
74
-
75
- it "should correctly deal with qualified columns and subselects" do
76
- @ds.from_self(:alias=>:a).select(Sequel[:a][:id], Sequel.qualify(:a, :number)).all.must_equal [{:id=>1, :number=>10}]
77
- @ds.join(@ds.as(:a), :id=>:id).select(Sequel[:a][:id], Sequel.qualify(:a, :number)).all.must_equal [{:id=>1, :number=>10}]
78
- end
79
-
80
- it "should graph correctly" do
81
- a = [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
82
- pr = proc{|t| @ds.graph(t, {:id=>:id}, :table_alias=>:b).extension(:graph_each).all.must_equal a}
83
- pr[:items]
84
- pr[Sequel[:items].as(:foo)]
85
- pr[Sequel.identifier(:items)]
86
- pr[Sequel.identifier('items')]
87
- pr[Sequel.as(:items, :foo)]
88
- pr[Sequel.as(Sequel.identifier('items'), 'foo')]
89
- end
90
-
91
- it "should graph correctly with a subselect" do
92
- @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}}]
93
- end
94
-
95
- cspecify "should have insert work correctly when inserting a row with all NULL values", :hsqldb do
96
- @db.create_table!(:items) do
97
- String :name
98
- Integer :number
99
- end
100
- @ds.insert
101
- @ds.all.must_equal [{:name=>nil, :number=>nil}]
102
- end
103
-
104
- it "should delete correctly" do
105
- @ds.filter(1=>1).delete.must_equal 1
106
- @ds.count.must_equal 0
107
- end
108
-
109
- it "should update correctly" do
110
- @ds.update(:number=>Sequel.expr(:number)+1).must_equal 1
111
- @ds.all.must_equal [{:id=>1, :number=>11}]
112
- end
113
-
114
- it "should have update return the number of matched rows" do
115
- @ds.update(:number=>:number).must_equal 1
116
- @ds.filter(:id=>1).update(:number=>:number).must_equal 1
117
- @ds.filter(:id=>2).update(:number=>:number).must_equal 0
118
- @ds.all.must_equal [{:id=>1, :number=>10}]
119
- end
120
-
121
- it "should iterate over records as they come in" do
122
- called = false
123
- @ds.each{|row| called = true; row.must_equal(:id=>1, :number=>10)}
124
- called.must_equal true
125
- end
126
-
127
- it "should support iterating over large numbers of records with paged_each" do
128
- (2..100).each{|i| @ds.insert(:number=>i*10)}
129
-
130
- [:offset, :filter].each do |strategy|
131
- rows = []
132
- @ds.order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
133
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
134
-
135
- rows = []
136
- @ds.order(:number).paged_each(:rows_per_fetch=>3, :strategy=>strategy){|row| rows << row}
137
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
138
-
139
- rows = []
140
- @ds.order(:number, :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
141
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
142
-
143
- rows = []
144
- @ds.reverse_order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
145
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}}.reverse)
146
-
147
- rows = []
148
- @ds.order(Sequel.desc(:number), :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
149
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}}.reverse)
150
- end
151
-
152
- rows = []
153
- @ds.order(:number).limit(50, 25).paged_each(:rows_per_fetch=>3).each{|row| rows << row}
154
- rows.must_equal((26..75).map{|i| {:id=>i, :number=>i*10}})
155
-
156
- rows = []
157
- @ds.order(:number).limit(50, 25).paged_each(:rows_per_fetch=>3){|row| rows << row}
158
- rows.must_equal((26..75).map{|i| {:id=>i, :number=>i*10}})
159
-
160
- rows = []
161
- @ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5){|row| rows << row}
162
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
163
-
164
- rows = []
165
- @ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5, :strategy=>:filter, :filter_values=>proc{|row, _| [row[:number] * 2]}){|row| rows << row}
166
- rows.must_equal((1..100).map{|i| {:id=>i, :number=>i*10}})
167
-
168
- if DB.adapter_scheme == :jdbc
169
- # check retrival with varying fetch sizes
170
- array = (1..100).to_a
171
- [1, 2, 5, 10, 33, 50, 100, 1000].each do |i|
172
- @ds.with_fetch_size(i).select_order_map(:id).must_equal array
173
- end
174
- end
175
- end
176
-
177
- it "should fetch all results correctly" do
178
- @ds.all.must_equal [{:id=>1, :number=>10}]
179
- end
180
-
181
- it "should skip locked rows correctly" do
182
- @ds.insert(:number=>10)
183
- q1 = Queue.new
184
- q2 = Queue.new
185
- ds = @ds.order(:id).for_update.skip_locked
186
- begin
187
- t = Thread.new{@db.transaction(:isolation=>:committed){q2.push(ds.get(:id)); q1.pop}}
188
- q2.pop.must_equal 1
189
- # Some databases do row level locking, others do page level locking
190
- [2, nil].must_include @db.transaction(:isolation=>:committed){ds.get(:id)}
191
- ensure
192
- q1.push(nil)
193
- t.join
194
- # Keep only one active connection, as some other specs expect that
195
- @db.disconnect
196
- end
197
- end if DB.dataset.supports_skip_locked?
198
-
199
- it "should raise error instead of waiting for rows correctly" do
200
- @ds.insert(:number=>10)
201
- q1 = Queue.new
202
- q2 = Queue.new
203
- ds = @ds.order(:id).for_update.nowait
204
- begin
205
- t = Thread.new{@db.transaction(:isolation=>:committed){q2.push(ds.get(:id)); q1.pop}}
206
- q2.pop.must_equal 1
207
- # Some databases do row level locking, others do page level locking
208
- proc{@db.transaction(:isolation=>:committed){ds.get(:id)}}.must_raise Sequel::DatabaseLockTimeout
209
- ensure
210
- q1.push(nil)
211
- t.join
212
- # Keep only one active connection, as some other specs expect that
213
- @db.disconnect
214
- end
215
- end if DB.dataset.supports_nowait?
216
-
217
- it "should raise exception if raising on duplication columns" do
218
- proc{@ds.select_map([:id, :id])}.must_raise Sequel::DuplicateColumnError
219
- end if DB.opts[:on_duplicate_columns] == :raise
220
-
221
- it "should fetch a single row correctly" do
222
- @ds.first.must_equal(:id=>1, :number=>10)
223
- @ds.single_record.must_equal(:id=>1, :number=>10)
224
- @ds.single_record!.must_equal(:id=>1, :number=>10)
225
- end
226
-
227
- it "should work correctly when returning from each without iterating over the whole result set" do
228
- @ds.insert(:number=>20)
229
- @ds.order(:id).each{|v| break v}.must_equal(:id=>1, :number=>10)
230
- @ds.reverse(:id).each{|v| break v}.must_equal(:id=>2, :number=>20)
231
- end
232
-
233
- it "should fetch a single value correctly" do
234
- @ds.get(:id).must_equal 1
235
- @ds.select(:id).single_value.must_equal 1
236
- @ds.select(:id).single_value!.must_equal 1
237
- end
238
-
239
- it "should have distinct work with limit" do
240
- @ds.limit(1).distinct.all.must_equal [{:id=>1, :number=>10}]
241
- end
242
-
243
- it "should fetch correctly with a limit" do
244
- @ds.order(:id).limit(2).all.must_equal [{:id=>1, :number=>10}]
245
- @ds.insert(:number=>20)
246
- @ds.order(:id).limit(1).all.must_equal [{:id=>1, :number=>10}]
247
- @ds.order(:id).limit(2).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
248
- end
249
-
250
- it "should fetch correctly with a limit and offset" do
251
- @ds.order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10}]
252
- @ds.order(:id).limit(2, 1).all.must_equal []
253
- @ds.insert(:number=>20)
254
- @ds.order(:id).limit(1, 1).all.must_equal [{:id=>2, :number=>20}]
255
- @ds.order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
256
- @ds.order(:id).limit(2, 1).all.must_equal [{:id=>2, :number=>20}]
257
- end
258
-
259
- it "should fetch correctly with just offset" do
260
- @ds.order(:id).offset(0).all.must_equal [{:id=>1, :number=>10}]
261
- @ds.order(:id).offset(1).all.must_equal []
262
- @ds.insert(:number=>20)
263
- @ds.order(:id).offset(0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
264
- @ds.order(:id).offset(1).all.must_equal [{:id=>2, :number=>20}]
265
- @ds.order(:id).offset(2).all.must_equal []
266
- end
267
-
268
- it "should fetch correctly with a limit and offset using seperate methods" do
269
- @ds.order(:id).limit(2).offset(0).all.must_equal [{:id=>1, :number=>10}]
270
- @ds.order(:id).limit(2).offset(1).all.must_equal []
271
- @ds.insert(:number=>20)
272
- @ds.order(:id).limit(1).offset(1).all.must_equal [{:id=>2, :number=>20}]
273
- @ds.order(:id).limit(2).offset(0).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
274
- @ds.order(:id).limit(2).offset(1).all.must_equal [{:id=>2, :number=>20}]
275
- end
276
-
277
- it "should provide correct columns when using a limit and offset" do
278
- ds = @ds.order(:id).limit(1, 1)
279
- ds.all
280
- ds.columns.must_equal [:id, :number]
281
- @ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
282
- end
283
-
284
- it "should fetch correctly with a limit and offset for different combinations of from and join tables" do
285
- @db.create_table!(:items2){primary_key :id2; Integer :number2}
286
- @db[:items2].insert(:number2=>10)
287
- @ds.from(:items, :items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
288
- @ds.from(Sequel[:items].as(:i), Sequel[:items2].as(:i2)).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
289
- @ds.cross_join(:items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
290
- @ds.from(Sequel[:items].as(:i)).cross_join(Sequel[:items2].as(:i2)).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
291
- @ds.cross_join(Sequel[:items2].as(:i)).cross_join(@db[:items2].select(Sequel[:id2].as(:id3), Sequel[:number2].as(:number3))).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10, :id3=>1, :number3=>10}]
292
-
293
- @ds.from(:items, :items2).order(:id).limit(2, 1).all.must_equal []
294
- @ds.from(Sequel[:items].as(:i), Sequel[:items2].as(:i2)).order(:id).limit(2, 1).all.must_equal []
295
- @ds.cross_join(:items2).order(:id).limit(2, 1).all.must_equal []
296
- @ds.from(Sequel[:items].as(:i)).cross_join(Sequel[:items2].as(:i2)).order(:id).limit(2, 1).all.must_equal []
297
- @ds.cross_join(Sequel[:items2].as(:i)).cross_join(@db[:items2].select(Sequel[:id2].as(:id3), Sequel[:number2].as(:number3))).order(:id).limit(2, 1).all.must_equal []
298
- @db.drop_table(:items2)
299
- end
300
-
301
- it "should fetch correctly with a limit and offset without an order" do
302
- @ds.limit(2, 1).all.must_equal []
303
- @ds.join(Sequel[:items].as(:i), :id=>:id).select(Sequel[:items][:id].as(:s), Sequel[:i][:id].as(:id2)).limit(2, 1).all.must_equal []
304
- @ds.join(Sequel[:items].as(:i), :id=>:id).select(Sequel[:items][:id]).limit(2, 1).all.must_equal []
305
- @ds.join(Sequel[:items].as(:i), :id=>:id).select(Sequel.qualify(:items, :id)).limit(2, 1).all.must_equal []
306
- @ds.join(Sequel[:items].as(:i), :id=>:id).select(Sequel.qualify(:items, :id).as(:s)).limit(2, 1).all.must_equal []
307
- end
308
-
309
- it "should be orderable by column number" do
310
- @ds.insert(:number=>20)
311
- @ds.insert(:number=>10)
312
- @ds.order(2, 1).select_map([:id, :number]).must_equal [[1, 10], [3, 10], [2, 20]]
313
- end
314
-
315
- it "should fetch correctly with a limit in an IN subselect" do
316
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).all.must_equal [{:id=>1, :number=>10}]
317
- @ds.insert(:number=>20)
318
- @ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.must_equal [{:id=>1, :number=>10}]
319
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2)).order(:id).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
320
- end
321
-
322
- it "should fetch correctly with a limit and offset in an IN subselect" do
323
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.must_equal [{:id=>1, :number=>10}]
324
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.must_equal []
325
- @ds.insert(:number=>20)
326
- @ds.where(:id=>@ds.select(:id).order(:id).limit(1, 1)).all.must_equal [{:id=>2, :number=>20}]
327
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).order(:id).all.must_equal [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
328
- @ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.must_equal [{:id=>2, :number=>20}]
329
- end
330
-
331
- it "should fetch correctly when using limit and offset in a from_self" do
332
- @ds.insert(:number=>20)
333
- ds = @ds.order(:id).limit(1, 1).from_self
334
- ds.all.must_equal [{:number=>20, :id=>2}]
335
- ds.columns.must_equal [:id, :number]
336
- @ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
337
- end
338
-
339
- it "should fetch correctly when using nested limit and offset in a from_self" do
340
- @ds.insert(:number=>20)
341
- @ds.insert(:number=>30)
342
- ds = @ds.order(:id).limit(2, 1).from_self.reverse_order(:number).limit(1, 1)
343
- ds.all.must_equal [{:number=>20, :id=>2}]
344
- ds.columns.must_equal [:id, :number]
345
- @ds.order(:id).limit(2, 1).from_self.reverse_order(:number).limit(1, 1).columns.must_equal [:id, :number]
346
-
347
- ds = @ds.order(:id).limit(3, 1).from_self.limit(2, 1).from_self.limit(1, 1)
348
- ds.all.must_equal []
349
- ds.columns.must_equal [:id, :number]
350
-
351
- @ds.insert(:number=>40)
352
- ds = @ds.order(:id).limit(3, 1).from_self.reverse_order(:number).limit(2, 1).from_self.reverse_order(:id).limit(1, 1)
353
- ds.all.must_equal [{:number=>20, :id=>2}]
354
- ds.columns.must_equal [:id, :number]
355
- end
356
-
357
- it "should alias columns correctly" do
358
- @ds.select(Sequel[:id].as(:x), Sequel[:number].as(:n)).first.must_equal(:x=>1, :n=>10)
359
- end
360
-
361
- it "should support table aliases with column aliases" do
362
- DB.from(@ds.as(:i, [:x, :n])).first.must_equal(:x=>1, :n=>10)
363
- end if DB.dataset.supports_derived_column_lists?
364
-
365
- it "should handle true/false properly" do
366
- @ds.filter(Sequel::TRUE).select_map(:number).must_equal [10]
367
- @ds.filter(Sequel::FALSE).select_map(:number).must_equal []
368
- @ds.filter(true).select_map(:number).must_equal [10]
369
- @ds.filter(false).select_map(:number).must_equal []
370
- end
371
-
372
- it "should support the sql_comments extension" do
373
- ds = @ds.extension(:sql_comments).comment("Some\rComment\r\nHere")
374
- ds.all.must_equal [{:id=>1, :number=>10}]
375
- ds.insert(:number=>20).must_equal 2
376
- ds.update(:number=>30).must_equal 2
377
- ds.delete.must_equal 2
378
- end
379
- end
380
-
381
- describe "Simple dataset operations with nasty table names" do
382
- before do
383
- @db = DB
384
- @table = :"i`t' [e]\"m\\s"
385
- end
386
-
387
- cspecify "should work correctly", :oracle, :sqlanywhere, [:jdbc, :mssql] do
388
- @db.create_table!(@table) do
389
- primary_key :id
390
- Integer :number
391
- end
392
- @ds = @db[@table]
393
- @ds.insert(:number=>10).must_equal 1
394
- @ds.all.must_equal [{:id=>1, :number=>10}]
395
- @ds.update(:number=>20).must_equal 1
396
- @ds.all.must_equal [{:id=>1, :number=>20}]
397
- @ds.delete.must_equal 1
398
- @ds.count.must_equal 0
399
- @db.drop_table?(@table)
400
- end
401
- end if DB.dataset.quote_identifiers?
402
-
403
- describe Sequel::Dataset do
404
- before do
405
- DB.create_table!(:test) do
406
- String :name
407
- Integer :value
408
- end
409
- @d = DB[:test]
410
- end
411
- after do
412
- DB.drop_table?(:test)
413
- end
414
-
415
- it "should return the correct record count" do
416
- @d.count.must_equal 0
417
- @d.insert(:name => 'abc', :value => 123)
418
- @d.insert(:name => 'abc', :value => 456)
419
- @d.insert(:name => 'def', :value => nil)
420
- 5.times do
421
- @d.count.must_equal 3
422
- @d.count(:name).must_equal 3
423
- @d.count(:value).must_equal 2
424
- end
425
- end
426
-
427
- it "should handle functions with identifier names correctly" do
428
- @d.insert(:name => 'abc', :value => 6)
429
- @d.get{sum.function(:value)}.must_equal 6
430
- end
431
-
432
- it "should handle aggregate methods on limited datasets correctly" do
433
- @d.insert(:name => 'abc', :value => 6)
434
- @d.insert(:name => 'bcd', :value => 12)
435
- @d.insert(:name => 'def', :value => 18)
436
- @d = @d.order(:name).limit(2)
437
- @d.count.must_equal 2
438
- @d.avg(:value).to_i.must_equal 9
439
- @d.min(:value).to_i.must_equal 6
440
- @d.reverse.min(:value).to_i.must_equal 12
441
- @d.max(:value).to_i.must_equal 12
442
- @d.sum(:value).to_i.must_equal 18
443
- @d.extension(:sequel_4_dataset_methods).interval(:value).to_i.must_equal 6
444
- end
445
-
446
- it "should return the correct records" do
447
- @d.to_a.must_equal []
448
- @d.insert(:name => 'abc', :value => 123)
449
- @d.insert(:name => 'abc', :value => 456)
450
- @d.insert(:name => 'def', :value => 789)
451
-
452
- @d.order(:value).to_a.must_equal [
453
- {:name => 'abc', :value => 123},
454
- {:name => 'abc', :value => 456},
455
- {:name => 'def', :value => 789}
456
- ]
457
- end
458
-
459
- it "should update records correctly" do
460
- @d.insert(:name => 'abc', :value => 123)
461
- @d.insert(:name => 'abc', :value => 456)
462
- @d.insert(:name => 'def', :value => 789)
463
- @d.filter(:name => 'abc').update(:value => 530)
464
- @d[:name => 'def'][:value].must_equal 789
465
- @d.filter(:value => 530).count.must_equal 2
466
- end
467
-
468
- it "should delete records correctly" do
469
- @d.insert(:name => 'abc', :value => 123)
470
- @d.insert(:name => 'abc', :value => 456)
471
- @d.insert(:name => 'def', :value => 789)
472
- @d.filter(:name => 'abc').delete
473
- @d.count.must_equal 1
474
- @d.first[:name].must_equal 'def'
475
- end
476
-
477
- it "should be able to truncate the table" do
478
- @d.insert(:name => 'abc', :value => 123)
479
- @d.insert(:name => 'abc', :value => 456)
480
- @d.insert(:name => 'def', :value => 789)
481
- @d.count.must_equal 3
482
- @d.truncate.must_be_nil
483
- @d.count.must_equal 0
484
- end
485
-
486
- it "should be able to literalize booleans" do
487
- @d.literal(true)
488
- @d.literal(false)
489
- end
490
- end
491
-
492
- describe Sequel::Database do
493
- it "should correctly escape strings" do
494
- ["\\\n",
495
- "\\\\\n",
496
- "\\\r\n",
497
- "\\\\\r\n",
498
- "\\\\\n\n",
499
- "\\\\\r\n\r\n",
500
- "\\dingo",
501
- "\\'dingo",
502
- "\\\\''dingo",
503
- ].each do |str|
504
- DB.get(Sequel.cast(str, String)).must_equal str
505
- str = "1#{str}1"
506
- DB.get(Sequel.cast(str, String)).must_equal str
507
- str = "#{str}#{str}"
508
- DB.get(Sequel.cast(str, String)).must_equal str
509
- end
510
- end
511
-
512
- cspecify "should properly escape binary data", [:odbc], [:jdbc, :hsqldb], :oracle do
513
- DB.get(Sequel.cast(Sequel.blob("\1\2\3"), File).as(:a)).must_equal "\1\2\3"
514
- end
515
-
516
- cspecify "should properly handle empty blobs", [:jdbc, :hsqldb], :oracle do
517
- DB.get(Sequel.cast(Sequel.blob(""), File).as(:a)).must_equal ""
518
- end
519
-
520
- cspecify "should properly escape identifiers", :db2, :oracle, :sqlanywhere do
521
- DB.create_table!(:"\\'\"[]"){Integer :id}
522
- DB.drop_table(:"\\'\"[]")
523
- end
524
-
525
- it "should have a working table_exists?" do
526
- t = :basdfdsafsaddsaf
527
- DB.drop_table?(t)
528
- DB.table_exists?(t).must_equal false
529
- DB.create_table(t){Integer :a}
530
- begin
531
- DB.table_exists?(t).must_equal true
532
- ensure
533
- DB.drop_table(t)
534
- end
535
- end
536
- end
537
-
538
- describe Sequel::Dataset do
539
- before do
540
- DB.create_table! :items do
541
- primary_key :id
542
- Integer :value
543
- end
544
- @d = DB[:items]
545
- @d.insert(:value => 123)
546
- @d.insert(:value => 456)
547
- @d.insert(:value => 789)
548
- end
549
- after do
550
- DB.drop_table?(:items)
551
- end
552
-
553
- it "should correctly return avg" do
554
- @d.avg(:value).to_i.must_equal 456
555
- end
556
-
557
- it "should correctly return sum" do
558
- @d.sum(:value).to_i.must_equal 1368
559
- end
560
-
561
- it "should correctly return max" do
562
- @d.max(:value).to_i.must_equal 789
563
- end
564
-
565
- it "should correctly return min" do
566
- @d.min(:value).to_i.must_equal 123
567
- end
568
- end
569
-
570
- describe "Simple Dataset operations" do
571
- before do
572
- DB.create_table!(:items) do
573
- Integer :number
574
- TrueClass :flag
575
- end
576
- @ds = DB[:items]
577
- end
578
- after do
579
- DB.drop_table?(:items)
580
- end
581
-
582
- it "should deal with boolean conditions correctly" do
583
- @ds.insert(:number=>1, :flag=>true)
584
- @ds.insert(:number=>2, :flag=>false)
585
- @ds.insert(:number=>3, :flag=>nil)
586
- @ds = @ds.order(:number)
587
- @ds.filter(:flag=>true).map(:number).must_equal [1]
588
- @ds.filter(:flag=>false).map(:number).must_equal [2]
589
- @ds.filter(:flag=>nil).map(:number).must_equal [3]
590
- @ds.exclude(:flag=>true).map(:number).must_equal [2, 3]
591
- @ds.exclude(:flag=>false).map(:number).must_equal [1, 3]
592
- @ds.exclude(:flag=>nil).map(:number).must_equal [1, 2]
593
- end
594
- end
595
-
596
- describe "Simple Dataset operations in transactions" do
597
- before do
598
- DB.create_table!(:items) do
599
- primary_key :id
600
- integer :number
601
- end
602
- @ds = DB[:items]
603
- end
604
- after do
605
- DB.drop_table?(:items)
606
- end
607
-
608
- cspecify "should insert correctly with a primary key specified inside a transaction", :db2, :mssql do
609
- DB.transaction do
610
- @ds.insert(:id=>100, :number=>20)
611
- @ds.count.must_equal 1
612
- @ds.order(:id).all.must_equal [{:id=>100, :number=>20}]
613
- end
614
- end
615
-
616
- it "should have insert return primary key value inside a transaction" do
617
- DB.transaction do
618
- @ds.insert(:number=>20).must_equal 1
619
- @ds.count.must_equal 1
620
- @ds.order(:id).all.must_equal [{:id=>1, :number=>20}]
621
- end
622
- end
623
-
624
- it "should support for_update" do
625
- DB.transaction{@ds.for_update.all.must_equal []}
626
- end
627
- end
628
-
629
- describe "Dataset UNION, EXCEPT, and INTERSECT" do
630
- before do
631
- DB.create_table!(:i1){integer :number}
632
- DB.create_table!(:i2){integer :number}
633
- @ds1 = DB[:i1]
634
- @ds1.insert(:number=>10)
635
- @ds1.insert(:number=>20)
636
- @ds2 = DB[:i2]
637
- @ds2.insert(:number=>10)
638
- @ds2.insert(:number=>30)
639
- end
640
- after do
641
- DB.drop_table?(:i1, :i2, :i3)
642
- end
643
-
644
- it "should give the correct results for UNION with an existing order" do
645
- @ds1.order(:number).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30'
646
- end
647
-
648
- it "should give the correct results for simple UNION, EXCEPT, and INTERSECT" do
649
- @ds1.union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30'
650
- if @ds1.supports_intersect_except?
651
- @ds1.except(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
652
- @ds1.intersect(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
653
- end
654
- end
655
-
656
- it "should give the correct results for UNION, EXCEPT, and INTERSECT when used with ordering and limits and offsets" do
657
- [%w'10 30', %w'10 20 30'].must_include @ds1.limit(1).union(@ds2).order(:number).map{|x| x[:number].to_s}
658
- [%w'10 30', %w'10 20 30'].must_include @ds1.offset(1).union(@ds2).order(:number).map{|x| x[:number].to_s}
659
-
660
- @ds1.insert(:number=>8)
661
- @ds2.insert(:number=>9)
662
- @ds1.insert(:number=>38)
663
- @ds2.insert(:number=>39)
664
-
665
- @ds1.reverse_order(:number).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
666
- @ds1.union(@ds2.reverse_order(:number)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
667
-
668
- @ds1.reverse_order(:number).limit(1).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 30 38 39'
669
- @ds2.reverse_order(:number).limit(1).union(@ds1).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 38 39'
670
- @ds1.reverse_order(:number).limit(1, 1).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 20 30 39'
671
- @ds2.reverse_order(:number).limit(1, 1).union(@ds1).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 30 38'
672
- @ds1.reverse_order(:number).offset(1).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 39'
673
- @ds2.reverse_order(:number).offset(1).union(@ds1).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38'
674
-
675
- @ds1.union(@ds2.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 38'
676
- @ds2.union(@ds1.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 30 39'
677
- @ds1.union(@ds2.order(:number).limit(1, 1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 38'
678
- @ds2.union(@ds1.order(:number).limit(1, 1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 30 39'
679
- @ds1.union(@ds2.order(:number).offset(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 30 38 39'
680
- @ds2.union(@ds1.order(:number).offset(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 20 30 38 39'
681
-
682
- @ds1.union(@ds2).limit(2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9'
683
- @ds2.union(@ds1).reverse_order(:number).limit(2).map{|x| x[:number].to_s}.must_equal %w'39 38'
684
- @ds1.union(@ds2).limit(2, 1).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10'
685
- @ds2.union(@ds1).reverse_order(:number).limit(2, 1).map{|x| x[:number].to_s}.must_equal %w'38 30'
686
- @ds1.union(@ds2).offset(1).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 20 30 38 39'
687
- @ds2.union(@ds1).reverse_order(:number).offset(1).map{|x| x[:number].to_s}.must_equal %w'38 30 20 10 9 8'
688
-
689
- @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'
690
- @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'
691
- @ds1.reverse_order(:number).limit(2, 1).union(@ds2.reverse_order(:number).limit(2, 1)).order(:number).limit(3, 1).map{|x| x[:number].to_s}.must_equal %w'20 30'
692
- @ds2.order(:number).limit(2, 1).union(@ds1.order(:number).limit(2, 1)).reverse_order(:number).limit(3, 1).map{|x| x[:number].to_s}.must_equal %w'20 10'
693
- @ds1.reverse_order(:number).offset(1).union(@ds2.reverse_order(:number).offset(1)).order(:number).offset(1).map{|x| x[:number].to_s}.must_equal %w'9 10 20 30'
694
- @ds2.order(:number).offset(1).union(@ds1.order(:number).offset(1)).reverse_order(:number).offset(1).map{|x| x[:number].to_s}.must_equal %w'38 30 20 10'
695
- end
696
-
697
- it "should give the correct results for compound UNION, EXCEPT, and INTERSECT" do
698
- DB.create_table!(:i3){integer :number}
699
- @ds3 = DB[:i3]
700
- @ds3.insert(:number=>10)
701
- @ds3.insert(:number=>40)
702
-
703
- @ds1.union(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30 40'
704
- @ds1.union(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30 40'
705
- if @ds1.supports_intersect_except?
706
- @ds1.union(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'20 30'
707
- @ds1.union(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 30'
708
- @ds1.union(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 '
709
- @ds1.union(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20'
710
-
711
- @ds1.except(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20 40'
712
- @ds1.except(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
713
- @ds1.except(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
714
- @ds1.except(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 20'
715
- @ds1.except(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w''
716
- @ds1.except(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'20'
717
-
718
- @ds1.intersect(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10 40'
719
- @ds1.intersect(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
720
- @ds1.intersect(@ds2).except(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w''
721
- @ds1.intersect(@ds2.except(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w''
722
- @ds1.intersect(@ds2).intersect(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
723
- @ds1.intersect(@ds2.intersect(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'10'
724
- end
725
- end
726
- end
727
-
728
- if DB.dataset.supports_cte?
729
- describe "Common Table Expressions" do
730
- before(:all) do
731
- @db = DB
732
- @db.create_table!(:i1){Integer :id; Integer :parent_id}
733
- @ds = @db[:i1]
734
- @ds.insert(:id=>1)
735
- @ds.insert(:id=>2)
736
- @ds.insert(:id=>3, :parent_id=>1)
737
- @ds.insert(:id=>4, :parent_id=>1)
738
- @ds.insert(:id=>5, :parent_id=>3)
739
- @ds.insert(:id=>6, :parent_id=>5)
740
- end
741
- after(:all) do
742
- @db.drop_table?(:i1)
743
- end
744
-
745
- it "should give correct results for WITH" do
746
- @db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).must_equal [1, 2]
747
- end
748
-
749
- cspecify "should give correct results for recursive WITH", :db2 do
750
- ds = @db[:t].select(Sequel[:i].as(:id), Sequel[:pi].as(:parent_id)).with_recursive(:t, @ds.filter(:parent_id=>nil), @ds.join(:t, :i=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi]).order(:id)
751
- 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}]
752
- ps = @db[:t].select(Sequel[:i].as(:id), Sequel[:pi].as(:parent_id)).with_recursive(:t, @ds.filter(:parent_id=>:$n), @ds.join(:t, :i=>:parent_id).filter(Sequel[:t][:i]=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi]).order(:id).prepare(:select, :cte_sel)
753
- 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}]
754
- ps.call(:n=>3).must_equal [{:id=>5, :parent_id=>3}, {:id=>6, :parent_id=>5}]
755
- ps.call(:n=>5).must_equal [{:id=>6, :parent_id=>5}]
756
- end
757
-
758
- it "should support joining a dataset with a CTE" do
759
- @ds.inner_join(@db[:t].with(:t, @ds.filter(:parent_id=>nil)), :id => :id).select(Sequel[:i1][:id]).order(Sequel[:i1][:id]).map(:id).must_equal [1,2]
760
- @db[:t].with(:t, @ds).inner_join(@db[:s].with(:s, @ds.filter(:parent_id=>nil)), :id => :id).select(Sequel[:t][:id]).order(Sequel[:t][:id]).map(:id).must_equal [1,2]
761
- end
762
-
763
- it "should support a subselect in the FROM clause with a CTE" do
764
- @ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
765
- @db[:t].with(:t, @ds).from_self.select_order_map(:id).must_equal [1,2,3,4,5,6]
766
- end
767
-
768
- it "should support using a CTE inside a CTE" do
769
- @db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
770
- @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]
771
- end
772
-
773
- it "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
774
- @ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
775
- if @ds.supports_intersect_except?
776
- @ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
777
- @ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal []
778
- end
779
- end
780
- end
781
- end
782
-
783
- if DB.dataset.supports_cte?(:insert) || DB.dataset.supports_cte?(:update) || DB.dataset.supports_cte?(:delete)
784
- describe "Common Table Expressions" do
785
- before do
786
- @db = DB
787
- @db.create_table!(:i1){Integer :id}
788
- @ds = @db[:i1]
789
- @ds2 = @ds.with(:t, @ds)
790
- @ds.insert(:id=>1)
791
- @ds.insert(:id=>2)
792
- end
793
- after do
794
- @db.drop_table?(:i1)
795
- end
796
-
797
- it "should give correct results for WITH in insert" do
798
- @ds2.insert(@db[:t])
799
- @ds.select_order_map(:id).must_equal [1, 1, 2, 2]
800
- end if DB.dataset.supports_cte?(:insert)
801
-
802
- it "should give correct results for WITH in update" do
803
- @ds2.filter(:id=>@db[:t].select{max(id)}).update(:id=>Sequel.+(:id, 1))
804
- @ds.select_order_map(:id).must_equal [1, 3]
805
- end if DB.dataset.supports_cte?(:update)
806
-
807
- it "should give correct results for WITH in delete" do
808
- @ds2.filter(:id=>@db[:t].select{max(id)}).delete
809
- @ds.select_order_map(:id).must_equal [1]
810
- end if DB.dataset.supports_cte?(:delete)
811
-
812
- it "should support a subselect in an subquery used for INSERT" do
813
- @db.transaction(:rollback=>:always) do
814
- @ds.insert([:id], @db[:foo].with(:foo, @ds.select{(id + 10).as(:id)}))
815
- @ds.select_order_map(:id).must_equal [1,2,11,12]
816
- end
817
- end
818
- end
819
- end
820
-
821
- if DB.dataset.supports_returning?(:insert)
822
- describe "RETURNING clauses in INSERT" do
823
- before do
824
- @db = DB
825
- @db.create_table!(:i1){Integer :id; Integer :foo}
826
- @ds = @db[:i1]
827
- end
828
- after do
829
- @db.drop_table?(:i1)
830
- end
831
-
832
- it "should give correct results" do
833
- h = {}
834
- @ds.returning(:foo).insert(1, 2){|r| h = r}
835
- h.must_equal(:foo=>2)
836
- @ds.returning(:id).insert(3, 4){|r| h = r}
837
- h.must_equal(:id=>3)
838
- @ds.returning.insert(5, 6){|r| h = r}
839
- h.must_equal(:id=>5, :foo=>6)
840
- @ds.returning(Sequel[:id].as(:foo), Sequel[:foo].as(:id)).insert(7, 8){|r| h = r}
841
- h.must_equal(:id=>8, :foo=>7)
842
- end
843
- end
844
- end
845
-
846
- if DB.dataset.supports_returning?(:update) # Assume DELETE support as well
847
- describe "RETURNING clauses in UPDATE/DELETE" do
848
- before do
849
- @db = DB
850
- @db.create_table!(:i1){Integer :id; Integer :foo}
851
- @ds = @db[:i1]
852
- @ds.insert(1, 2)
853
- end
854
- after do
855
- @db.drop_table?(:i1)
856
- end
857
-
858
- it "should give correct results" do
859
- h = []
860
- @ds.returning(:foo).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
861
- h.must_equal [{:foo=>4}]
862
- h.clear
863
- @ds.returning(:id).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
864
- h.must_equal [{:id=>3}]
865
- h.clear
866
- @ds.returning.update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
867
- h.must_equal [{:id=>4, :foo=>16}]
868
- h.clear
869
- @ds.returning(Sequel[:id].as(:foo), Sequel[:foo].as(:id)).update(:id=>Sequel.+(:id, 1), :foo=>Sequel.*(:foo, 2)){|r| h << r}
870
- h.must_equal [{:id=>32, :foo=>5}]
871
- h.clear
872
-
873
- @ds.returning.delete{|r| h << r}
874
- h.must_equal [{:id=>5, :foo=>32}]
875
- h.clear
876
- @ds.returning.delete{|r| h << r}
877
- h.must_equal []
878
- end
879
- end
880
- end
881
-
882
- if DB.dataset.supports_window_functions?
883
- describe "Window Functions" do
884
- before(:all) do
885
- @db = DB
886
- @db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
887
- @ds = @db[:i1].order(:id)
888
- @ds.insert(:id=>1, :group_id=>1, :amount=>1)
889
- @ds.insert(:id=>2, :group_id=>1, :amount=>10)
890
- @ds.insert(:id=>3, :group_id=>1, :amount=>100)
891
- @ds.insert(:id=>4, :group_id=>2, :amount=>1000)
892
- @ds.insert(:id=>5, :group_id=>2, :amount=>10000)
893
- @ds.insert(:id=>6, :group_id=>2, :amount=>100000)
894
- end
895
- after(:all) do
896
- @db.drop_table?(:i1)
897
- end
898
-
899
- it "should give correct results for aggregate window functions" do
900
- @ds.select(:id){sum(:amount).over(:partition=>:group_id).as(:sum)}.all.
901
- 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}]
902
- @ds.select(:id){sum(:amount).over.as(:sum)}.all.
903
- 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}]
904
- end
905
-
906
- it "should give correct results for ranking window functions with orders" do
907
- @ds.select(:id){rank.function.over(:partition=>:group_id, :order=>:id).as(:rank)}.all.
908
- 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}]
909
- @ds.select(:id){rank.function.over(:order=>id).as(:rank)}.all.
910
- 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}]
911
- end
912
-
913
- it "should give correct results for aggregate window functions with orders" do
914
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id).as(:sum)}.all.
915
- 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}]
916
- @ds.select(:id){sum(:amount).over(:order=>:id).as(:sum)}.all.
917
- 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}]
918
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>id.desc, :frame=>:rows).as(:sum)}.all.
919
- must_equal [{:sum=>111, :id=>1}, {:sum=>110, :id=>2}, {:sum=>100, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>110000, :id=>5}, {:sum=>100000, :id=>6}]
920
- end
921
-
922
- it "should give correct results for aggregate window functions with frames" do
923
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:all).as(:sum)}.all.
924
- 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}]
925
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:all).as(:sum)}.all.
926
- 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}]
927
-
928
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:rows).as(:sum)}.all.
929
- 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}]
930
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:rows).as(:sum)}.all.
931
- 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}]
932
- end
933
-
934
- it "should give correct results for aggregate window functions with ranges" do
935
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:range).as(:sum)}.all.
936
- 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}]
937
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:group_id, :frame=>:range).as(:sum)}.all.
938
- 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}]
939
- end if DB.dataset.supports_window_function_frame_option?(:range)
940
-
941
- it "should give correct results for aggregate window functions with groups" do
942
- @ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:groups).as(:sum)}.all.
943
- 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}]
944
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>:groups).as(:sum)}.all.
945
- must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
946
- end if DB.dataset.supports_window_function_frame_option?(:groups)
947
-
948
- if DB.dataset.supports_window_function_frame_option?(:offset)
949
- it "should give correct results for aggregate window functions with offsets for ROWS" do
950
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>1}).as(:sum)}.all.
951
- must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>110, :id=>3}, {:sum=>1100, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>110000, :id=>6}]
952
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>1, :end=>1}).as(:sum)}.all.
953
- must_equal [{:sum=>11, :id=>1}, {:sum=>111, :id=>2}, {:sum=>1110, :id=>3}, {:sum=>11100, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>110000, :id=>6}]
954
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>2, :end=>[1, :preceding]}).as(:sum)}.all.
955
- must_equal [{:sum=>nil, :id=>1}, {:sum=>1, :id=>2}, {:sum=>11, :id=>3}, {:sum=>110, :id=>4}, {:sum=>1100, :id=>5}, {:sum=>11000, :id=>6}]
956
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>[1, :following], :end=>2}).as(:sum)}.order(:id).all.
957
- must_equal [{:sum=>110, :id=>1}, {:sum=>1100, :id=>2}, {:sum=>11000, :id=>3}, {:sum=>110000, :id=>4}, {:sum=>100000, :id=>5}, {:sum=>nil, :id=>6}]
958
- end
959
-
960
- cspecify "should give correct results for aggregate window functions with offsets for RANGES", :mssql, :sqlite, [proc{DB.server_version < 110000}, :postgres] do
961
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:range, :start=>1}).as(:sum)}.all.
962
- must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
963
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:range, :start=>0, :end=>1}).as(:sum)}.all.
964
- must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
965
- @ds.select(:id){sum(:amount).over(:order=>:amount, :frame=>{:type=>:range, :start=>100, :end=>1000}).as(:sum)}.all.
966
- must_equal [{:sum=>1111, :id=>1}, {:sum=>1111, :id=>2}, {:sum=>1111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>10000, :id=>5}, {:sum=>100000, :id=>6}]
967
- end if DB.dataset.supports_window_function_frame_option?(:range)
968
-
969
- it "should give correct results for aggregate window functions with offsets for GROUPS" do
970
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:groups, :start=>1}).as(:sum)}.all.
971
- must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
972
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:groups, :start=>0, :end=>1}).as(:sum)}.all.
973
- must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
974
- end if DB.dataset.supports_window_function_frame_option?(:groups)
975
- end
976
-
977
- it "should give correct results for aggregate window functions with exclusions" do
978
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>:preceding, :exclude=>:current}).as(:sum)}.all.
979
- must_equal [{:sum=>nil, :id=>1}, {:sum=>1, :id=>2}, {:sum=>11, :id=>3}, {:sum=>111, :id=>4}, {:sum=>1111, :id=>5}, {:sum=>11111, :id=>6}]
980
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:rows, :start=>:preceding, :exclude=>:group}).as(:sum)}.all.
981
- must_equal [{:sum=>nil, :id=>1}, {:sum=>nil, :id=>2}, {:sum=>nil, :id=>3}, {:sum=>111, :id=>4}, {:sum=>111, :id=>5}, {:sum=>111, :id=>6}]
982
- @ds.select(:id){sum(:amount).over(:order=>:group_id, :frame=>{:type=>:rows, :start=>:preceding, :exclude=>:ties}).as(:sum)}.all.
983
- must_equal [{:sum=>1, :id=>1}, {:sum=>10, :id=>2}, {:sum=>100, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>10111, :id=>5}, {:sum=>100111, :id=>6}]
984
- @ds.select(:id){sum(:amount).over(:order=>:id, :frame=>{:type=>:rows, :start=>:preceding, :exclude=>:no_others}).as(:sum)}.all.
985
- 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}]
986
- end if DB.dataset.supports_window_function_frame_option?(:exclude)
987
-
988
- it "should give correct results for window functions" do
989
- @ds.window(:win, :partition=>:group_id, :order=>:id).select(:id){sum(:amount).over(:window=>win, :frame=>:rows).as(:sum)}.all.
990
- 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}]
991
- @ds.window(:win, :partition=>:group_id).select(:id){sum(:amount).over(:window=>win, :order=>id, :frame=>:rows).as(:sum)}.all.
992
- 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}]
993
- @ds.window(:win, {}).select(:id){sum(:amount).over(:window=>:win, :order=>id, :frame=>:rows).as(:sum)}.all.
994
- 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}]
995
- @ds.window(:win, :partition=>:group_id).select(:id){sum(:amount).over(:window=>:win, :order=>id, :frame=>:all).as(:sum)}.all.
996
- 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}]
997
- end if DB.dataset.supports_window_clause?
998
- end
999
- end
1000
-
1001
- describe Sequel::SQL::Constants do
1002
- before do
1003
- @db = DB
1004
- @ds = @db[:constants]
1005
- @c = proc do |v|
1006
- case v
1007
- when Time
1008
- v
1009
- when DateTime, String
1010
- Time.parse(v.to_s)
1011
- else
1012
- v
1013
- end
1014
- end
1015
- @c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
1016
- end
1017
- after do
1018
- @db.drop_table?(:constants)
1019
- end
1020
-
1021
- cspecify "should have working CURRENT_DATE", [:jdbc, :sqlite], :oracle do
1022
- @db.create_table!(:constants){Date :d}
1023
- @ds.insert(:d=>Sequel::CURRENT_DATE)
1024
- d = @c2[@ds.get(:d)]
1025
- d.must_be_kind_of(Date)
1026
- d.to_s.must_equal Date.today.to_s
1027
- end
1028
-
1029
- cspecify "should have working CURRENT_TIME", [:jdbc, :sqlite], [:mysql2], [:tinytds], [:ado] do
1030
- @db.create_table!(:constants){Time :t, :only_time=>true}
1031
- @ds.insert(:t=>Sequel::CURRENT_TIME)
1032
- (Time.now - @c[@ds.get(:t)]).must_be_close_to 0, 60
1033
- end
1034
-
1035
- cspecify "should have working CURRENT_TIMESTAMP", [:jdbc, :sqlite] do
1036
- @db.create_table!(:constants){DateTime :ts}
1037
- @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
1038
- (Time.now - @c[@ds.get(:ts)]).must_be_close_to 0, 60
1039
- end
1040
-
1041
- cspecify "should have working CURRENT_TIMESTAMP when used as a column default", [:jdbc, :sqlite] do
1042
- @db.create_table!(:constants){DateTime :ts, :default=>Sequel::CURRENT_TIMESTAMP}
1043
- @ds.insert
1044
- (Time.now - @c[@ds.get(:ts)]).must_be_close_to 0, 60
1045
- end
1046
- end
1047
-
1048
- describe "Sequel::Dataset#import and #multi_insert" do
1049
- before(:all) do
1050
- @db = DB
1051
- @db.create_table!(:imp){Integer :i}
1052
- @ids = @db[:imp].order(:i)
1053
- end
1054
- before do
1055
- @ids.delete
1056
- end
1057
- after(:all) do
1058
- @db.drop_table?(:imp)
1059
- end
1060
-
1061
- it "should import with multi_insert and an array of hashes" do
1062
- @ids.multi_insert([{:i=>10}, {:i=>20}])
1063
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
1064
- end
1065
-
1066
- it "should import with an array of arrays of values" do
1067
- @ids.import([:i], [[10], [20]])
1068
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
1069
- end
1070
-
1071
- it "should import with a dataset" do
1072
- @db.create_table!(:exp2){Integer :i}
1073
- @db[:exp2].import([:i], [[10], [20]])
1074
- @ids.import([:i], @db[:exp2])
1075
- @ids.all.must_equal [{:i=>10}, {:i=>20}]
1076
- @db.drop_table(:exp2)
1077
- end
1078
-
1079
- it "should have import work with the :slice_size option" do
1080
- @ids.import([:i], [[10], [20], [30]], :slice_size=>1)
1081
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
1082
- @ids.delete
1083
- @ids.import([:i], [[10], [20], [30]], :slice_size=>2)
1084
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
1085
- @ids.delete
1086
- @ids.import([:i], [[10], [20], [30]], :slice_size=>3)
1087
- @ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
1088
- end
1089
-
1090
- it "should import many rows at once" do
1091
- @ids.import([:i], (1..1000).to_a.map{|x| [x]})
1092
- @ids.select_order_map(:i).must_equal((1..1000).to_a)
1093
- end
1094
- end
1095
-
1096
- describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
1097
- before do
1098
- @db = DB
1099
- @db.create_table!(:imp){primary_key :id; Integer :i}
1100
- @ds = @db[:imp]
1101
- end
1102
- after do
1103
- @db.drop_table?(:imp)
1104
- end
1105
-
1106
- it "should return primary key values" do
1107
- @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).must_equal [1, 2, 3]
1108
- @ds.import([:i], [[40], [50], [60]], :return=>:primary_key).must_equal [4, 5, 6]
1109
- @ds.order(:id).map([:id, :i]).must_equal [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
1110
- end
1111
-
1112
- it "should return primary key values when :slice is used" do
1113
- @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).must_equal [1, 2, 3]
1114
- @ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).must_equal [4, 5, 6]
1115
- @ds.order(:id).map([:id, :i]).must_equal [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
1116
- end
1117
- end
1118
-
1119
- describe "Sequel::Dataset convenience methods" do
1120
- before(:all) do
1121
- @db = DB
1122
- @db.create_table!(:a){Integer :a; Integer :b; Integer :c}
1123
- @ds = @db[:a]
1124
- @ds.insert(1, 3, 5)
1125
- @ds.insert(1, 3, 6)
1126
- @ds.insert(1, 4, 5)
1127
- @ds.insert(2, 3, 5)
1128
- @ds.insert(2, 4, 6)
1129
- end
1130
- after(:all) do
1131
- @db.drop_table?(:a)
1132
- end
1133
-
1134
- it "#group_rollup should include hierarchy of groupings" do
1135
- @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]]
1136
- @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]]
1137
- end if DB.dataset.supports_group_rollup?
1138
-
1139
- it "#group_cube should include all combinations of groupings" do
1140
- @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]]
1141
- @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]]
1142
- end if DB.dataset.supports_group_cube?
1143
-
1144
- it "#grouping_sets should include sets specified in group" do
1145
- @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]]
1146
- @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]]
1147
- end if DB.dataset.supports_grouping_sets?
1148
- end
1149
-
1150
- describe "Sequel::Dataset convenience methods" do
1151
- before(:all) do
1152
- @db = DB
1153
- @db.create_table!(:a){Integer :a; Integer :b}
1154
- @ds = @db[:a].order(:a)
1155
- end
1156
- before do
1157
- @ds.delete
1158
- end
1159
- after(:all) do
1160
- @db.drop_table?(:a)
1161
- end
1162
-
1163
- it "#empty? should return whether the dataset returns no rows" do
1164
- @ds.empty?.must_equal true
1165
- @ds.insert(20, 10)
1166
- @ds.empty?.must_equal false
1167
- end
1168
-
1169
- it "#empty? should work correctly for datasets with limits" do
1170
- ds = @ds.limit(1)
1171
- ds.empty?.must_equal true
1172
- ds.insert(20, 10)
1173
- ds.empty?.must_equal false
1174
- end
1175
-
1176
- it "#empty? should work correctly for datasets with limits and offsets" do
1177
- ds = @ds.limit(1, 1)
1178
- ds.empty?.must_equal true
1179
- ds.insert(20, 10)
1180
- ds.empty?.must_equal true
1181
- ds.insert(20, 10)
1182
- ds.empty?.must_equal false
1183
- end
1184
-
1185
- it "#group_and_count should return a grouping by count" do
1186
- @ds.group_and_count(:a).order{count(:a)}.all.must_equal []
1187
- @ds.insert(20, 10)
1188
- @ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>1}]
1189
- @ds.insert(20, 30)
1190
- @ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>2}]
1191
- @ds.insert(30, 30)
1192
- @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}]
1193
- end
1194
-
1195
- it "#group_and_count should support column aliases" do
1196
- @ds.group_and_count(Sequel[:a].as(:c)).order{count(:a)}.all.must_equal []
1197
- @ds.insert(20, 10)
1198
- @ds.group_and_count(Sequel[:a].as(:c)).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>1}]
1199
- @ds.insert(20, 30)
1200
- @ds.group_and_count(Sequel[:a].as(:c)).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>2}]
1201
- @ds.insert(30, 30)
1202
- @ds.group_and_count(Sequel[:a].as(:c)).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>30, :count=>1}, {:c=>20, :count=>2}]
1203
- end
1204
-
1205
- it "#range should return the range between the maximum and minimum values" do
1206
- @ds = @ds.unordered.extension(:sequel_4_dataset_methods)
1207
- @ds.insert(20, 10)
1208
- @ds.insert(30, 10)
1209
- @ds.range(:a).must_equal(20..30)
1210
- @ds.range(:b).must_equal(10..10)
1211
- end
1212
-
1213
- it "#interval should return the different between the maximum and minimum values" do
1214
- @ds = @ds.unordered.extension(:sequel_4_dataset_methods)
1215
- @ds.insert(20, 10)
1216
- @ds.insert(30, 10)
1217
- @ds.interval(:a).to_i.must_equal 10
1218
- @ds.interval(:b).to_i.must_equal 0
1219
- end
1220
- end
1221
-
1222
- describe "Sequel::Dataset main SQL methods" do
1223
- before(:all) do
1224
- @db = DB
1225
- @db.create_table!(:d){Integer :a; Integer :b}
1226
- @ds = @db[:d].order(:a)
1227
- end
1228
- before do
1229
- @ds.delete
1230
- end
1231
- after(:all) do
1232
- @db.drop_table?(:d)
1233
- end
1234
-
1235
- it "#exists should return a usable exists clause" do
1236
- @ds.filter(@db[Sequel[:d].as(:c)].filter(Sequel[:c][:a]=>Sequel[:d][:b]).exists).all.must_equal []
1237
- @ds.insert(20, 30)
1238
- @ds.insert(10, 20)
1239
- @ds.filter(@db[Sequel[:d].as(:c)].filter(Sequel[:c][:a]=>Sequel[:d][:b]).exists).all.must_equal [{:a=>10, :b=>20}]
1240
- end
1241
-
1242
- it "#filter and #exclude should work with placeholder strings" do
1243
- @ds.insert(20, 30)
1244
- @ds.filter(Sequel.lit("a > ?", 15)).all.must_equal [{:a=>20, :b=>30}]
1245
- @ds.exclude(Sequel.lit("b < ?", 15)).all.must_equal [{:a=>20, :b=>30}]
1246
- @ds.filter(Sequel.lit("b < ?", 15)).invert.all.must_equal [{:a=>20, :b=>30}]
1247
- end
1248
-
1249
- it "#where and #or should work correctly" do
1250
- @ds.insert(20, 30)
1251
- @ds.filter(:a=>20).where(:b=>30).all.must_equal [{:a=>20, :b=>30}]
1252
- @ds.filter(:a=>20).where(:b=>15).all.must_equal []
1253
- @ds.filter(:a=>20).or(:b=>15).all.must_equal [{:a=>20, :b=>30}]
1254
- @ds.filter(:a=>10).or(:b=>15).all.must_equal []
1255
- end
1256
-
1257
- it "#select_group should work correctly" do
1258
- @ds = @ds.unordered
1259
- @ds.select_group(:a).all.must_equal []
1260
- @ds.insert(20, 30)
1261
- @ds.select_group(:a).all.must_equal [{:a=>20}]
1262
- @ds.select_group(:b).all.must_equal [{:b=>30}]
1263
- @ds.insert(20, 40)
1264
- @ds.select_group(:a).all.must_equal [{:a=>20}]
1265
- @ds.order(:b).select_group(:b).all.must_equal [{:b=>30}, {:b=>40}]
1266
- end
1267
-
1268
- it "#select_group should work correctly when aliasing" do
1269
- @ds = @ds.unordered
1270
- @ds.insert(20, 30)
1271
- @ds.select_group(Sequel[:b].as(:c)).all.must_equal [{:c=>30}]
1272
- end
1273
-
1274
- it "#having should work correctly" do
1275
- @ds = @ds.unordered
1276
- @ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
1277
- @ds.insert(20, 30)
1278
- @ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
1279
- @ds.insert(40, 20)
1280
- @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}]
1281
- end
1282
-
1283
- cspecify "#having should work without a previous group", :sqlite do
1284
- @ds = @ds.unordered
1285
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
1286
- @ds.insert(20, 30)
1287
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
1288
- @ds.insert(40, 20)
1289
- @ds.select{max(a).as(c)}.having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.must_equal [{:c=>40}]
1290
- end
1291
- end
1292
-
1293
- describe "Sequel::Dataset convenience methods" do
1294
- before(:all) do
1295
- @db = DB
1296
- @db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
1297
- @ds = @db[:a].order(:a)
1298
- end
1299
- before do
1300
- @ds.delete
1301
- @ds.insert(1, 2, 3, 4)
1302
- @ds.insert(5, 6, 7, 8)
1303
- end
1304
- after(:all) do
1305
- @db.drop_table?(:a)
1306
- end
1307
-
1308
- it "should have working #map" do
1309
- @ds.map(:a).must_equal [1, 5]
1310
- @ds.map(:b).must_equal [2, 6]
1311
- @ds.map([:a, :b]).must_equal [[1, 2], [5, 6]]
1312
- end
1313
-
1314
- it "should have working #as_hash" do
1315
- @ds.to_hash(:a).must_equal(1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8})
1316
- @ds.as_hash(:a).must_equal(1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8})
1317
- @ds.as_hash(:b).must_equal(2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8})
1318
- @ds.as_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})
1319
-
1320
- @ds.as_hash(:a, :b).must_equal(1=>2, 5=>6)
1321
- @ds.as_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
1322
- @ds.as_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
1323
- @ds.as_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
1324
- @ds.extension(:null_dataset).nullify.as_hash([:a, :c], [:b, :d]).must_equal({})
1325
-
1326
- @ds.as_hash(:a, :b, :hash => (tmp = {})).must_be_same_as(tmp)
1327
- end
1328
-
1329
- it "should have working #to_hash_groups" do
1330
- ds = @ds.order(*@ds.columns)
1331
- ds.insert(1, 2, 3, 9)
1332
- 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}])
1333
- 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}])
1334
- 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}])
1335
-
1336
- ds.to_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
1337
- ds.to_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
1338
- ds.to_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
1339
- ds.to_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
1340
- @ds.extension(:null_dataset).nullify.to_hash_groups([:a, :c], [:b, :d]).must_equal({})
1341
-
1342
- ds.to_hash_groups(:a, :d, :hash => (tmp = {})).must_be_same_as(tmp)
1343
- end
1344
-
1345
- it "should have working #select_map" do
1346
- @ds.select_map(:a).must_equal [1, 5]
1347
- @ds.select_map(:b).must_equal [2, 6]
1348
- @ds.select_map([:a]).must_equal [[1], [5]]
1349
- @ds.select_map([:a, :b]).must_equal [[1, 2], [5, 6]]
1350
- @ds.extension(:null_dataset).nullify.select_map([:a, :b]).must_equal []
1351
-
1352
- @ds.select_map(Sequel[:a].as(:e)).must_equal [1, 5]
1353
- @ds.select_map(Sequel[:b].as(:e)).must_equal [2, 6]
1354
- @ds.select_map([Sequel[:a].as(:e), Sequel[:b].as(:f)]).must_equal [[1, 2], [5, 6]]
1355
- @ds.select_map([Sequel[:a][:a].as(:e), Sequel[:a][:b].as(:f)]).must_equal [[1, 2], [5, 6]]
1356
- @ds.select_map([Sequel.expr(Sequel[:a][:a]).as(:e), Sequel.expr(Sequel[:a][:b]).as(:f)]).must_equal [[1, 2], [5, 6]]
1357
- @ds.select_map([Sequel.qualify(:a, :a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
1358
- @ds.select_map([Sequel.identifier(:a).qualify(:a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
1359
- end
1360
-
1361
- it "should have working #select_order_map" do
1362
- @ds.select_order_map(:a).must_equal [1, 5]
1363
- @ds.select_order_map(Sequel.desc(Sequel[:a][:b])).must_equal [6, 2]
1364
- @ds.select_order_map(Sequel.desc(Sequel[:a][:b].as(:e))).must_equal [6, 2]
1365
- @ds.select_order_map(Sequel.qualify(:a, :b).as(:e)).must_equal [2, 6]
1366
- @ds.select_order_map([:a]).must_equal [[1], [5]]
1367
- @ds.select_order_map([Sequel.desc(:a), :b]).must_equal [[5, 6], [1, 2]]
1368
- @ds.extension(:null_dataset).nullify.select_order_map(:a).must_equal []
1369
-
1370
- @ds.select_order_map(Sequel[:a].as(:e)).must_equal [1, 5]
1371
- @ds.select_order_map(Sequel[:b].as(:e)).must_equal [2, 6]
1372
- @ds.select_order_map([Sequel.desc(Sequel[:a].as(:e)), Sequel[:b].as(:f)]).must_equal [[5, 6], [1, 2]]
1373
- @ds.select_order_map([Sequel.desc(Sequel[:a][:a].as(:e)), Sequel[:a][:b].as(:f)]).must_equal [[5, 6], [1, 2]]
1374
- @ds.select_order_map([Sequel.desc(Sequel[:a][:a]), Sequel.expr(Sequel[:a][:b]).as(:f)]).must_equal [[5, 6], [1, 2]]
1375
- @ds.select_order_map([Sequel.qualify(:a, :a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
1376
- @ds.select_order_map([Sequel.identifier(:a).qualify(:a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
1377
- end
1378
-
1379
- it "should have working #select_hash" do
1380
- @ds.select_hash(:a, :b).must_equal(1=>2, 5=>6)
1381
- @ds.select_hash(Sequel[:a][:a].as(:e), :b).must_equal(1=>2, 5=>6)
1382
- @ds.select_hash(Sequel.expr(Sequel[:a][:a]).as(:e), :b).must_equal(1=>2, 5=>6)
1383
- @ds.select_hash(Sequel.qualify(:a, :a).as(:e), :b).must_equal(1=>2, 5=>6)
1384
- @ds.select_hash(Sequel.identifier(:a).qualify(:a).as(:e), :b).must_equal(1=>2, 5=>6)
1385
- @ds.select_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
1386
- @ds.select_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
1387
- @ds.select_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
1388
- @ds.select_hash(:a, :b, :hash => (tmp = {})).must_be_same_as(tmp)
1389
- @ds.extension(:null_dataset).nullify.select_hash(:a, :b).must_equal({})
1390
- end
1391
-
1392
- it "should have working #select_hash_groups" do
1393
- ds = @ds.order(*@ds.columns)
1394
- ds.insert(1, 2, 3, 9)
1395
- ds.select_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
1396
- ds.select_hash_groups(Sequel[:a][:a].as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1397
- ds.select_hash_groups(Sequel.expr(Sequel[:a][:a]).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1398
- ds.select_hash_groups(Sequel.qualify(:a, :a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1399
- ds.select_hash_groups(Sequel.identifier(:a).qualify(:a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
1400
- ds.select_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
1401
- ds.select_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
1402
- ds.select_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
1403
- ds.select_hash_groups(:a, :d, :hash => (tmp = {})).must_be_same_as(tmp)
1404
- @ds.extension(:null_dataset).nullify.select_hash_groups(:a, :d).must_equal({})
1405
- end
1406
- end
1407
-
1408
- describe "Sequel::Dataset DSL support" do
1409
- before(:all) do
1410
- @db = DB
1411
- @db.create_table!(:a){Integer :a; Integer :b}
1412
- @ds = @db[:a].order(:a)
1413
- end
1414
- before do
1415
- @ds.delete
1416
- end
1417
- after(:all) do
1418
- @db.drop_table?(:a)
1419
- end
1420
-
1421
- it "should work with standard mathematical operators" do
1422
- @ds.insert(20, 10)
1423
- @ds.get{a + b}.to_i.must_equal 30
1424
- @ds.get{a - b}.to_i.must_equal 10
1425
- @ds.get{a * b}.to_i.must_equal 200
1426
- @ds.get{a / b}.to_i.must_equal 2
1427
- end
1428
-
1429
- it "should work with exponentiation operator" do
1430
- @ds.insert(:a=>2)
1431
- (-4..4).each do |i|
1432
- # Allow minor differences due to emulation issues on some adapters
1433
- @ds.get{(a / 1.0) ** i}.to_f.must_be_close_to((2**i).to_f)
1434
- end
1435
- end
1436
-
1437
- cspecify "should work with bitwise shift operators", :derby do
1438
- @ds.insert(3, 2)
1439
- b = Sequel[:b]
1440
- b = b.cast(:integer) if @db.database_type == :postgres
1441
- @ds.get{a.sql_number << b}.to_i.must_equal 12
1442
- @ds.get{a.sql_number >> b}.to_i.must_equal 0
1443
- @ds.get{a.sql_number << b << 1}.to_i.must_equal 24
1444
- @ds.delete
1445
- @ds.insert(3, 1)
1446
- @ds.get{a.sql_number << b}.to_i.must_equal 6
1447
- @ds.get{a.sql_number >> b}.to_i.must_equal 1
1448
- @ds.get{a.sql_number >> b >> 1}.to_i.must_equal 0
1449
- end
1450
-
1451
- cspecify "should work with bitwise AND and OR operators", :derby do
1452
- @ds.insert(3, 5)
1453
- @ds.get{a.sql_number | b}.to_i.must_equal 7
1454
- @ds.get{a.sql_number & b}.to_i.must_equal 1
1455
- @ds.get{a.sql_number | b | 8}.to_i.must_equal 15
1456
- @ds.get{a.sql_number & b & 8}.to_i.must_equal 0
1457
- end
1458
-
1459
- it "should work with the bitwise compliment operator" do
1460
- @ds.insert(-3, 3)
1461
- @ds.get{~a.sql_number}.to_i.must_equal 2
1462
- @ds.get{~b.sql_number}.to_i.must_equal(-4)
1463
- end
1464
-
1465
- cspecify "should work with the bitwise xor operator", :derby do
1466
- @ds.insert(3, 5)
1467
- @ds.get{a.sql_number ^ b}.to_i.must_equal 6
1468
- @ds.get{a.sql_number ^ b ^ 1}.to_i.must_equal 7
1469
- end
1470
-
1471
- it "should work with the modulus operator" do
1472
- @ds.insert(3, 5)
1473
- @ds.get{a.sql_number % 4}.to_i.must_equal 3
1474
- @ds.get{b.sql_number % 4}.to_i.must_equal 1
1475
- @ds.get{a.sql_number % 4 % 2}.to_i.must_equal 1
1476
- end
1477
-
1478
- it "should work with inequality operators" do
1479
- @ds.insert(10, 11)
1480
- @ds.insert(11, 11)
1481
- @ds.insert(20, 19)
1482
- @ds.insert(20, 20)
1483
- @ds.filter{a > b}.select_order_map(:a).must_equal [20]
1484
- @ds.filter{a >= b}.select_order_map(:a).must_equal [11, 20, 20]
1485
- @ds.filter{a < b}.select_order_map(:a).must_equal [10]
1486
- @ds.filter{a <= b}.select_order_map(:a).must_equal [10, 11, 20]
1487
- end
1488
-
1489
- it "should work with casting and string concatentation" do
1490
- @ds.insert(20, 20)
1491
- @ds.get{Sequel.cast(a, String).sql_string + Sequel.cast(b, String)}.must_equal '2020'
1492
- end
1493
-
1494
- it "should work with ordering" do
1495
- @ds.insert(10, 20)
1496
- @ds.insert(20, 10)
1497
- @ds.order(:a, :b).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
1498
- @ds.order(Sequel.asc(:a), Sequel.asc(:b)).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
1499
- @ds.order(Sequel.desc(:a), Sequel.desc(:b)).all.must_equal [{:a=>20, :b=>10}, {:a=>10, :b=>20}]
1500
- end
1501
-
1502
- it "should work with qualifying" do
1503
- @ds.insert(10, 20)
1504
- @ds.get(Sequel[:a][:b]).must_equal 20
1505
- @ds.get{a[:b]}.must_equal 20
1506
- @ds.get(Sequel.qualify(:a, :b)).must_equal 20
1507
- end
1508
-
1509
- it "should work with aliasing" do
1510
- @ds.insert(10, 20)
1511
- @ds.get(Sequel[:a][:b].as(:c)).must_equal 20
1512
- @ds.get{a[:b].as(c)}.must_equal 20
1513
- @ds.get(Sequel.qualify(:a, :b).as(:c)).must_equal 20
1514
- @ds.get(Sequel.as(:b, :c)).must_equal 20
1515
- end
1516
-
1517
- it "should work with selecting all columns of a table" do
1518
- @ds.insert(20, 10)
1519
- @ds.select_all(:a).all.must_equal [{:a=>20, :b=>10}]
1520
- end
1521
-
1522
- it "should work with ranges as hash values" do
1523
- @ds.insert(20, 10)
1524
- @ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
1525
- @ds.filter(:a=>(25..30)).all.must_equal []
1526
- @ds.filter(:a=>(10..15)).all.must_equal []
1527
- @ds.exclude(:a=>(10..30)).all.must_equal []
1528
- @ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
1529
- @ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
1530
- end
1531
-
1532
- it "should work with nil as hash value" do
1533
- @ds.insert(20, nil)
1534
- @ds.filter(:a=>nil).all.must_equal []
1535
- @ds.filter(:b=>nil).all.must_equal [{:a=>20, :b=>nil}]
1536
- @ds.exclude(:b=>nil).all.must_equal []
1537
- @ds.exclude(:a=>nil).all.must_equal [{:a=>20, :b=>nil}]
1538
- end
1539
-
1540
- it "should work with arrays as hash values" do
1541
- @ds.insert(20, 10)
1542
- @ds.filter(:a=>[10]).all.must_equal []
1543
- @ds.filter(:a=>[20, 10]).all.must_equal [{:a=>20, :b=>10}]
1544
- @ds.exclude(:a=>[10]).all.must_equal [{:a=>20, :b=>10}]
1545
- @ds.exclude(:a=>[20, 10]).all.must_equal []
1546
- end
1547
-
1548
- it "should work with ranges as hash values" do
1549
- @ds.insert(20, 10)
1550
- @ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
1551
- @ds.filter(:a=>(25..30)).all.must_equal []
1552
- @ds.filter(:a=>(10..15)).all.must_equal []
1553
- @ds.exclude(:a=>(10..30)).all.must_equal []
1554
- @ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
1555
- @ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
1556
- end
1557
-
1558
- it "should work with CASE statements" do
1559
- @ds.insert(20, 10)
1560
- @ds.filter(Sequel.case({{:a=>20}=>20}, 0) > 0).all.must_equal [{:a=>20, :b=>10}]
1561
- @ds.filter(Sequel.case({{:a=>15}=>20}, 0) > 0).all.must_equal []
1562
- @ds.filter(Sequel.case({20=>20}, 0, :a) > 0).all.must_equal [{:a=>20, :b=>10}]
1563
- @ds.filter(Sequel.case({15=>20}, 0, :a) > 0).all.must_equal []
1564
- end
1565
-
1566
- it "should work with multiple value arrays" do
1567
- @ds.insert(20, 10)
1568
- @ds.filter([:a, :b]=>[[20, 10]]).all.must_equal [{:a=>20, :b=>10}]
1569
- @ds.filter([:a, :b]=>[[10, 20]]).all.must_equal []
1570
- @ds.filter([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal [{:a=>20, :b=>10}]
1571
- @ds.filter([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal []
1572
-
1573
- @ds.exclude([:a, :b]=>[[20, 10]]).all.must_equal []
1574
- @ds.exclude([:a, :b]=>[[10, 20]]).all.must_equal [{:a=>20, :b=>10}]
1575
- @ds.exclude([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal []
1576
- @ds.exclude([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal [{:a=>20, :b=>10}]
1577
- end
1578
-
1579
- it "should work with IN/NOT in with datasets" do
1580
- @ds.insert(20, 10)
1581
- ds = @ds.unordered
1582
-
1583
- @ds.filter(:a=>ds.select(:a)).all.must_equal [{:a=>20, :b=>10}]
1584
- @ds.filter(:a=>ds.select(:a).where(:a=>15)).all.must_equal []
1585
- @ds.exclude(:a=>ds.select(:a)).all.must_equal []
1586
- @ds.exclude(:a=>ds.select(:a).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
1587
-
1588
- @ds.filter([:a, :b]=>ds.select(:a, :b)).all.must_equal [{:a=>20, :b=>10}]
1589
- @ds.filter([:a, :b]=>ds.select(:b, :a)).all.must_equal []
1590
- @ds.exclude([:a, :b]=>ds.select(:a, :b)).all.must_equal []
1591
- @ds.exclude([:a, :b]=>ds.select(:b, :a)).all.must_equal [{:a=>20, :b=>10}]
1592
-
1593
- @ds.filter([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal []
1594
- @ds.exclude([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
1595
- end
1596
-
1597
- it "should work empty arrays" do
1598
- @ds.insert(20, 10)
1599
- @ds.filter(:a=>[]).all.must_equal []
1600
- @ds.exclude(:a=>[]).all.must_equal [{:a=>20, :b=>10}]
1601
- @ds.filter([:a, :b]=>[]).all.must_equal []
1602
- @ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>20, :b=>10}]
1603
- end
1604
-
1605
- it "should work empty arrays with nulls when using empty_array_consider_nulls extension" do
1606
- @ds = @ds.extension(:empty_array_consider_nulls)
1607
- @ds.insert(nil, nil)
1608
- @ds.filter(:a=>[]).all.must_equal []
1609
- @ds.exclude(:a=>[]).all.must_equal []
1610
- @ds.filter([:a, :b]=>[]).all.must_equal []
1611
- @ds.exclude([:a, :b]=>[]).all.must_equal []
1612
-
1613
- unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1614
- # Some databases don't like boolean results in the select list
1615
- pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1616
- pr[@ds.get(Sequel.expr(:a=>[]))].must_be_nil
1617
- pr[@ds.get(~Sequel.expr(:a=>[]))].must_be_nil
1618
- pr[@ds.get(Sequel.expr([:a, :b]=>[]))].must_be_nil
1619
- pr[@ds.get(~Sequel.expr([:a, :b]=>[]))].must_be_nil
1620
- end
1621
- end
1622
-
1623
- it "should work empty arrays with nulls" do
1624
- ds = @ds
1625
- ds.insert(nil, nil)
1626
- ds.filter(:a=>[]).all.must_equal []
1627
- ds.exclude(:a=>[]).all.must_equal [{:a=>nil, :b=>nil}]
1628
- ds.filter([:a, :b]=>[]).all.must_equal []
1629
- ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>nil, :b=>nil}]
1630
-
1631
- unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1632
- # Some databases don't like boolean results in the select list
1633
- pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1634
- pr[ds.get(Sequel.expr(:a=>[]))].must_equal false
1635
- pr[ds.get(~Sequel.expr(:a=>[]))].must_equal true
1636
- pr[ds.get(Sequel.expr([:a, :b]=>[]))].must_equal false
1637
- pr[ds.get(~Sequel.expr([:a, :b]=>[]))].must_equal true
1638
- end
1639
- end
1640
-
1641
- it "should work multiple conditions" do
1642
- @ds.insert(20, 10)
1643
- @ds.filter(:a=>20, :b=>10).all.must_equal [{:a=>20, :b=>10}]
1644
- @ds.filter([[:a, 20], [:b, 10]]).all.must_equal [{:a=>20, :b=>10}]
1645
- @ds.filter(Sequel.&({:a=>20}, {:b=>10})).all.must_equal [{:a=>20, :b=>10}]
1646
- @ds.filter(Sequel.|({:a=>20}, {:b=>5})).all.must_equal [{:a=>20, :b=>10}]
1647
- @ds.filter(Sequel.~(:a=>10)).all.must_equal [{:a=>20, :b=>10}]
1648
- end
1649
- end
1650
-
1651
- describe "SQL Extract Function" do
1652
- before do
1653
- @db = DB
1654
- @db.create_table!(:a){DateTime :a}
1655
- @ds = @db[:a].order(:a)
1656
- end
1657
- after do
1658
- @db.drop_table?(:a)
1659
- end
1660
-
1661
- it "should return the part of the datetime asked for" do
1662
- t = Time.now
1663
- @ds = @ds.with_extend{def supports_timestamp_timezones?() false end}
1664
- @ds.insert(t)
1665
- @ds.get{a.extract(:year)}.must_equal t.year
1666
- @ds.get{a.extract(:month)}.must_equal t.month
1667
- @ds.get{a.extract(:day)}.must_equal t.day
1668
- @ds.get{a.extract(:hour)}.must_equal t.hour
1669
- @ds.get{a.extract(:minute)}.must_equal t.min
1670
- @ds.get{a.extract(:second)}.to_i.must_equal t.sec
1671
- end
1672
- end
1673
-
1674
- describe "Dataset string methods" do
1675
- before(:all) do
1676
- @db = DB
1677
- csc = {}
1678
- cic = {}
1679
- if @db.database_type == :mssql
1680
- csc[:collate] = 'Latin1_General_CS_AS'
1681
- cic[:collate] = 'Latin1_General_CI_AS'
1682
- end
1683
- @db.create_table!(:a) do
1684
- String :a, csc
1685
- String :b, cic
1686
- end
1687
- @ds = @db[:a].order(:a)
1688
- end
1689
- before do
1690
- @ds.delete
1691
- end
1692
- after(:all) do
1693
- @db.drop_table?(:a)
1694
- end
1695
-
1696
- it "#grep should return matching rows" do
1697
- @ds.insert('foo', 'bar')
1698
- @ds.grep(:a, 'foo').all.must_equal [{:a=>'foo', :b=>'bar'}]
1699
- @ds.grep(:b, 'foo').all.must_equal []
1700
- @ds.grep(:b, 'bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
1701
- @ds.grep(:a, 'bar').all.must_equal []
1702
- @ds.grep([:a, :b], %w'foo bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
1703
- @ds.grep([:a, :b], %w'boo far').all.must_equal []
1704
- end
1705
-
1706
- it "#grep should work with :all_patterns and :all_columns options" do
1707
- @ds.insert('foo bar', ' ')
1708
- @ds.insert('foo d', 'bar')
1709
- @ds.insert('foo e', ' ')
1710
- @ds.insert(' ', 'bar')
1711
- @ds.insert('foo f', 'baz')
1712
- @ds.insert('foo baz', 'bar baz')
1713
- @ds.insert('foo boo', 'boo foo')
1714
-
1715
- @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'}]
1716
- @ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.must_equal []
1717
-
1718
- @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"}]
1719
- @ds.grep([:a, :b], %w'%baz%', :all_columns=>true).all.must_equal [{:a=>'foo baz', :b=>'bar baz'}]
1720
-
1721
- @ds.grep([:a, :b], %w'%baz% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal []
1722
- @ds.grep([:a, :b], %w'%boo% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal [{:a=>'foo boo', :b=>'boo foo'}]
1723
- end
1724
-
1725
- it "#like should return matching rows" do
1726
- @ds.insert('foo', 'bar')
1727
- @ds.filter(Sequel.expr(:a).like('foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1728
- @ds.filter(Sequel.expr(:a).like('bar')).all.must_equal []
1729
- @ds.filter(Sequel.expr(:a).like('foo', 'bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1730
- @ds.exclude(Sequel.expr(:a).like('foo')).all.must_equal []
1731
- @ds.exclude(Sequel.expr(:a).like('bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1732
- @ds.exclude(Sequel.expr(:a).like('foo', 'bar')).all.must_equal []
1733
- end
1734
-
1735
- it "#like should be case sensitive" do
1736
- @ds.insert('foo', 'bar')
1737
- @ds.filter(Sequel.expr(:a).like('Foo')).all.must_equal []
1738
- @ds.filter(Sequel.expr(:b).like('baR')).all.must_equal []
1739
- @ds.filter(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal []
1740
- @ds.exclude(Sequel.expr(:a).like('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1741
- @ds.exclude(Sequel.expr(:b).like('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1742
- @ds.exclude(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1743
- end
1744
-
1745
- it "#ilike should return matching rows, in a case insensitive manner" do
1746
- @ds.insert('foo', 'bar')
1747
- @ds.filter(Sequel.expr(:a).ilike('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1748
- @ds.filter(Sequel.expr(:a).ilike('baR')).all.must_equal []
1749
- @ds.filter(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1750
- @ds.exclude(Sequel.expr(:a).ilike('Foo')).all.must_equal []
1751
- @ds.exclude(Sequel.expr(:a).ilike('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
1752
- @ds.exclude(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal []
1753
- end
1754
-
1755
- it "#escape_like should escape any metacharacters" do
1756
- @ds.insert('foo', 'bar')
1757
- @ds.insert('foo.', 'bar..')
1758
- @ds.insert('foo\\..', 'bar\\..')
1759
- @ds.insert('foo\\_', 'bar\\%')
1760
- @ds.insert('foo_', 'bar%')
1761
- @ds.insert('foo_.', 'bar%.')
1762
- @ds.insert('foo_..', 'bar%..')
1763
- @ds.insert('[f#*?oo_]', '[bar%]')
1764
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('foo_'))).select_order_map(:a).must_equal ['foo_']
1765
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('bar%'))).select_order_map(:b).must_equal ['bar%']
1766
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('foo\\_'))).select_order_map(:a).must_equal ['foo\\_']
1767
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('bar\\%'))).select_order_map(:b).must_equal ['bar\\%']
1768
- @ds.filter(Sequel.expr(:a).like(@ds.escape_like('[f#*?oo_]'))).select_order_map(:a).must_equal ['[f#*?oo_]']
1769
- @ds.filter(Sequel.expr(:b).like(@ds.escape_like('[bar%]'))).select_order_map(:b).must_equal ['[bar%]']
1770
- @ds.filter(Sequel.expr(:b).like("#{@ds.escape_like('bar%')}_")).select_order_map(:b).must_equal ['bar%.']
1771
- @ds.filter(Sequel.expr(:b).like("#{@ds.escape_like('bar%')}%")).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1772
-
1773
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('Foo_'))).select_order_map(:a).must_equal ['foo_']
1774
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('Bar%'))).select_order_map(:b).must_equal ['bar%']
1775
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('Foo\\_'))).select_order_map(:a).must_equal ['foo\\_']
1776
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('Bar\\%'))).select_order_map(:b).must_equal ['bar\\%']
1777
- @ds.filter(Sequel.expr(:a).ilike(@ds.escape_like('[F#*?oo_]'))).select_order_map(:a).must_equal ['[f#*?oo_]']
1778
- @ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('[Bar%]'))).select_order_map(:b).must_equal ['[bar%]']
1779
- @ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}_")).select_order_map(:b).must_equal ['bar%.']
1780
- @ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}%")).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1781
-
1782
- Sequel.extension(:escaped_like)
1783
- @ds.filter(Sequel.expr(:a).escaped_like('?', 'Foo_')).select_order_map(:a).must_equal []
1784
- @ds.filter(Sequel.expr(:a).escaped_like('?', 'foo_')).select_order_map(:a).must_equal ['foo_']
1785
- @ds.filter(Sequel.expr(:b).escaped_like('?', ['bar%'])).select_order_map(:b).must_equal ['bar%']
1786
- @ds.filter(Sequel.expr(:a).escaped_like('??', ['fo', 'o\\_'])).select_order_map(:a).must_equal ['foo\\_']
1787
- @ds.filter(Sequel.expr(:b).escaped_like('?', 'bar\\%')).select_order_map(:b).must_equal ['bar\\%']
1788
- @ds.filter(Sequel.expr(:a).escaped_like('?', '[f#*?oo_]')).select_order_map(:a).must_equal ['[f#*?oo_]']
1789
- @ds.filter(Sequel.expr(:b).escaped_like('?', '[bar%]')).select_order_map(:b).must_equal ['[bar%]']
1790
- @ds.filter(Sequel.expr(:b).escaped_like('?_', 'bar%')).select_order_map(:b).must_equal ['bar%.']
1791
- @ds.filter(Sequel.expr(:b).escaped_like('?%', 'bar%')).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1792
-
1793
- @ds.filter(Sequel.expr(:a).escaped_ilike('?', 'Foo_')).select_order_map(:a).must_equal ['foo_']
1794
- @ds.filter(Sequel.expr(:a).escaped_ilike('?', 'Foo_')).select_order_map(:a).must_equal ['foo_']
1795
- @ds.filter(Sequel.expr(:b).escaped_ilike('?', ['Bar%'])).select_order_map(:b).must_equal ['bar%']
1796
- @ds.filter(Sequel.expr(:a).escaped_ilike('??', ['Fo', 'o\\_'])).select_order_map(:a).must_equal ['foo\\_']
1797
- @ds.filter(Sequel.expr(:b).escaped_ilike('?', 'Bar\\%')).select_order_map(:b).must_equal ['bar\\%']
1798
- @ds.filter(Sequel.expr(:a).escaped_ilike('?', '[F#*?oo_]')).select_order_map(:a).must_equal ['[f#*?oo_]']
1799
- @ds.filter(Sequel.expr(:b).escaped_ilike('?', '[Bar%]')).select_order_map(:b).must_equal ['[bar%]']
1800
- @ds.filter(Sequel.expr(:b).escaped_ilike('?_', 'Bar%')).select_order_map(:b).must_equal ['bar%.']
1801
- @ds.filter(Sequel.expr(:b).escaped_ilike('?%', 'Bar%')).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
1802
- end
1803
-
1804
- if DB.dataset.supports_regexp?
1805
- it "#like with regexp return matching rows" do
1806
- @ds.insert('foo', 'bar')
1807
- @ds.filter(Sequel.expr(:a).like(/fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1808
- @ds.filter(Sequel.expr(:a).like(/fo$/)).all.must_equal []
1809
- @ds.filter(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1810
- @ds.exclude(Sequel.expr(:a).like(/fo/)).all.must_equal []
1811
- @ds.exclude(Sequel.expr(:a).like(/fo$/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1812
- @ds.exclude(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal []
1813
- end
1814
-
1815
- it "#like with regexp should be case sensitive if regexp is case sensitive" do
1816
- @ds.insert('foo', 'bar')
1817
- @ds.filter(Sequel.expr(:a).like(/Fo/)).all.must_equal []
1818
- @ds.filter(Sequel.expr(:b).like(/baR/)).all.must_equal []
1819
- @ds.filter(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal []
1820
- @ds.exclude(Sequel.expr(:a).like(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1821
- @ds.exclude(Sequel.expr(:b).like(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1822
- @ds.exclude(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1823
-
1824
- @ds.filter(Sequel.expr(:a).like(/Fo/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1825
- @ds.filter(Sequel.expr(:b).like(/baR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1826
- @ds.filter(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1827
- @ds.exclude(Sequel.expr(:a).like(/Fo/i)).all.must_equal []
1828
- @ds.exclude(Sequel.expr(:b).like(/baR/i)).all.must_equal []
1829
- @ds.exclude(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal []
1830
- end
1831
-
1832
- it "#ilike with regexp should return matching rows, in a case insensitive manner" do
1833
- @ds.insert('foo', 'bar')
1834
- @ds.filter(Sequel.expr(:a).ilike(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1835
- @ds.filter(Sequel.expr(:b).ilike(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1836
- @ds.filter(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
1837
- @ds.exclude(Sequel.expr(:a).ilike(/Fo/)).all.must_equal []
1838
- @ds.exclude(Sequel.expr(:b).ilike(/baR/)).all.must_equal []
1839
- @ds.exclude(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal []
1840
- end
1841
- end
1842
-
1843
- it "should work with strings created with Sequel.join" do
1844
- @ds.insert('foo', 'bar')
1845
- @ds.get(Sequel.join([:a, "bar"])).must_equal 'foobar'
1846
- @ds.get(Sequel.join(["foo", :b], ' ')).must_equal 'foo bar'
1847
- end
1848
- end
1849
-
1850
- describe "Dataset identifier methods" do
1851
- before(:all) do
1852
- class ::String
1853
- def uprev
1854
- upcase.reverse
1855
- end
1856
- end
1857
- @db = DB
1858
- @db.create_table!(:a){Integer :ab}
1859
- @db[:a].insert(1)
1860
- end
1861
- before do
1862
- @ds = @db[:a].order(:ab)
1863
- end
1864
- after(:all) do
1865
- @db.drop_table?(:a)
1866
- end
1867
-
1868
- it "#identifier_output_method should change how identifiers are output" do
1869
- @ds.with_identifier_output_method(:upcase).first.must_equal(:AB=>1)
1870
- @ds.with_identifier_output_method(:uprev).first.must_equal(:BA=>1)
1871
- end
1872
-
1873
- it "should work with a nil identifier_output_method" do
1874
- [{:ab=>1}, {:AB=>1}].must_include(@ds.with_identifier_output_method(nil).first)
1875
- end
1876
-
1877
- it "should work when not quoting identifiers" do
1878
- @ds.with_quote_identifiers(false).first.must_equal(:ab=>1)
1879
- end
1880
- end if IDENTIFIER_MANGLING
1881
-
1882
- if DB.dataset.supports_modifying_joins?
1883
- describe "Modifying joined datasets" do
1884
- before do
1885
- @db = DB
1886
- @db.create_table!(:a){Integer :a; Integer :d}
1887
- @db.create_table!(:b){Integer :b; Integer :e}
1888
- @db.create_table!(:c){Integer :c; Integer :f}
1889
- @ds = @db.from(:a, :b).join(:c, {:c=>Sequel.identifier(:e)}, :qualify=>:symbol).where(:d=>:b, :f=>6)
1890
- @db[:a].insert(1, 2)
1891
- @db[:a].insert(3, 4)
1892
- @db[:b].insert(2, 5)
1893
- @db[:c].insert(5, 6)
1894
- @db[:b].insert(4, 7)
1895
- @db[:c].insert(7, 8)
1896
- end
1897
- after do
1898
- @db.drop_table?(:a, :b, :c)
1899
- end
1900
-
1901
- it "#update should allow updating joined datasets" do
1902
- @ds.update(:a=>10)
1903
- @ds.all.must_equal [{:c=>5, :b=>2, :a=>10, :d=>2, :e=>5, :f=>6}]
1904
- @db[:a].order(:a).all.must_equal [{:a=>3, :d=>4}, {:a=>10, :d=>2}]
1905
- @db[:b].order(:b).all.must_equal [{:b=>2, :e=>5}, {:b=>4, :e=>7}]
1906
- @db[:c].order(:c).all.must_equal [{:c=>5, :f=>6}, {:c=>7, :f=>8}]
1907
- end
1908
-
1909
- it "#delete should allow deleting from joined datasets" do
1910
- @ds.delete
1911
- @ds.all.must_equal []
1912
- @db[:a].order(:a).all.must_equal [{:a=>3, :d=>4}]
1913
- @db[:b].order(:b).all.must_equal [{:b=>2, :e=>5}, {:b=>4, :e=>7}]
1914
- @db[:c].order(:c).all.must_equal [{:c=>5, :f=>6}, {:c=>7, :f=>8}]
1915
- end
1916
- end
1917
- end
1918
-
1919
- describe "Emulated functions" do
1920
- before(:all) do
1921
- @db = DB
1922
- @db.create_table!(:a){String :a}
1923
- @ds = @db[:a]
1924
- end
1925
- after(:all) do
1926
- @db.drop_table?(:a)
1927
- end
1928
- after do
1929
- @ds.delete
1930
- end
1931
-
1932
- it "Sequel.char_length should return the length of characters in the string" do
1933
- @ds.get(Sequel.char_length(:a)).must_be_nil
1934
- @ds.insert(:a=>'foo')
1935
- @ds.get(Sequel.char_length(:a)).must_equal 3
1936
- # Check behavior with leading/trailing blanks
1937
- @ds.update(:a=>' foo22 ')
1938
- @ds.get(Sequel.char_length(:a)).must_equal 7
1939
- end
1940
-
1941
- it "Sequel.trim should return the string with spaces trimmed from both sides" do
1942
- @ds.get(Sequel.trim(:a)).must_be_nil
1943
- @ds.insert(:a=>'foo')
1944
- @ds.get(Sequel.trim(:a)).must_equal 'foo'
1945
- # Check behavior with leading/trailing blanks
1946
- @ds.update(:a=>' foo22 ')
1947
- @ds.get(Sequel.trim(:a)).must_equal 'foo22'
1948
- end
1949
- end
1950
-
1951
- describe "Dataset replace" do
1952
- before do
1953
- DB.create_table!(:items){Integer :id, :unique=>true; Integer :value}
1954
- @d = DB[:items]
1955
- end
1956
-
1957
- after do
1958
- DB.drop_table?(:items)
1959
- end
1960
-
1961
- it "should use support arrays, datasets, and multiple values" do
1962
- @d.replace([1, 2])
1963
- @d.all.must_equal [{:id=>1, :value=>2}]
1964
- @d.replace(1, 2)
1965
- @d.all.must_equal [{:id=>1, :value=>2}]
1966
- @d.replace(@d)
1967
- @d.all.must_equal [{:id=>1, :value=>2}]
1968
- end
1969
-
1970
- it "should create a record if the condition is not met" do
1971
- @d.replace(:id => 111, :value => 333)
1972
- @d.all.must_equal [{:id => 111, :value => 333}]
1973
- end
1974
-
1975
- it "should update a record if the condition is met" do
1976
- @d.insert(:id => 111)
1977
- @d.all.must_equal [{:id => 111, :value => nil}]
1978
- @d.replace(:id => 111, :value => 333)
1979
- @d.all.must_equal [{:id => 111, :value => 333}]
1980
- end
1981
- end if DB.dataset.supports_replace?