sequel 5.20.0 → 5.49.0

Sign up to get free protection for your applications and to get access to all the features.
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?