sequel 4.36.0 → 5.61.0

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