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,2297 +0,0 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
-
3
- describe "Class Table Inheritance Plugin" do
4
- before(:all) do
5
- @db = DB
6
- @db.instance_variable_set(:@schemas, {})
7
- @db.drop_table?(:staff, :executives, :managers, :employees)
8
- @db.create_table(:employees) do
9
- primary_key :id
10
- String :name
11
- String :kind
12
- end
13
- @db.create_table(:managers) do
14
- foreign_key :id, :employees, :primary_key=>true
15
- Integer :num_staff
16
- end
17
- @db.create_table(:executives) do
18
- foreign_key :id, :managers, :primary_key=>true
19
- Integer :num_managers
20
- end
21
- @db.create_table(:staff) do
22
- foreign_key :id, :employees, :primary_key=>true
23
- foreign_key :manager_id, :managers
24
- end
25
- end
26
- before do
27
- [:staff, :executives, :managers, :employees].each{|t| @db[t].delete}
28
- class ::Employee < Sequel::Model(@db)
29
- plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}
30
- end
31
- class ::Manager < Employee
32
- one_to_many :staff_members, :class=>:Staff
33
- end
34
- class ::Executive < Manager
35
- end
36
- class ::Ceo < Executive
37
- end
38
- class ::Staff < Employee
39
- many_to_one :manager
40
- end
41
-
42
-
43
- @i1 = @db[:employees].insert(:name=>'E', :kind=>'Employee')
44
- @i2 = @db[:employees].insert(:name=>'S', :kind=>'Staff')
45
- @i3 = @db[:employees].insert(:name=>'M', :kind=>'Manager')
46
- @db[:managers].insert(:id=>@i3, :num_staff=>7)
47
- @i4 = @db[:employees].insert(:name=>'Ex', :kind=>'Executive')
48
- @db[:managers].insert(:id=>@i4, :num_staff=>5)
49
- @db[:executives].insert(:id=>@i4, :num_managers=>6)
50
- @i5 = @db[:employees].insert(:name=>'C', :kind=>'Ceo')
51
- @db[:managers].insert(:id=>@i5, :num_staff=>2)
52
- @db[:executives].insert(:id=>@i5, :num_managers=>1)
53
- @db[:staff].insert(:id=>@i2, :manager_id=>@i4)
54
- end
55
- after do
56
- [:Ceo, :Executive, :Manager, :Staff, :Employee].each{|s| Object.send(:remove_const, s)}
57
- end
58
- after(:all) do
59
- @db.drop_table? :staff, :executives, :managers, :employees
60
- end
61
-
62
- it "should return rows as subclass instances" do
63
- Employee.order(:id).all.must_equal [
64
- Employee.load(:id=>@i1, :name=>'E', :kind=>'Employee'),
65
- Staff.load(:id=>@i2, :name=>'S', :kind=>'Staff'),
66
- Manager.load(:id=>@i3, :name=>'M', :kind=>'Manager'),
67
- Executive.load(:id=>@i4, :name=>'Ex', :kind=>'Executive'),
68
- Ceo.load(:id=>@i5, :name=>'C', :kind=>'Ceo')
69
- ]
70
- end
71
-
72
- it "should lazily load columns in subclass tables" do
73
- Employee[@i2][:manager_id].must_equal nil
74
- Employee[@i2].manager_id.must_equal @i4
75
- Employee[@i3][:num_staff].must_equal nil
76
- Employee[@i3].num_staff.must_equal 7
77
- Employee[@i4][:num_staff].must_equal nil
78
- Employee[@i4].num_staff.must_equal 5
79
- Employee[@i4][:num_managers].must_equal nil
80
- Employee[@i4].num_managers.must_equal 6
81
- Employee[@i5][:num_managers].must_equal nil
82
- Employee[@i5].num_managers.must_equal 1
83
- end
84
-
85
- it "should eagerly load columns in subclass tables when retrieving multiple objects" do
86
- a = Employee.order(:id).all
87
- a[1][:manager_id].must_equal nil
88
- a[1].manager_id.must_equal @i4
89
- a[2][:num_staff].must_equal nil
90
- a[2].num_staff.must_equal 7
91
- a[3][:num_staff].must_equal 5 # eagerly loaded by previous call
92
- a[3].num_staff.must_equal 5
93
- a[3][:num_managers].must_equal nil
94
- a[3].num_managers.must_equal 6
95
- a[4][:num_managers].must_equal 1
96
- a[4].num_managers.must_equal 1
97
- end
98
-
99
- it "should include schema for columns for tables for ancestor classes" do
100
- Employee.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name]
101
- Staff.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :manager_id, :name]
102
- Manager.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_staff]
103
- Executive.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_managers, :num_staff]
104
- Ceo.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_managers, :num_staff]
105
- end
106
-
107
- it "should include columns for tables for ancestor classes" do
108
- Employee.columns.must_equal [:id, :name, :kind]
109
- Staff.columns.must_equal [:id, :name, :kind, :manager_id]
110
- Manager.columns.must_equal [:id, :name, :kind, :num_staff]
111
- Executive.columns.must_equal [:id, :name, :kind, :num_staff, :num_managers]
112
- Ceo.columns.must_equal [:id, :name, :kind, :num_staff, :num_managers]
113
- end
114
-
115
- it "should delete rows from all tables" do
116
- e = Ceo.first
117
- i = e.id
118
- e.staff_members_dataset.destroy
119
- e.destroy
120
- @db[:executives][:id=>i].must_equal nil
121
- @db[:managers][:id=>i].must_equal nil
122
- @db[:employees][:id=>i].must_equal nil
123
- end
124
-
125
- it "should handle associations only defined in subclasses" do
126
- Employee.filter(:employees__id=>@i2).all.first.manager.id.must_equal @i4
127
- end
128
-
129
- it "should insert rows into all tables" do
130
- e = Ceo.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
131
- i = e.id
132
- @db[:employees][:id=>i].must_equal(:id=>i, :name=>'Ex2', :kind=>'Ceo')
133
- @db[:managers][:id=>i].must_equal(:id=>i, :num_staff=>9)
134
- @db[:executives][:id=>i].must_equal(:id=>i, :num_managers=>8)
135
- end
136
-
137
- it "should update rows in all tables" do
138
- Executive.first.update(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
139
- @db[:employees][:id=>@i4].must_equal(:id=>@i4, :name=>'Ex2', :kind=>'Executive')
140
- @db[:managers][:id=>@i4].must_equal(:id=>@i4, :num_staff=>9)
141
- @db[:executives][:id=>@i4].must_equal(:id=>@i4, :num_managers=>8)
142
- end
143
-
144
- it "should handle many_to_one relationships" do
145
- m = Staff.first.manager
146
- m.must_equal Manager[@i4]
147
- m.must_be_kind_of(Executive)
148
- end
149
-
150
- it "should handle eagerly loading many_to_one relationships" do
151
- Staff.limit(1).eager(:manager).all.map{|x| x.manager}.must_equal [Manager[@i4]]
152
- end
153
-
154
- it "should handle eagerly graphing many_to_one relationships" do
155
- ss = Staff.eager_graph(:manager).all
156
- ss.must_equal [Staff[@i2]]
157
- ss.map{|x| x.manager}.must_equal [Manager[@i4]]
158
- end
159
-
160
- it "should handle one_to_many relationships" do
161
- Executive.first(:name=>'Ex').staff_members.must_equal [Staff[@i2]]
162
- end
163
-
164
- it "should handle eagerly loading one_to_many relationships" do
165
- Executive.where(:name=>'Ex').eager(:staff_members).first.staff_members.must_equal [Staff[@i2]]
166
- end
167
-
168
- it "should handle eagerly graphing one_to_many relationships" do
169
- es = Executive.where(:name=>'Ex').eager_graph(:staff_members).all
170
- es.must_equal [Executive[@i4]]
171
- es.map{|x| x.staff_members}.must_equal [[Staff[@i2]]]
172
- end
173
- end
174
-
175
- describe "Many Through Many Plugin" do
176
- before(:all) do
177
- @db = DB
178
- @db.instance_variable_set(:@schemas, {})
179
- @db.drop_table?(:albums_artists, :albums, :artists)
180
- @db.create_table(:albums) do
181
- primary_key :id
182
- String :name
183
- end
184
- @db.create_table(:artists) do
185
- primary_key :id
186
- String :name
187
- end
188
- @db.create_table(:albums_artists) do
189
- foreign_key :album_id, :albums
190
- foreign_key :artist_id, :artists
191
- end
192
- end
193
- before do
194
- [:albums_artists, :albums, :artists].each{|t| @db[t].delete}
195
- class ::Album < Sequel::Model(@db)
196
- many_to_many :artists
197
- end
198
- class ::Artist < Sequel::Model(@db)
199
- plugin :many_through_many
200
- end
201
-
202
- @artist1 = Artist.create(:name=>'1')
203
- @artist2 = Artist.create(:name=>'2')
204
- @artist3 = Artist.create(:name=>'3')
205
- @artist4 = Artist.create(:name=>'4')
206
- @album1 = Album.create(:name=>'A')
207
- @album1.add_artist(@artist1)
208
- @album1.add_artist(@artist2)
209
- @album2 = Album.create(:name=>'B')
210
- @album2.add_artist(@artist3)
211
- @album2.add_artist(@artist4)
212
- @album3 = Album.create(:name=>'C')
213
- @album3.add_artist(@artist2)
214
- @album3.add_artist(@artist3)
215
- @album4 = Album.create(:name=>'D')
216
- @album4.add_artist(@artist1)
217
- @album4.add_artist(@artist4)
218
- end
219
- after do
220
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
221
- end
222
- after(:all) do
223
- @db.drop_table? :albums_artists, :albums, :artists
224
- end
225
- def around
226
- DB.transaction(:rollback=>:always){super}
227
- end
228
-
229
- def self_join(c)
230
- c.join(Sequel.as(c.table_name, :b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
231
- end
232
-
233
- it "should handle super simple case with 1 join table" do
234
- Artist.many_through_many :albums, [[:albums_artists, :artist_id, :album_id]]
235
- Artist[@artist1.id].albums.map{|x| x.name}.sort.must_equal %w'A D'
236
- Artist[@artist2.id].albums.map{|x| x.name}.sort.must_equal %w'A C'
237
- Artist[@artist3.id].albums.map{|x| x.name}.sort.must_equal %w'B C'
238
- Artist[@artist4.id].albums.map{|x| x.name}.sort.must_equal %w'B D'
239
-
240
- Artist.plugin :prepared_statements_associations
241
- Artist[@artist1.id].albums.map{|x| x.name}.sort.must_equal %w'A D'
242
- Artist[@artist2.id].albums.map{|x| x.name}.sort.must_equal %w'A C'
243
- Artist[@artist3.id].albums.map{|x| x.name}.sort.must_equal %w'B C'
244
- Artist[@artist4.id].albums.map{|x| x.name}.sort.must_equal %w'B D'
245
-
246
- Artist.filter(:id=>@artist1.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A D'
247
- Artist.filter(:id=>@artist2.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A C'
248
- Artist.filter(:id=>@artist3.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B C'
249
- Artist.filter(:id=>@artist4.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
250
-
251
- Artist.filter(:artists__id=>@artist1.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A D'
252
- Artist.filter(:artists__id=>@artist2.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A C'
253
- Artist.filter(:artists__id=>@artist3.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B C'
254
- Artist.filter(:artists__id=>@artist4.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
255
-
256
- Artist.filter(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2'
257
- Artist.filter(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'3 4'
258
- Artist.filter(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'2 3'
259
- Artist.filter(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1 4'
260
-
261
- Artist.exclude(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'3 4'
262
- Artist.exclude(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2'
263
- Artist.exclude(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 4'
264
- Artist.exclude(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3'
265
-
266
- Artist.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
267
- Artist.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
268
-
269
- Artist.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
270
- Artist.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'2'
271
-
272
- Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
273
- Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
274
-
275
- c = self_join(Artist)
276
- c.filter(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2'
277
- c.filter(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'3 4'
278
- c.filter(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'2 3'
279
- c.filter(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1 4'
280
-
281
- c.exclude(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'3 4'
282
- c.exclude(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2'
283
- c.exclude(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 4'
284
- c.exclude(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3'
285
-
286
- c.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
287
- c.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
288
-
289
- c.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
290
- c.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'2'
291
-
292
- c.filter(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
293
- c.exclude(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
294
- end
295
-
296
- it "should handle typical case with 3 join tables" do
297
- Artist.many_through_many :related_artists, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id]], :class=>Artist, :distinct=>true
298
- Artist[@artist1.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 4'
299
- Artist[@artist2.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 3'
300
- Artist[@artist3.id].related_artists.map{|x| x.name}.sort.must_equal %w'2 3 4'
301
- Artist[@artist4.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 3 4'
302
-
303
- Artist.plugin :prepared_statements_associations
304
- Artist[@artist1.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 4'
305
- Artist[@artist2.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 3'
306
- Artist[@artist3.id].related_artists.map{|x| x.name}.sort.must_equal %w'2 3 4'
307
- Artist[@artist4.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 3 4'
308
-
309
- Artist.filter(:id=>@artist1.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 4'
310
- Artist.filter(:id=>@artist2.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 3'
311
- Artist.filter(:id=>@artist3.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'2 3 4'
312
- Artist.filter(:id=>@artist4.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 3 4'
313
-
314
- Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 4'
315
- Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 3'
316
- Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'2 3 4'
317
- Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 3 4'
318
-
319
- Artist.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
320
- Artist.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
321
- Artist.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
322
- Artist.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
323
-
324
- Artist.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'3'
325
- Artist.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'4'
326
- Artist.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'1'
327
- Artist.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'2'
328
-
329
- Artist.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
330
- Artist.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w''
331
-
332
- Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
333
- Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'3'
334
-
335
- c = self_join(Artist)
336
- c.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
337
- c.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
338
- c.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
339
- c.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
340
-
341
- c.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'3'
342
- c.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'4'
343
- c.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'1'
344
- c.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'2'
345
-
346
- c.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
347
- c.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w''
348
-
349
- c.filter(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
350
- c.exclude(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'3'
351
- end
352
-
353
- it "should handle extreme case with 5 join tables" do
354
- Artist.many_through_many :related_albums, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id], [:artists, :id, :id], [:albums_artists, :artist_id, :album_id]], :class=>Album, :distinct=>true
355
- @db[:albums_artists].delete
356
- @album1.add_artist(@artist1)
357
- @album1.add_artist(@artist2)
358
- @album2.add_artist(@artist2)
359
- @album2.add_artist(@artist3)
360
- @album3.add_artist(@artist1)
361
- @album4.add_artist(@artist3)
362
- @album4.add_artist(@artist4)
363
-
364
- Artist[@artist1.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C'
365
- Artist[@artist2.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C D'
366
- Artist[@artist3.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B D'
367
- Artist[@artist4.id].related_albums.map{|x| x.name}.sort.must_equal %w'B D'
368
-
369
- Artist.plugin :prepared_statements_associations
370
- Artist[@artist1.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C'
371
- Artist[@artist2.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C D'
372
- Artist[@artist3.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B D'
373
- Artist[@artist4.id].related_albums.map{|x| x.name}.sort.must_equal %w'B D'
374
-
375
- Artist.filter(:id=>@artist1.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C'
376
- Artist.filter(:id=>@artist2.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C D'
377
- Artist.filter(:id=>@artist3.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B D'
378
- Artist.filter(:id=>@artist4.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
379
-
380
- Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C'
381
- Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C D'
382
- Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B D'
383
- Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
384
-
385
- Artist.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
386
- Artist.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
387
- Artist.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 2'
388
- Artist.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
389
-
390
- Artist.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'4'
391
- Artist.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w''
392
- Artist.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'3 4'
393
- Artist.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1'
394
-
395
- Artist.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
396
- Artist.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
397
-
398
- Artist.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
399
- Artist.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w''
400
-
401
- Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
402
- Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
403
-
404
- c = self_join(Artist)
405
- c.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
406
- c.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
407
- c.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 2'
408
- c.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
409
-
410
- c.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'4'
411
- c.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w''
412
- c.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'3 4'
413
- c.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1'
414
-
415
- c.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
416
- c.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
417
-
418
- c.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
419
- c.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w''
420
-
421
- c.filter(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
422
- c.exclude(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
423
- end
424
- end
425
-
426
- describe "Lazy Attributes plugin" do
427
- before(:all) do
428
- @db = DB
429
- @db.create_table!(:items) do
430
- primary_key :id
431
- String :name
432
- Integer :num
433
- end
434
- @db[:items].delete
435
- class ::Item < Sequel::Model(@db)
436
- plugin :lazy_attributes, :num
437
- end
438
- Item.create(:name=>'J', :num=>1)
439
- end
440
- after(:all) do
441
- @db.drop_table?(:items)
442
- Object.send(:remove_const, :Item)
443
- end
444
-
445
- it "should not include lazy attribute columns by default" do
446
- Item.first.must_equal Item.load(:id=>1, :name=>'J')
447
- end
448
-
449
- it "should load lazy attribute on access" do
450
- Item.first.num.must_equal 1
451
- end
452
-
453
- it "should typecast lazy attribute in setter" do
454
- i = Item.new
455
- i.num = '1'
456
- i.num.must_equal 1
457
- end
458
-
459
- it "should load lazy attribute for all items returned when accessing any item if using identity map " do
460
- Item.create(:name=>'K', :num=>2)
461
- a = Item.order(:name).all
462
- a.must_equal [Item.load(:id=>1, :name=>'J'), Item.load(:id=>2, :name=>'K')]
463
- a.map{|x| x[:num]}.must_equal [nil, nil]
464
- a.first.num.must_equal 1
465
- a.map{|x| x[:num]}.must_equal [1, 2]
466
- a.last.num.must_equal 2
467
- end
468
- end
469
-
470
- describe "Tactical Eager Loading Plugin" do
471
- before(:all) do
472
- @db = DB
473
- @db.instance_variable_set(:@schemas, {})
474
- @db.drop_table?(:albums_artists)
475
- @db.create_table!(:artists) do
476
- primary_key :id
477
- String :name
478
- end
479
- @db.create_table!(:albums) do
480
- primary_key :id
481
- String :name
482
- foreign_key :artist_id, :artists
483
- end
484
- end
485
- before do
486
- @db[:albums].delete
487
- @db[:artists].delete
488
- class ::Album < Sequel::Model(@db)
489
- plugin :tactical_eager_loading
490
- many_to_one :artist
491
- end
492
- class ::Artist < Sequel::Model(@db)
493
- plugin :tactical_eager_loading
494
- one_to_many :albums, :order=>:name
495
- end
496
-
497
- @artist1 = Artist.create(:name=>'1')
498
- @artist2 = Artist.create(:name=>'2')
499
- @artist3 = Artist.create(:name=>'3')
500
- @artist4 = Artist.create(:name=>'4')
501
- @album1 = Album.create(:name=>'A', :artist=>@artist1)
502
- @album2 = Album.create(:name=>'B', :artist=>@artist1)
503
- @album3 = Album.create(:name=>'C', :artist=>@artist2)
504
- @album4 = Album.create(:name=>'D', :artist=>@artist3)
505
- end
506
- after do
507
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
508
- end
509
- after(:all) do
510
- @db.drop_table? :albums, :artists
511
- end
512
-
513
- it "should eagerly load associations for all items when accessing any item" do
514
- a = Artist.order(:name).all
515
- a.map{|x| x.associations}.must_equal [{}, {}, {}, {}]
516
- a.first.albums.must_equal [@album1, @album2]
517
- a.map{|x| x.associations}.must_equal [{:albums=>[@album1, @album2]}, {:albums=>[@album3]}, {:albums=>[@album4]}, {:albums=>[]}]
518
-
519
- a = Album.order(:name).all
520
- a.map{|x| x.associations}.must_equal [{}, {}, {}, {}]
521
- a.first.artist.must_equal @artist1
522
- a.map{|x| x.associations}.must_equal [{:artist=>@artist1}, {:artist=>@artist1}, {:artist=>@artist2}, {:artist=>@artist3}]
523
- end
524
- end
525
-
526
- describe "Touch plugin" do
527
- before(:all) do
528
- @db = DB
529
- @db.drop_table? :albums_artists, :albums, :artists
530
- @db.create_table(:artists) do
531
- primary_key :id
532
- String :name
533
- DateTime :updated_at
534
- end
535
- @db.create_table(:albums) do
536
- primary_key :id
537
- String :name
538
- foreign_key :artist_id, :artists
539
- DateTime :updated_at
540
- end
541
- @db.create_join_table({:album_id=>:albums, :artist_id=>:artists}, :no_index=>true)
542
- end
543
- before do
544
- @db[:albums].delete
545
- @db[:artists].delete
546
- class ::Album < Sequel::Model(@db)
547
- end
548
- class ::Artist < Sequel::Model(@db)
549
- end
550
-
551
- @artist = Artist.create(:name=>'1')
552
- @album = Album.create(:name=>'A', :artist_id=>@artist.id)
553
- end
554
- after do
555
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
556
- end
557
- after(:all) do
558
- @db.drop_table? :albums_artists, :albums, :artists
559
- end
560
- def around
561
- DB.transaction(:rollback=>:always){super}
562
- end
563
-
564
- it "should update the timestamp column when touching the record" do
565
- Album.plugin :touch
566
- @album.updated_at.must_equal nil
567
- @album.touch
568
- @album.updated_at.to_i.must_be_close_to Time.now.to_i, 2
569
- end
570
-
571
- cspecify "should update the timestamp column for many_to_one associated records when the record is updated or destroyed", [:do, :sqlite], [:jdbc, :sqlite], [:swift] do
572
- Album.many_to_one :artist
573
- Album.plugin :touch, :associations=>:artist
574
- @artist.updated_at.must_equal nil
575
- @album.update(:name=>'B')
576
- ua = @artist.reload.updated_at
577
- if ua.is_a?(Time)
578
- ua.to_i.must_be_close_to Time.now.to_i, 60
579
- else
580
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
581
- end
582
- @artist.update(:updated_at=>nil)
583
- @album.destroy
584
- if ua.is_a?(Time)
585
- ua.to_i.must_be_close_to Time.now.to_i, 60
586
- else
587
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
588
- end
589
- end
590
-
591
- cspecify "should update the timestamp column for one_to_many associated records when the record is updated", [:do, :sqlite], [:jdbc, :sqlite], [:swift] do
592
- Artist.one_to_many :albums
593
- Artist.plugin :touch, :associations=>:albums
594
- @album.updated_at.must_equal nil
595
- @artist.update(:name=>'B')
596
- ua = @album.reload.updated_at
597
- if ua.is_a?(Time)
598
- ua.to_i.must_be_close_to Time.now.to_i, 60
599
- else
600
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
601
- end
602
- end
603
-
604
- cspecify "should update the timestamp column for many_to_many associated records when the record is updated", [:do, :sqlite], [:jdbc, :sqlite], [:swift] do
605
- Artist.many_to_many :albums
606
- Artist.plugin :touch, :associations=>:albums
607
- @artist.add_album(@album)
608
- @album.updated_at.must_equal nil
609
- @artist.update(:name=>'B')
610
- ua = @album.reload.updated_at
611
- if ua.is_a?(Time)
612
- ua.to_i.must_be_close_to Time.now.to_i, 60
613
- else
614
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
615
- end
616
- end
617
- end
618
-
619
- describe "Serialization plugin" do
620
- before do
621
- @db = DB
622
- @db.create_table!(:items) do
623
- primary_key :id
624
- String :stuff
625
- end
626
- class ::Item < Sequel::Model(@db)
627
- plugin :serialization, :marshal, :stuff
628
- end
629
- end
630
- after do
631
- @db.drop_table?(:items)
632
- Object.send(:remove_const, :Item)
633
- end
634
-
635
- it "should serialize and deserialize items as needed" do
636
- i = Item.create(:stuff=>{:a=>1})
637
- i.stuff.must_equal(:a=>1)
638
- i.stuff = [1, 2, 3]
639
- i.save
640
- Item.first.stuff.must_equal [1, 2, 3]
641
- i.update(:stuff=>Item.new)
642
- Item.first.stuff.must_equal Item.new
643
- end
644
- end
645
-
646
- describe "OptimisticLocking plugin" do
647
- before(:all) do
648
- @db = DB
649
- @db.create_table!(:people) do
650
- primary_key :id
651
- String :name
652
- Integer :lock_version, :default=>0, :null=>false
653
- end
654
- class ::Person < Sequel::Model(@db)
655
- plugin :optimistic_locking
656
- end
657
- end
658
- before do
659
- @db[:people].delete
660
- @p = Person.create(:name=>'John')
661
- end
662
- after(:all) do
663
- @db.drop_table?(:people)
664
- Object.send(:remove_const, :Person)
665
- end
666
-
667
- it "should raise an error when updating a stale record" do
668
- p1 = Person[@p.id]
669
- p2 = Person[@p.id]
670
- p1.update(:name=>'Jim')
671
- proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
672
- end
673
-
674
- it "should raise an error when destroying a stale record" do
675
- p1 = Person[@p.id]
676
- p2 = Person[@p.id]
677
- p1.update(:name=>'Jim')
678
- proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
679
- end
680
-
681
- it "should not raise an error when updating the same record twice" do
682
- p1 = Person[@p.id]
683
- p1.update(:name=>'Jim')
684
- p1.update(:name=>'Bob')
685
- end
686
- end
687
-
688
- describe "Composition plugin" do
689
- before do
690
- @db = DB
691
- @db.create_table!(:events) do
692
- primary_key :id
693
- Integer :year
694
- Integer :month
695
- Integer :day
696
- end
697
- class ::Event < Sequel::Model(@db)
698
- plugin :composition
699
- composition :date, :composer=>proc{Date.new(year, month, day) if year && month && day}, :decomposer=>(proc do
700
- if date
701
- self.year = date.year
702
- self.month = date.month
703
- self.day = date.day
704
- else
705
- self.year, self.month, self.day = nil
706
- end
707
- end)
708
- composition :date, :mapping=>[:year, :month, :day]
709
- end
710
- @e1 = Event.create(:year=>2010, :month=>2, :day=>15)
711
- @e2 = Event.create(:year=>nil)
712
- end
713
- after do
714
- @db.drop_table?(:events)
715
- Object.send(:remove_const, :Event)
716
- end
717
-
718
- it "should return a composed object if the underlying columns have a value" do
719
- @e1.date.must_equal Date.civil(2010, 2, 15)
720
- @e2.date.must_equal nil
721
- end
722
-
723
- it "should decompose the object when saving the record" do
724
- @e1.date = Date.civil(2009, 1, 2)
725
- @e1.save
726
- @e1.year.must_equal 2009
727
- @e1.month.must_equal 1
728
- @e1.day.must_equal 2
729
- end
730
-
731
- it "should save all columns when saving changes" do
732
- @e2.date = Date.civil(2009, 10, 2)
733
- @e2.save_changes
734
- @e2.reload
735
- @e2.year.must_equal 2009
736
- @e2.month.must_equal 10
737
- @e2.day.must_equal 2
738
- end
739
- end
740
-
741
- describe "RcteTree Plugin" do
742
- RcteTreePluginSpecs = shared_description do
743
- it "should load all standard (not-CTE) methods correctly" do
744
- @a.children.must_equal [@aa, @ab]
745
- @b.children.must_equal [@ba, @bb]
746
- @aa.children.must_equal [@aaa, @aab]
747
- @ab.children.must_equal [@aba, @abb]
748
- @ba.children.must_equal []
749
- @bb.children.must_equal []
750
- @aaa.children.must_equal [@aaaa, @aaab]
751
- @aab.children.must_equal []
752
- @aba.children.must_equal []
753
- @abb.children.must_equal []
754
- @aaaa.children.must_equal [@aaaaa]
755
- @aaab.children.must_equal []
756
- @aaaaa.children.must_equal []
757
-
758
- @a.parent.must_equal nil
759
- @b.parent.must_equal nil
760
- @aa.parent.must_equal @a
761
- @ab.parent.must_equal @a
762
- @ba.parent.must_equal @b
763
- @bb.parent.must_equal @b
764
- @aaa.parent.must_equal @aa
765
- @aab.parent.must_equal @aa
766
- @aba.parent.must_equal @ab
767
- @abb.parent.must_equal @ab
768
- @aaaa.parent.must_equal @aaa
769
- @aaab.parent.must_equal @aaa
770
- @aaaaa.parent.must_equal @aaaa
771
- end
772
-
773
- it "should load all ancestors and descendants lazily for a given instance" do
774
- @a.descendants.must_equal [@aa, @aaa, @aaaa, @aaaaa, @aaab, @aab, @ab, @aba, @abb]
775
- @b.descendants.must_equal [@ba, @bb]
776
- @aa.descendants.must_equal [@aaa, @aaaa, @aaaaa, @aaab, @aab]
777
- @ab.descendants.must_equal [@aba, @abb]
778
- @ba.descendants.must_equal []
779
- @bb.descendants.must_equal []
780
- @aaa.descendants.must_equal [@aaaa, @aaaaa, @aaab]
781
- @aab.descendants.must_equal []
782
- @aba.descendants.must_equal []
783
- @abb.descendants.must_equal []
784
- @aaaa.descendants.must_equal [@aaaaa]
785
- @aaab.descendants.must_equal []
786
- @aaaaa.descendants.must_equal []
787
-
788
- @a.ancestors.must_equal []
789
- @b.ancestors.must_equal []
790
- @aa.ancestors.must_equal [@a]
791
- @ab.ancestors.must_equal [@a]
792
- @ba.ancestors.must_equal [@b]
793
- @bb.ancestors.must_equal [@b]
794
- @aaa.ancestors.must_equal [@a, @aa]
795
- @aab.ancestors.must_equal [@a, @aa]
796
- @aba.ancestors.must_equal [@a, @ab]
797
- @abb.ancestors.must_equal [@a, @ab]
798
- @aaaa.ancestors.must_equal [@a, @aa, @aaa]
799
- @aaab.ancestors.must_equal [@a, @aa, @aaa]
800
- @aaaaa.ancestors.must_equal [@a, @aa, @aaa, @aaaa]
801
- end
802
-
803
- it "should eagerly load all ancestors and descendants for a dataset" do
804
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:ancestors, :descendants).all
805
- nodes.must_equal [@a, @aaa, @b]
806
- nodes[0].descendants.must_equal [@aa, @aaa, @aaaa, @aaaaa, @aaab, @aab, @ab, @aba, @abb]
807
- nodes[1].descendants.must_equal [@aaaa, @aaaaa, @aaab]
808
- nodes[2].descendants.must_equal [@ba, @bb]
809
- nodes[0].ancestors.must_equal []
810
- nodes[1].ancestors.must_equal [@a, @aa]
811
- nodes[2].ancestors.must_equal []
812
- end
813
-
814
- it "should eagerly load descendants to a given level" do
815
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
816
- nodes.must_equal [@a, @aaa, @b]
817
- nodes[0].descendants.must_equal [@aa, @ab]
818
- nodes[1].descendants.must_equal [@aaaa, @aaab]
819
- nodes[2].descendants.must_equal [@ba, @bb]
820
-
821
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
822
- nodes.must_equal [@a, @aaa, @b]
823
- nodes[0].descendants.must_equal [@aa, @aaa, @aab, @ab, @aba, @abb]
824
- nodes[1].descendants.must_equal [@aaaa, @aaaaa, @aaab]
825
- nodes[2].descendants.must_equal [@ba, @bb]
826
- end
827
-
828
- it "should populate all :children associations when eagerly loading descendants for a dataset" do
829
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants).all
830
- nodes[0].associations[:children].must_equal [@aa, @ab]
831
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
832
- nodes[2].associations[:children].must_equal [@ba, @bb]
833
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
834
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
835
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
836
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
837
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[]], []]
838
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children]}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
839
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children].map{|c4| c4.associations[:children]}}}}.must_equal [[[[[]], []], []], [[], []]]
840
- end
841
-
842
- it "should not populate :children associations for final level when loading descendants to a given level" do
843
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
844
- nodes[0].associations[:children].must_equal [@aa, @ab]
845
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
846
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
847
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
848
- nodes[2].associations[:children].must_equal [@ba, @bb]
849
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
850
-
851
- nodes[0].associations[:children].map{|c1| c1.children}.must_equal [[@aaa, @aab], [@aba, @abb]]
852
- nodes[1].associations[:children].map{|c1| c1.children}.must_equal [[@aaaaa], []]
853
- nodes[2].associations[:children].map{|c1| c1.children}.must_equal [[], []]
854
-
855
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
856
- nodes[0].associations[:children].must_equal [@aa, @ab]
857
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
858
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], nil], [nil, nil]]
859
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| (cc2 = c2.associations[:children]) ? cc2.map{|c3| c3.associations[:children]} : nil}}.must_equal [[[[@aaaaa], []], nil], [nil, nil]]
860
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| (cc2 = c2.associations[:children]) ? cc2.map{|c3| (cc3 = c3.associations[:children]) ? cc3.map{|c4| c4.associations[:children]} : nil} : nil}}.must_equal [[[[nil], []], nil], [nil, nil]]
861
-
862
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
863
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
864
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[nil], []]
865
-
866
- nodes[2].associations[:children].must_equal [@ba, @bb]
867
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
868
-
869
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
870
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children.map{|c3| c3.children}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
871
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children.map{|c3| c3.children.map{|c4| c4.children}}}}.must_equal [[[[[]], []], []], [[], []]]
872
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children}}.must_equal [[[]], []]
873
- end
874
-
875
- it "should populate all :children associations when lazily loading descendants" do
876
- @a.descendants
877
- @a.associations[:children].must_equal [@aa, @ab]
878
- @a.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
879
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
880
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children]}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
881
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children].map{|c4| c4.associations[:children]}}}}.must_equal [[[[[]], []], []], [[], []]]
882
-
883
- @b.descendants
884
- @b.associations[:children].must_equal [@ba, @bb]
885
- @b.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
886
-
887
- @aaa.descendants
888
- @aaa.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
889
- @aaa.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[]], []]
890
- end
891
-
892
- it "should populate all :parent associations when eagerly loading ancestors for a dataset" do
893
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @ba.pk, @aaa.pk, @aaaaa.pk]).order(:name).eager(:ancestors).all
894
- nodes[0].associations.fetch(:parent, 1).must_equal nil
895
- nodes[1].associations[:parent].must_equal @aa
896
- nodes[1].associations[:parent].associations[:parent].must_equal @a
897
- nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_equal nil
898
- nodes[2].associations[:parent].must_equal @aaaa
899
- nodes[2].associations[:parent].associations[:parent].must_equal @aaa
900
- nodes[2].associations[:parent].associations[:parent].associations[:parent].must_equal @aa
901
- nodes[2].associations[:parent].associations[:parent].associations[:parent].associations[:parent].must_equal @a
902
- nodes[2].associations[:parent].associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_equal nil
903
- nodes[3].associations[:parent].must_equal @b
904
- nodes[3].associations[:parent].associations.fetch(:parent, 1).must_equal nil
905
- end
906
-
907
- it "should populate all :parent associations when lazily loading ancestors" do
908
- @a.reload
909
- @a.ancestors
910
- @a.associations[:parent].must_equal nil
911
-
912
- @ba.reload
913
- @ba.ancestors
914
- @ba.associations[:parent].must_equal @b
915
- @ba.associations[:parent].associations.fetch(:parent, 1).must_equal nil
916
-
917
- @ba.reload
918
- @aaaaa.ancestors
919
- @aaaaa.associations[:parent].must_equal @aaaa
920
- @aaaaa.associations[:parent].associations[:parent].must_equal @aaa
921
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].must_equal @aa
922
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].associations[:parent].must_equal @a
923
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_equal nil
924
- end
925
- end
926
-
927
- before do
928
- @nodes.each{|n| n.associations.clear}
929
- end
930
-
931
- describe "with single key" do
932
- before(:all) do
933
- @db = DB
934
- @db.create_table!(:nodes) do
935
- primary_key :id
936
- Integer :parent_id
937
- String :name
938
- end
939
- @Node = Class.new(Sequel::Model(@db[:nodes]))
940
- @Node.plugin :rcte_tree, :order=>:name
941
- @nodes = []
942
- @nodes << @a = @Node.create(:name=>'a')
943
- @nodes << @b = @Node.create(:name=>'b')
944
- @nodes << @aa = @Node.create(:name=>'aa', :parent=>@a)
945
- @nodes << @ab = @Node.create(:name=>'ab', :parent=>@a)
946
- @nodes << @ba = @Node.create(:name=>'ba', :parent=>@b)
947
- @nodes << @bb = @Node.create(:name=>'bb', :parent=>@b)
948
- @nodes << @aaa = @Node.create(:name=>'aaa', :parent=>@aa)
949
- @nodes << @aab = @Node.create(:name=>'aab', :parent=>@aa)
950
- @nodes << @aba = @Node.create(:name=>'aba', :parent=>@ab)
951
- @nodes << @abb = @Node.create(:name=>'abb', :parent=>@ab)
952
- @nodes << @aaaa = @Node.create(:name=>'aaaa', :parent=>@aaa)
953
- @nodes << @aaab = @Node.create(:name=>'aaab', :parent=>@aaa)
954
- @nodes << @aaaaa = @Node.create(:name=>'aaaaa', :parent=>@aaaa)
955
- end
956
- after(:all) do
957
- @db.drop_table? :nodes
958
- end
959
-
960
- include RcteTreePluginSpecs
961
-
962
- it "should work correctly if not all columns are selected" do
963
- c = Class.new(Sequel::Model(@db[:nodes]))
964
- c.plugin :rcte_tree, :order=>:name
965
- c.plugin :lazy_attributes, :name
966
- c[:name=>'aaaa'].descendants.must_equal [c.load(:parent_id=>11, :id=>13)]
967
- c[:name=>'aa'].ancestors.must_equal [c.load(:parent_id=>nil, :id=>1)]
968
- nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
969
- nodes.must_equal [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
970
- nodes[2].descendants.must_equal [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
971
- nodes[1].ancestors.must_equal [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
972
- end
973
- end
974
-
975
- describe "with composite keys" do
976
- before(:all) do
977
- @db = DB
978
- @db.create_table!(:nodes) do
979
- Integer :id
980
- Integer :id2
981
- Integer :parent_id
982
- Integer :parent_id2
983
- String :name
984
- primary_key [:id, :id2]
985
- end
986
- @Node = Class.new(Sequel::Model(@db[:nodes]))
987
- @Node.plugin :rcte_tree, :order=>:name, :key=>[:parent_id, :parent_id2]
988
- @Node.unrestrict_primary_key
989
- @nodes = []
990
- @nodes << @a = @Node.create(:id=>1, :id2=>1, :name=>'a')
991
- @nodes << @b = @Node.create(:id=>1, :id2=>2, :name=>'b')
992
- @nodes << @aa = @Node.create(:id=>2, :id2=>1, :name=>'aa', :parent=>@a)
993
- @nodes << @ab = @Node.create(:id=>2, :id2=>2, :name=>'ab', :parent=>@a)
994
- @nodes << @ba = @Node.create(:id=>3, :id2=>1, :name=>'ba', :parent=>@b)
995
- @nodes << @bb = @Node.create(:id=>3, :id2=>2, :name=>'bb', :parent=>@b)
996
- @nodes << @aaa = @Node.create(:id=>3, :id2=>3, :name=>'aaa', :parent=>@aa)
997
- @nodes << @aab = @Node.create(:id=>1, :id2=>3, :name=>'aab', :parent=>@aa)
998
- @nodes << @aba = @Node.create(:id=>2, :id2=>3, :name=>'aba', :parent=>@ab)
999
- @nodes << @abb = @Node.create(:id=>4, :id2=>1, :name=>'abb', :parent=>@ab)
1000
- @nodes << @aaaa = @Node.create(:id=>1, :id2=>4, :name=>'aaaa', :parent=>@aaa)
1001
- @nodes << @aaab = @Node.create(:id=>2, :id2=>4, :name=>'aaab', :parent=>@aaa)
1002
- @nodes << @aaaaa = @Node.create(:id=>3, :id2=>4, :name=>'aaaaa', :parent=>@aaaa)
1003
- end
1004
- after(:all) do
1005
- @db.drop_table? :nodes
1006
- end
1007
-
1008
- include RcteTreePluginSpecs
1009
- end
1010
- end if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
1011
-
1012
- describe "Instance Filters plugin" do
1013
- before(:all) do
1014
- @db = DB
1015
- @db.create_table!(:items) do
1016
- primary_key :id
1017
- String :name
1018
- Integer :cost
1019
- Integer :number
1020
- end
1021
- class ::Item < Sequel::Model(@db)
1022
- plugin :instance_filters
1023
- end
1024
- end
1025
- before do
1026
- @db[:items].delete
1027
- @i = Item.create(:name=>'J', :number=>1, :cost=>2)
1028
- @i.instance_filter(:number=>1)
1029
- @i.set(:name=>'K')
1030
- end
1031
- after(:all) do
1032
- @db.drop_table?(:items)
1033
- Object.send(:remove_const, :Item)
1034
- end
1035
-
1036
- it "should not raise an error if saving only updates one row" do
1037
- @i.save
1038
- @i.refresh.name.must_equal 'K'
1039
- end
1040
-
1041
- it "should raise error if saving doesn't update a row" do
1042
- @i.this.update(:number=>2)
1043
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1044
- end
1045
-
1046
- it "should apply all instance filters" do
1047
- @i.instance_filter{cost <= 2}
1048
- @i.this.update(:number=>2)
1049
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1050
- @i.this.update(:number=>1, :cost=>3)
1051
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1052
- @i.this.update(:cost=>2)
1053
- @i.save
1054
- @i.refresh.name.must_equal 'K'
1055
- end
1056
-
1057
- it "should clear instance filters after successful save" do
1058
- @i.save
1059
- @i.this.update(:number=>2)
1060
- @i.update(:name=>'L')
1061
- @i.refresh.name.must_equal 'L'
1062
- end
1063
-
1064
- it "should not raise an error if deleting only deletes one row" do
1065
- @i.destroy
1066
- proc{@i.refresh}.must_raise(Sequel::Error, 'Record not found')
1067
- end
1068
-
1069
- it "should raise error if destroying doesn't delete a row" do
1070
- @i.this.update(:number=>2)
1071
- proc{@i.destroy}.must_raise(Sequel::NoExistingObject)
1072
- end
1073
- end
1074
-
1075
- describe "UpdatePrimaryKey plugin" do
1076
- before(:all) do
1077
- @db = DB
1078
- @db.create_table!(:t) do
1079
- Integer :a, :primary_key=>true
1080
- Integer :b
1081
- end
1082
- @ds = @db[:t]
1083
- @c = Class.new(Sequel::Model(@ds))
1084
- @c.set_primary_key(:a)
1085
- @c.unrestrict_primary_key
1086
- @c.plugin :update_primary_key
1087
- end
1088
- before do
1089
- @ds.delete
1090
- @ds.insert(:a=>1, :b=>3)
1091
- end
1092
- after(:all) do
1093
- @db.drop_table?(:t)
1094
- end
1095
-
1096
- it "should handle regular updates" do
1097
- @c.first.update(:b=>4)
1098
- @db[:t].all.must_equal [{:a=>1, :b=>4}]
1099
- @c.first.set(:b=>5).save
1100
- @db[:t].all.must_equal [{:a=>1, :b=>5}]
1101
- @c.first.set(:b=>6).save(:columns=>:b)
1102
- @db[:t].all.must_equal [{:a=>1, :b=>6}]
1103
- end
1104
-
1105
- it "should handle updating the primary key field with another field" do
1106
- @c.first.update(:a=>2, :b=>4)
1107
- @db[:t].all.must_equal [{:a=>2, :b=>4}]
1108
- end
1109
-
1110
- it "should handle updating just the primary key field when saving changes" do
1111
- @c.first.update(:a=>2)
1112
- @db[:t].all.must_equal [{:a=>2, :b=>3}]
1113
- @c.first.set(:a=>3).save(:columns=>:a)
1114
- @db[:t].all.must_equal [{:a=>3, :b=>3}]
1115
- end
1116
-
1117
- it "should handle saving after modifying the primary key field with another field" do
1118
- @c.first.set(:a=>2, :b=>4).save
1119
- @db[:t].all.must_equal [{:a=>2, :b=>4}]
1120
- end
1121
-
1122
- it "should handle saving after modifying just the primary key field" do
1123
- @c.first.set(:a=>2).save
1124
- @db[:t].all.must_equal [{:a=>2, :b=>3}]
1125
- end
1126
-
1127
- it "should handle saving after updating the primary key" do
1128
- @c.first.update(:a=>2).update(:b=>4).set(:b=>5).save
1129
- @db[:t].all.must_equal [{:a=>2, :b=>5}]
1130
- end
1131
- end
1132
-
1133
- describe "AssociationPks plugin" do
1134
- before(:all) do
1135
- @db = DB
1136
- @db.drop_table?(:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists)
1137
- @db.create_table(:artists) do
1138
- primary_key :id
1139
- String :name
1140
- end
1141
- @db.create_table(:albums) do
1142
- primary_key :id
1143
- String :name
1144
- foreign_key :artist_id, :artists
1145
- end
1146
- @db.create_table(:tags) do
1147
- primary_key :id
1148
- String :name
1149
- end
1150
- @db.create_table(:albums_tags) do
1151
- foreign_key :album_id, :albums
1152
- foreign_key :tag_id, :tags
1153
- end
1154
- @db.create_table(:vocalists) do
1155
- String :first
1156
- String :last
1157
- primary_key [:first, :last]
1158
- foreign_key :album_id, :albums
1159
- end
1160
- @db.create_table(:albums_vocalists) do
1161
- foreign_key :album_id, :albums
1162
- String :first
1163
- String :last
1164
- foreign_key [:first, :last], :vocalists
1165
- end
1166
- @db.create_table(:instruments) do
1167
- primary_key :id
1168
- String :first
1169
- String :last
1170
- foreign_key [:first, :last], :vocalists
1171
- end
1172
- @db.create_table(:vocalists_instruments) do
1173
- String :first
1174
- String :last
1175
- foreign_key [:first, :last], :vocalists
1176
- foreign_key :instrument_id, :instruments
1177
- end
1178
- @db.create_table(:hits) do
1179
- Integer :year
1180
- Integer :week
1181
- primary_key [:year, :week]
1182
- String :first
1183
- String :last
1184
- foreign_key [:first, :last], :vocalists
1185
- end
1186
- @db.create_table(:vocalists_hits) do
1187
- String :first
1188
- String :last
1189
- foreign_key [:first, :last], :vocalists
1190
- Integer :year
1191
- Integer :week
1192
- foreign_key [:year, :week], :hits
1193
- end
1194
- class ::Artist < Sequel::Model
1195
- plugin :association_pks
1196
- one_to_many :albums, :order=>:id
1197
- end
1198
- class ::Album < Sequel::Model
1199
- plugin :association_pks
1200
- many_to_many :tags, :order=>:id
1201
- end
1202
- class ::Tag < Sequel::Model
1203
- end
1204
- class ::Vocalist < Sequel::Model
1205
- set_primary_key [:first, :last]
1206
- plugin :association_pks
1207
- end
1208
- class ::Instrument < Sequel::Model
1209
- plugin :association_pks
1210
- end
1211
- class ::Hit < Sequel::Model
1212
- set_primary_key [:year, :week]
1213
- end
1214
- end
1215
- before do
1216
- [:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists].each{|t| @db[t].delete}
1217
- @ar1 =@db[:artists].insert(:name=>'YJM')
1218
- @ar2 =@db[:artists].insert(:name=>'AS')
1219
- @al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
1220
- @al2 =@db[:albums].insert(:name=>'MO', :artist_id=>@ar1)
1221
- @al3 =@db[:albums].insert(:name=>'T', :artist_id=>@ar1)
1222
- @t1 = @db[:tags].insert(:name=>'A')
1223
- @t2 = @db[:tags].insert(:name=>'B')
1224
- @t3 = @db[:tags].insert(:name=>'C')
1225
- {@al1=>[@t1, @t2, @t3], @al2=>[@t2]}.each do |aid, tids|
1226
- tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
1227
- end
1228
- @v1 = ['F1', 'L1']
1229
- @v2 = ['F2', 'L2']
1230
- @v3 = ['F3', 'L3']
1231
- @db[:vocalists].insert(@v1 + [@al1])
1232
- @db[:vocalists].insert(@v2 + [@al1])
1233
- @db[:vocalists].insert(@v3 + [@al1])
1234
- @i1 = @db[:instruments].insert([:first, :last], @v1)
1235
- @i2 = @db[:instruments].insert([:first, :last], @v1)
1236
- @i3 = @db[:instruments].insert([:first, :last], @v1)
1237
- @h1 = [1997, 1]
1238
- @h2 = [1997, 2]
1239
- @h3 = [1997, 3]
1240
- @db[:hits].insert(@h1 + @v1)
1241
- @db[:hits].insert(@h2 + @v1)
1242
- @db[:hits].insert(@h3 + @v1)
1243
- {@al1=>[@v1, @v2, @v3], @al2=>[@v2]}.each do |aid, vids|
1244
- vids.each{|vid| @db[:albums_vocalists].insert([aid] + vid)}
1245
- end
1246
- {@v1=>[@i1, @i2, @i3], @v2=>[@i2]}.each do |vid, iids|
1247
- iids.each{|iid| @db[:vocalists_instruments].insert(vid + [iid])}
1248
- end
1249
- {@v1=>[@h1, @h2, @h3], @v2=>[@h2]}.each do |vid, hids|
1250
- hids.each{|hid| @db[:vocalists_hits].insert(vid + hid)}
1251
- end
1252
- end
1253
- after(:all) do
1254
- @db.drop_table? :albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists
1255
- [:Artist, :Album, :Tag, :Vocalist, :Instrument, :Hit].each{|s| Object.send(:remove_const, s)}
1256
- end
1257
-
1258
- it "should return correct associated pks for one_to_many associations" do
1259
- Artist.order(:id).all.map{|a| a.album_pks}.must_equal [[@al1, @al2, @al3], []]
1260
- end
1261
-
1262
- it "should return correct associated pks for many_to_many associations" do
1263
- Album.order(:id).all.map{|a| a.tag_pks.sort}.must_equal [[@t1, @t2, @t3], [@t2], []]
1264
- end
1265
-
1266
- it "should return correct associated right-side cpks for one_to_many associations" do
1267
- Album.one_to_many :vocalists, :order=>:first
1268
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [], []]
1269
- end
1270
-
1271
- it "should return correct associated right-side cpks for many_to_many associations" do
1272
- Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first
1273
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [@v2], []]
1274
- end
1275
-
1276
- it "should return correct associated pks for left-side cpks for one_to_many associations" do
1277
- Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id
1278
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [], []]
1279
- end
1280
-
1281
- it "should return correct associated pks for left-side cpks for many_to_many associations" do
1282
- Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id
1283
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [@i2], []]
1284
- end
1285
-
1286
- it "should return correct associated right-side cpks for left-side cpks for one_to_many associations" do
1287
- Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week
1288
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [], []]
1289
- end
1290
-
1291
- it "should return correct associated right-side cpks for left-side cpks for many_to_many associations" do
1292
- Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week
1293
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [@h2], []]
1294
- end
1295
-
1296
- it "should handle :delay association option for new instances" do
1297
- album_class = Class.new(Album)
1298
- album_class.many_to_many :tags, :clone=>:tags, :delay_pks=>true, :join_table=>:albums_tags, :left_key=>:album_id
1299
- album = album_class.new(:name=>'test album')
1300
- album.tag_pks.must_equal []
1301
- album.tag_pks = [@t1, @t2]
1302
- album.tag_pks.must_equal [@t1, @t2]
1303
- album.save
1304
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal [@t1, @t2]
1305
-
1306
- album.tag_pks = []
1307
- album.tag_pks.must_equal []
1308
- album.save
1309
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal []
1310
- end
1311
-
1312
- it "should handle :delay=>:all association option for existing instances" do
1313
- album_class = Class.new(Album)
1314
- album_class.many_to_many :tags, :clone=>:tags, :delay_pks=>:always, :join_table=>:albums_tags, :left_key=>:album_id
1315
- album = album_class.with_pk!(@al1)
1316
- album.tag_pks.sort.must_equal [@t1, @t2, @t3]
1317
- album.tag_pks = [@t1, @t2]
1318
- album.tag_pks.must_equal [@t1, @t2]
1319
- album.save_changes
1320
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal [@t1, @t2]
1321
-
1322
- album.tag_pks = []
1323
- album.tag_pks.must_equal []
1324
- album.save_changes
1325
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal []
1326
- end
1327
-
1328
- it "should set associated pks correctly for a one_to_many association" do
1329
- Artist.use_transactions = true
1330
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, @ar1, @ar1]
1331
-
1332
- Artist[@ar2].album_pks = [@al1, @al3]
1333
- Artist[@ar1].album_pks.must_equal [@al2]
1334
- Album.order(:id).select_map(:artist_id).must_equal [@ar2, @ar1, @ar2]
1335
-
1336
- Artist[@ar1].album_pks = [@al1]
1337
- Artist[@ar2].album_pks.must_equal [@al3]
1338
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, nil, @ar2]
1339
-
1340
- Artist[@ar1].album_pks = [@al1, @al2]
1341
- Artist[@ar2].album_pks.must_equal [@al3]
1342
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, @ar1, @ar2]
1343
-
1344
- Artist[@ar1].album_pks = []
1345
- Album.order(:id).select_map(:artist_id).must_equal [nil, nil, @ar2]
1346
- end
1347
-
1348
- it "should set associated pks correctly for a many_to_many association" do
1349
- Artist.use_transactions = true
1350
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal [@t1, @t2, @t3]
1351
- Album[@al1].tag_pks = [@t1, @t3]
1352
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal [@t1, @t3]
1353
- Album[@al1].tag_pks = []
1354
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1355
-
1356
- @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).must_equal [@t2]
1357
- Album[@al2].tag_pks = [@t1, @t2]
1358
- @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).must_equal [@t1, @t2]
1359
- Album[@al2].tag_pks = []
1360
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1361
-
1362
- @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).must_equal []
1363
- Album[@al3].tag_pks = [@t1, @t3]
1364
- @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).must_equal [@t1, @t3]
1365
- Album[@al3].tag_pks = []
1366
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1367
- end
1368
-
1369
- it "should set associated right-side cpks correctly for a one_to_many association" do
1370
- Album.use_transactions = true
1371
- Album.one_to_many :vocalists, :order=>:first
1372
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [], []]
1373
-
1374
- Album[@al2].vocalist_pks = [@v1, @v3]
1375
- Album[@al1].vocalist_pks.must_equal [@v2]
1376
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al2, @al1, @al2]
1377
-
1378
- Album[@al1].vocalist_pks = [@v1]
1379
- Album[@al2].vocalist_pks.must_equal [@v3]
1380
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al1, nil, @al2]
1381
-
1382
- Album[@al1].vocalist_pks = [@v1, @v2]
1383
- Album[@al2].vocalist_pks.must_equal [@v3]
1384
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al1, @al1, @al2]
1385
-
1386
- Album[@al1].vocalist_pks = []
1387
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [nil, nil, @al2]
1388
- end
1389
-
1390
- it "should set associated right-side cpks correctly for a many_to_many association" do
1391
- Album.use_transactions = true
1392
- Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first
1393
-
1394
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal [@v1, @v2, @v3]
1395
- Album[@al1].vocalist_pks = [@v1, @v3]
1396
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal [@v1, @v3]
1397
- Album[@al1].vocalist_pks = []
1398
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1399
-
1400
- @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).must_equal [@v2]
1401
- Album[@al2].vocalist_pks = [@v1, @v2]
1402
- @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).must_equal [@v1, @v2]
1403
- Album[@al2].vocalist_pks = []
1404
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1405
-
1406
- @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).must_equal []
1407
- Album[@al3].vocalist_pks = [@v1, @v3]
1408
- @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).must_equal [@v1, @v3]
1409
- Album[@al3].vocalist_pks = []
1410
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1411
- end
1412
-
1413
- it "should set associated pks correctly with left-side cpks for a one_to_many association" do
1414
- Vocalist.use_transactions = true
1415
- Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id
1416
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [], []]
1417
-
1418
- Vocalist[@v2].instrument_pks = [@i1, @i3]
1419
- Vocalist[@v1].instrument_pks.must_equal [@i2]
1420
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v2, @v1, @v2]
1421
-
1422
- Vocalist[@v1].instrument_pks = [@i1]
1423
- Vocalist[@v2].instrument_pks.must_equal [@i3]
1424
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v1, [nil, nil], @v2]
1425
-
1426
- Vocalist[@v1].instrument_pks = [@i1, @i2]
1427
- Vocalist[@v2].instrument_pks.must_equal [@i3]
1428
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v1, @v1, @v2]
1429
-
1430
- Vocalist[@v1].instrument_pks = []
1431
- Instrument.order(:id).select_map([:first, :last]).must_equal [[nil, nil], [nil, nil], @v2]
1432
- end
1433
-
1434
- it "should set associated pks correctly with left-side cpks for a many_to_many association" do
1435
- Vocalist.use_transactions = true
1436
- Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id
1437
-
1438
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal [@i1, @i2, @i3]
1439
- Vocalist[@v1].instrument_pks = [@i1, @i3]
1440
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal [@i1, @i3]
1441
- Vocalist[@v1].instrument_pks = []
1442
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1443
-
1444
- @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).must_equal [@i2]
1445
- Vocalist[@v2].instrument_pks = [@i1, @i2]
1446
- @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).must_equal [@i1, @i2]
1447
- Vocalist[@v2].instrument_pks = []
1448
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1449
-
1450
- @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).must_equal []
1451
- Vocalist[@v3].instrument_pks = [@i1, @i3]
1452
- @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).must_equal [@i1, @i3]
1453
- Vocalist[@v3].instrument_pks = []
1454
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1455
- end
1456
-
1457
- it "should set associated right-side cpks correctly with left-side cpks for a one_to_many association" do
1458
- Vocalist.use_transactions = true
1459
- Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week
1460
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [], []]
1461
-
1462
- Vocalist[@v2].hit_pks = [@h1, @h3]
1463
- Vocalist[@v1].hit_pks.must_equal [@h2]
1464
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v2, @v1, @v2]
1465
-
1466
- Vocalist[@v1].hit_pks = [@h1]
1467
- Vocalist[@v2].hit_pks.must_equal [@h3]
1468
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v1, [nil, nil], @v2]
1469
-
1470
- Vocalist[@v1].hit_pks = [@h1, @h2]
1471
- Vocalist[@v2].hit_pks.must_equal [@h3]
1472
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v1, @v1, @v2]
1473
-
1474
- Vocalist[@v1].hit_pks = []
1475
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [[nil, nil], [nil, nil], @v2]
1476
- end
1477
-
1478
- it "should set associated right-side cpks correctly with left-side cpks for a many_to_many association" do
1479
- Vocalist.use_transactions = true
1480
- Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week
1481
-
1482
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal [@h1, @h2, @h3]
1483
- Vocalist[@v1].hit_pks = [@h1, @h3]
1484
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal [@h1, @h3]
1485
- Vocalist[@v1].hit_pks = []
1486
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1487
-
1488
- @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).must_equal [@h2]
1489
- Vocalist[@v2].hit_pks = [@h1, @h2]
1490
- @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).must_equal [@h1, @h2]
1491
- Vocalist[@v2].hit_pks = []
1492
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1493
-
1494
- @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).must_equal []
1495
- Vocalist[@v3].hit_pks = [@h1, @h3]
1496
- @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).must_equal [@h1, @h3]
1497
- Vocalist[@v3].hit_pks = []
1498
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1499
- end
1500
- end
1501
-
1502
- describe "List plugin without a scope" do
1503
- before(:all) do
1504
- @db = DB
1505
- @db.create_table!(:sites) do
1506
- primary_key :id
1507
- String :name
1508
- Integer :position
1509
- end
1510
-
1511
- @c = Class.new(Sequel::Model(@db[:sites]))
1512
- @c.plugin :list
1513
- end
1514
- before do
1515
- @c.dataset.delete
1516
- @c.create :name => "abc"
1517
- @c.create :name => "def"
1518
- @c.create :name => "hig"
1519
- end
1520
- after(:all) do
1521
- @db.drop_table?(:sites)
1522
- end
1523
-
1524
- it "should return rows in order of position" do
1525
- @c.map(:position).must_equal [1,2,3]
1526
- @c.map(:name).must_equal %w[ abc def hig ]
1527
- end
1528
-
1529
- it "should define prev and next" do
1530
- i = @c[:name => "abc"]
1531
- i.prev.must_equal nil
1532
- i = @c[:name => "def"]
1533
- i.prev.must_equal @c[:name => "abc"]
1534
- i.next.must_equal @c[:name => "hig"]
1535
- i = @c[:name => "hig"]
1536
- i.next.must_equal nil
1537
- end
1538
-
1539
- it "should define move_to" do
1540
- @c[:name => "def"].move_to(1)
1541
- @c.map(:name).must_equal %w[ def abc hig ]
1542
-
1543
- @c[:name => "abc"].move_to(3)
1544
- @c.map(:name).must_equal %w[ def hig abc ]
1545
-
1546
- @c[:name => "abc"].move_to(-1)
1547
- @c.map(:name).must_equal %w[ abc def hig ]
1548
- @c[:name => "abc"].move_to(10)
1549
- @c.map(:name).must_equal %w[ def hig abc ]
1550
- end
1551
-
1552
- it "should define move_to_top and move_to_bottom" do
1553
- @c[:name => "def"].move_to_top
1554
- @c.map(:name).must_equal %w[ def abc hig ]
1555
-
1556
- @c[:name => "def"].move_to_bottom
1557
- @c.map(:name).must_equal %w[ abc hig def ]
1558
- end
1559
-
1560
- it "should define move_up and move_down" do
1561
- @c[:name => "def"].move_up
1562
- @c.map(:name).must_equal %w[ def abc hig ]
1563
-
1564
- @c[:name => "abc"].move_down
1565
- @c.map(:name).must_equal %w[ def hig abc ]
1566
-
1567
- @c[:name => "abc"].move_up(2)
1568
- @c.map(:name).must_equal %w[ abc def hig ]
1569
-
1570
- @c[:name => "abc"].move_down(2)
1571
- @c.map(:name).must_equal %w[ def hig abc ]
1572
-
1573
- @c[:name => "abc"].move_up(10)
1574
- @c.map(:name).must_equal %w[ abc def hig ]
1575
- @c[:name => "abc"].move_down(10)
1576
- @c.map(:name).must_equal %w[ def hig abc ]
1577
- end
1578
-
1579
- it "should update positions on destroy" do
1580
- @c[:name => "def"].destroy
1581
- @c.select_map([:position, :name]).must_equal [[1, 'abc'], [2, 'hig']]
1582
- end
1583
- end
1584
-
1585
- describe "List plugin with a scope" do
1586
- before(:all) do
1587
- @db = DB
1588
- @db.create_table!(:pages) do
1589
- primary_key :id
1590
- String :name
1591
- Integer :pos
1592
- Integer :parent_id
1593
- end
1594
-
1595
- @c = Class.new(Sequel::Model(@db[:pages]))
1596
- @c.plugin :list, :field => :pos, :scope => :parent_id
1597
- end
1598
- before do
1599
- @c.dataset.delete
1600
- p1 = @c.create :name => "Hm", :parent_id => 0
1601
- p2 = @c.create :name => "Ps", :parent_id => p1.id
1602
- @c.create :name => "P1", :parent_id => p2.id
1603
- @c.create :name => "P2", :parent_id => p2.id
1604
- @c.create :name => "P3", :parent_id => p2.id
1605
- @c.create :name => "Au", :parent_id => p1.id
1606
- end
1607
- after(:all) do
1608
- @db.drop_table?(:pages)
1609
- end
1610
-
1611
- it "should return rows in order of position" do
1612
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1613
- end
1614
-
1615
- it "should define prev and next" do
1616
- @c[:name => "Ps"].next.name.must_equal 'Au'
1617
- @c[:name => "Au"].prev.name.must_equal 'Ps'
1618
- @c[:name => "P1"].next.name.must_equal 'P2'
1619
- @c[:name => "P2"].prev.name.must_equal 'P1'
1620
-
1621
- @c[:name => "P1"].next(2).name.must_equal 'P3'
1622
- @c[:name => "P2"].next(-1).name.must_equal 'P1'
1623
- @c[:name => "P3"].prev(2).name.must_equal 'P1'
1624
- @c[:name => "P2"].prev(-1).name.must_equal 'P3'
1625
-
1626
- @c[:name => "Ps"].prev.must_equal nil
1627
- @c[:name => "Au"].next.must_equal nil
1628
- @c[:name => "P1"].prev.must_equal nil
1629
- @c[:name => "P3"].next.must_equal nil
1630
- end
1631
-
1632
- it "should define move_to" do
1633
- @c[:name => "P2"].move_to(1)
1634
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1635
-
1636
- @c[:name => "P2"].move_to(3)
1637
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P3 P2 ]
1638
-
1639
- @c[:name => "P2"].move_to(-1)
1640
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1641
- @c[:name => "P2"].move_to(10)
1642
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P3 P2 ]
1643
- end
1644
-
1645
- it "should define move_to_top and move_to_bottom" do
1646
- @c[:name => "Au"].move_to_top
1647
- @c.map(:name).must_equal %w[ Hm Au Ps P1 P2 P3 ]
1648
-
1649
- @c[:name => "Au"].move_to_bottom
1650
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1651
- end
1652
-
1653
- it "should define move_up and move_down" do
1654
- @c[:name => "P2"].move_up
1655
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1656
-
1657
- @c[:name => "P1"].move_down
1658
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P3 P1 ]
1659
-
1660
- @c[:name => "P1"].move_up(10)
1661
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1662
- @c[:name => "P1"].move_down(10)
1663
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P3 P1 ]
1664
- end
1665
-
1666
- it "should update positions on destroy" do
1667
- @c[:name => "P2"].destroy
1668
- @c.select_order_map([:pos, :name]).must_equal [[1, "Hm"], [1, "P1"], [1, "Ps"], [2, "Au"], [2, "P3"]]
1669
- end
1670
- end
1671
-
1672
- describe "Sequel::Plugins::Tree" do
1673
- TreePluginSpecs = shared_description do
1674
- it "should instantiate" do
1675
- @Node.all.size.must_equal 12
1676
- end
1677
-
1678
- it "should find all descendants of a node" do
1679
- @Node.find(:name => 'two').descendants.map{|m| m.name}.must_equal %w'two.one two.two two.three two.two.one'
1680
- end
1681
-
1682
- it "should find all ancestors of a node" do
1683
- @Node.find(:name => "two.two.one").ancestors.map{|m| m.name}.must_equal %w'two.two two'
1684
- end
1685
-
1686
- it "should find all siblings of a node, excepting self" do
1687
- @Node.find(:name=>"two.one").siblings.map{|m| m.name}.must_equal %w'two.two two.three'
1688
- end
1689
-
1690
- it "should find all siblings of a node, including self" do
1691
- @Node.find(:name=>"two.one").self_and_siblings.map{|m| m.name}.must_equal %w'two.one two.two two.three'
1692
- end
1693
-
1694
- it "should find siblings for root nodes" do
1695
- @Node.find(:name=>'three').self_and_siblings.map{|m| m.name}.must_equal %w'one two three four five'
1696
- end
1697
-
1698
- it "should find correct root for a node" do
1699
- @Node.find(:name=>"two.two.one").root.name.must_equal 'two'
1700
- @Node.find(:name=>"three").root.name.must_equal 'three'
1701
- @Node.find(:name=>"five.one").root.name.must_equal 'five'
1702
- end
1703
-
1704
- it "iterate top-level nodes in order" do
1705
- @Node.roots_dataset.count.must_equal 5
1706
- @Node.roots.map{|p| p.name}.must_equal %w'one two three four five'
1707
- end
1708
-
1709
- it "should have children" do
1710
- @Node.find(:name=>'one').children.map{|m| m.name}.must_equal %w'one.one one.two'
1711
- end
1712
- end
1713
-
1714
- describe "with simple key" do
1715
- before(:all) do
1716
- @db = DB
1717
- @db.create_table!(:nodes) do
1718
- Integer :id, :primary_key=>true
1719
- String :name
1720
- Integer :parent_id
1721
- Integer :position
1722
- end
1723
-
1724
- @nodes = [{:id => 1, :name => 'one', :parent_id => nil, :position => 1},
1725
- {:id => 2, :name => 'two', :parent_id => nil, :position => 2},
1726
- {:id => 3, :name => 'three', :parent_id => nil, :position => 3},
1727
- {:id => 4, :name => "two.one", :parent_id => 2, :position => 1},
1728
- {:id => 5, :name => "two.two", :parent_id => 2, :position => 2},
1729
- {:id => 6, :name => "two.two.one", :parent_id => 5, :position => 1},
1730
- {:id => 7, :name => "one.two", :parent_id => 1, :position => 2},
1731
- {:id => 8, :name => "one.one", :parent_id => 1, :position => 1},
1732
- {:id => 9, :name => "five", :parent_id => nil, :position => 5},
1733
- {:id => 10, :name => "four", :parent_id => nil, :position => 4},
1734
- {:id => 11, :name => "five.one", :parent_id => 9, :position => 1},
1735
- {:id => 12, :name => "two.three", :parent_id => 2, :position => 3}]
1736
- @nodes.each{|node| @db[:nodes].insert(node)}
1737
-
1738
- @Node = Class.new(Sequel::Model(:nodes))
1739
- @Node.plugin :tree, :order=>:position
1740
- end
1741
- after(:all) do
1742
- @db.drop_table?(:nodes)
1743
- end
1744
-
1745
- include TreePluginSpecs
1746
- end
1747
-
1748
- describe "with composite key" do
1749
- before(:all) do
1750
- @db = DB
1751
- @db.create_table!(:nodes) do
1752
- Integer :id
1753
- Integer :id2
1754
- String :name
1755
- Integer :parent_id
1756
- Integer :parent_id2
1757
- Integer :position
1758
- primary_key [:id, :id2]
1759
- end
1760
-
1761
- @nodes = [{:id => 1, :id2=> 1, :name => 'one', :parent_id => nil, :parent_id2 => nil, :position => 1},
1762
- {:id => 2, :id2=> 1, :name => 'two', :parent_id => nil, :parent_id2 => nil, :position => 2},
1763
- {:id => 1, :id2=> 2, :name => 'three', :parent_id => nil, :parent_id2 => nil, :position => 3},
1764
- {:id => 2, :id2=> 2, :name => "two.one", :parent_id => 2, :parent_id2 => 1, :position => 1},
1765
- {:id => 3, :id2=> 1, :name => "two.two", :parent_id => 2, :parent_id2 => 1, :position => 2},
1766
- {:id => 3, :id2=> 2, :name => "two.two.one", :parent_id => 3, :parent_id2 => 1, :position => 1},
1767
- {:id => 3, :id2=> 3, :name => "one.two", :parent_id => 1, :parent_id2 => 1, :position => 2},
1768
- {:id => 1, :id2=> 3, :name => "one.one", :parent_id => 1, :parent_id2 => 1, :position => 1},
1769
- {:id => 2, :id2=> 3, :name => "five", :parent_id => nil, :parent_id2 => nil, :position => 5},
1770
- {:id => 4, :id2=> 1, :name => "four", :parent_id => nil, :parent_id2 => nil, :position => 4},
1771
- {:id => 1, :id2=> 4, :name => "five.one", :parent_id => 2, :parent_id2 => 3, :position => 1},
1772
- {:id => 2, :id2=> 4, :name => "two.three", :parent_id => 2, :parent_id2 => 1, :position => 3}]
1773
- @nodes.each{|node| @db[:nodes].insert(node)}
1774
-
1775
- @Node = Class.new(Sequel::Model(:nodes))
1776
- @Node.plugin :tree, :order=>:position, :key=>[:parent_id, :parent_id2]
1777
- end
1778
- after(:all) do
1779
- @db.drop_table?(:nodes)
1780
- end
1781
-
1782
- include TreePluginSpecs
1783
- end
1784
- end
1785
-
1786
- describe "Sequel::Plugins::UpdateRefresh" do
1787
- before(:all) do
1788
- @db = DB
1789
- @db.create_table!(:tests) do
1790
- primary_key :id
1791
- String :name
1792
- Integer :i
1793
- end
1794
- @c = Class.new(Sequel::Model(@db[:tests]))
1795
- @c.plugin :update_refresh
1796
- end
1797
- before do
1798
- @c.dataset.delete
1799
- @foo = @c.create(:name=>'foo', :i=>10)
1800
- end
1801
- after(:all) do
1802
- @db.drop_table?(:tests)
1803
- end
1804
-
1805
- it "should refresh when updating" do
1806
- @foo.this.update(:i=>20)
1807
- @foo.update(:name=>'bar')
1808
- @foo.name.must_equal 'bar'
1809
- @foo.i.must_equal 20
1810
- end
1811
- end
1812
-
1813
- describe "Sequel::Plugins::PreparedStatements" do
1814
- before(:all) do
1815
- @db = DB
1816
- @db.create_table!(:ps_test) do
1817
- primary_key :id
1818
- String :name
1819
- Integer :i
1820
- end
1821
- @c = Class.new(Sequel::Model(@db[:ps_test]))
1822
- @c.plugin :prepared_statements_with_pk
1823
- end
1824
- before do
1825
- @c.dataset.delete
1826
- @foo = @c.create(:name=>'foo', :i=>10)
1827
- @bar = @c.create(:name=>'bar', :i=>20)
1828
- end
1829
- after(:all) do
1830
- @db.drop_table?(:ps_test)
1831
- end
1832
-
1833
- it "should work with looking up using Model.[]" do
1834
- @c[@foo.id].must_equal @foo
1835
- @c[@bar.id].must_equal @bar
1836
- @c[0].must_equal nil
1837
- @c[nil].must_equal nil
1838
- end
1839
-
1840
- it "should work with looking up using Dataset#with_pk" do
1841
- @c.dataset.with_pk(@foo.id).must_equal @foo
1842
- @c.dataset.with_pk(@bar.id).must_equal @bar
1843
- @c.dataset.with_pk(0).must_equal nil
1844
- @c.dataset.with_pk(nil).must_equal nil
1845
-
1846
- @c.dataset.filter(:i=>0).with_pk(@foo.id).must_equal nil
1847
- @c.dataset.filter(:i=>10).with_pk(@foo.id).must_equal @foo
1848
- @c.dataset.filter(:i=>20).with_pk(@bar.id).must_equal @bar
1849
- @c.dataset.filter(:i=>10).with_pk(nil).must_equal nil
1850
- @c.dataset.filter(:name=>'foo').with_pk(@foo.id).must_equal @foo
1851
- @c.dataset.filter(:name=>'bar').with_pk(@bar.id).must_equal @bar
1852
- @c.dataset.filter(:name=>'baz').with_pk(@bar.id).must_equal nil
1853
- @c.dataset.filter(:name=>'bar').with_pk(nil).must_equal nil
1854
- end
1855
-
1856
- it "should work with Model#destroy" do
1857
- @foo.destroy
1858
- @bar.destroy
1859
- @c[@foo.id].must_equal nil
1860
- @c[@bar.id].must_equal nil
1861
- end
1862
-
1863
- it "should work with Model#update" do
1864
- @foo.update(:name=>'foo2', :i=>30)
1865
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo2', :i=>30)
1866
- @foo.update(:name=>'foo3')
1867
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>30)
1868
- @foo.update(:i=>40)
1869
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>40)
1870
- @foo.update(:i=>nil)
1871
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>nil)
1872
- end
1873
-
1874
- it "should work with Model#create" do
1875
- o = @c.create(:name=>'foo2', :i=>30)
1876
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>'foo2', :i=>30)
1877
- o = @c.create(:name=>'foo2')
1878
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>'foo2', :i=>nil)
1879
- o = @c.create(:i=>30)
1880
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>nil, :i=>30)
1881
- o = @c.create(:name=>nil, :i=>40)
1882
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>nil, :i=>40)
1883
- end
1884
- end
1885
-
1886
- describe "Sequel::Plugins::PreparedStatements with schema changes" do
1887
- before do
1888
- @db = DB
1889
- @db.create_table!(:ps_test) do
1890
- primary_key :id
1891
- String :name
1892
- end
1893
- @c = Class.new(Sequel::Model(@db[:ps_test]))
1894
- @c.many_to_one :ps_test, :key=>:id, :class=>@c
1895
- @c.one_to_many :ps_tests, :key=>:id, :class=>@c
1896
- @c.many_to_many :mps_tests, :left_key=>:id, :right_key=>:id, :class=>@c, :join_table=>:ps_test___x
1897
- @c.plugin :prepared_statements
1898
- @c.plugin :prepared_statements_associations
1899
- end
1900
- after do
1901
- @db.drop_table?(:ps_test)
1902
- end
1903
-
1904
- it "should handle added columns" do
1905
- foo = @c.create(:name=>'foo')
1906
- @c[foo.id].name.must_equal 'foo'
1907
- foo.ps_test.name.must_equal 'foo'
1908
- foo.ps_tests.map{|x| x.name}.must_equal %w'foo'
1909
- foo.mps_tests.map{|x| x.name}.must_equal %w'foo'
1910
- foo.update(:name=>'foo2')
1911
- @c[foo.id].name.must_equal 'foo2'
1912
- foo.delete
1913
- foo.exists?.must_equal false
1914
-
1915
- @db.alter_table(:ps_test){add_column :i, Integer}
1916
-
1917
- foo = @c.create(:name=>'foo')
1918
- @c[foo.id].name.must_equal 'foo'
1919
- foo.ps_test.name.must_equal 'foo'
1920
- foo.ps_tests.map{|x| x.name}.must_equal %w'foo'
1921
- foo.mps_tests.map{|x| x.name}.must_equal %w'foo'
1922
- foo.update(:name=>'foo2')
1923
- @c[foo.id].name.must_equal 'foo2'
1924
- foo.delete
1925
- foo.exists?.must_equal false
1926
- end
1927
- end
1928
-
1929
- describe "Caching plugins" do
1930
- before(:all) do
1931
- @db = DB
1932
- @db.drop_table?(:albums, :artists)
1933
- @db.create_table(:artists) do
1934
- primary_key :id
1935
- end
1936
- @db.create_table(:albums) do
1937
- primary_key :id
1938
- foreign_key :artist_id, :artists
1939
- end
1940
- @db[:artists].insert
1941
- @db[:albums].insert(:artist_id=>1)
1942
- end
1943
- before do
1944
- @Album = Class.new(Sequel::Model(@db[:albums]))
1945
- @Album.plugin :many_to_one_pk_lookup
1946
- end
1947
- after(:all) do
1948
- @db.drop_table?(:albums, :artists)
1949
- end
1950
-
1951
- CachingPluginSpecs = shared_description do
1952
- it "should work with looking up using Model.[]" do
1953
- @Artist[1].must_be_same_as(@Artist[1])
1954
- @Artist[:id=>1].must_equal @Artist[1]
1955
- @Artist[0].must_equal nil
1956
- @Artist[nil].must_equal nil
1957
- end
1958
-
1959
- it "should work with lookup up many_to_one associated objects" do
1960
- a = @Artist[1]
1961
- @Album.first.artist.must_be_same_as(a)
1962
- end
1963
- end
1964
-
1965
- describe "caching plugin" do
1966
- before do
1967
- @cache_class = Class.new(Hash) do
1968
- def set(k, v, ttl) self[k] = v end
1969
- alias get []
1970
- end
1971
- @cache = @cache_class.new
1972
-
1973
- @Artist = Class.new(Sequel::Model(@db[:artists]))
1974
- @Artist.plugin :caching, @cache
1975
- @Album.many_to_one :artist, :class=>@Artist
1976
- end
1977
-
1978
- include CachingPluginSpecs
1979
- end
1980
-
1981
- describe "static_cache plugin" do
1982
- before do
1983
- @Artist = Class.new(Sequel::Model(@db[:artists]))
1984
- @Artist.plugin :static_cache
1985
- @Album.many_to_one :artist, :class=>@Artist
1986
- end
1987
-
1988
- include CachingPluginSpecs
1989
- end
1990
- end
1991
-
1992
- describe "Sequel::Plugins::ConstraintValidations" do
1993
- before(:all) do
1994
- @db = DB
1995
- @db.extension(:constraint_validations)
1996
- @db.drop_table?(:sequel_constraint_validations)
1997
- @db.create_constraint_validations_table
1998
- @ds = @db[:cv_test]
1999
- @regexp = regexp = @db.dataset.supports_regexp?
2000
- @validation_opts = {}
2001
- opts_proc = proc{@validation_opts}
2002
- @validate_block = proc do |opts|
2003
- opts = opts_proc.call
2004
- presence :pre, opts.merge(:name=>:p)
2005
- exact_length 5, :exactlen, opts.merge(:name=>:el)
2006
- min_length 5, :minlen, opts.merge(:name=>:minl)
2007
- max_length 5, :maxlen, opts.merge(:name=>:maxl)
2008
- length_range 3..5, :lenrange, opts.merge(:name=>:lr)
2009
- if regexp
2010
- format(/^foo\d+/, :form, opts.merge(:name=>:f))
2011
- end
2012
- like 'foo%', :lik, opts.merge(:name=>:l)
2013
- ilike 'foo%', :ilik, opts.merge(:name=>:il)
2014
- includes %w'abc def', :inc, opts.merge(:name=>:i)
2015
- unique :uniq, opts.merge(:name=>:u)
2016
- max_length 6, :minlen, opts.merge(:name=>:maxl2)
2017
- operator :<, 'm', :exactlen, opts.merge(:name=>:lt)
2018
- operator :>=, 5, :num, opts.merge(:name=>:gte)
2019
- end
2020
- @valid_row = {:pre=>'a', :exactlen=>'12345', :minlen=>'12345', :maxlen=>'12345', :lenrange=>'1234', :lik=>'fooabc', :ilik=>'FooABC', :inc=>'abc', :uniq=>'u', :num=>5}
2021
- @violations = [
2022
- [:pre, [nil, '', ' ']],
2023
- [:exactlen, [nil, '', '1234', '123456', 'n1234']],
2024
- [:minlen, [nil, '', '1234']],
2025
- [:maxlen, [nil, '123456']],
2026
- [:lenrange, [nil, '', '12', '123456']],
2027
- [:lik, [nil, '', 'fo', 'fotabc', 'FOOABC']],
2028
- [:ilik, [nil, '', 'fo', 'fotabc']],
2029
- [:inc, [nil, '', 'ab', 'abcd']],
2030
- [:num, [nil, 3, 4]],
2031
- ]
2032
-
2033
- if @regexp
2034
- @valid_row[:form] = 'foo1'
2035
- @violations << [:form, [nil, '', 'foo', 'fooa']]
2036
- end
2037
- end
2038
- after(:all) do
2039
- @db.drop_constraint_validations_table
2040
- end
2041
-
2042
- ConstraintValidationsSpecs = shared_description do
2043
- cspecify "should set up constraints that work even outside the model", :mysql do
2044
- @ds.insert(@valid_row)
2045
-
2046
- # Test for unique constraint
2047
- proc{@ds.insert(@valid_row)}.must_raise(Sequel::DatabaseError, Sequel::UniqueConstraintViolation, Sequel::ConstraintViolation)
2048
-
2049
- @ds.delete
2050
- @violations.each do |col, vals|
2051
- try = @valid_row.dup
2052
- vals += ['1234567'] if col == :minlen
2053
- vals.each do |val|
2054
- next if val.nil? && @validation_opts[:allow_nil]
2055
- next if val == '' && @validation_opts[:allow_nil] && @db.database_type == :oracle
2056
- try[col] = val
2057
- proc{@ds.insert(try)}.must_raise(Sequel::DatabaseError, Sequel::CheckConstraintViolation, Sequel::ConstraintViolation)
2058
- end
2059
- end
2060
-
2061
- # Test for dropping of constraint
2062
- @db.alter_table(:cv_test){validate{drop :maxl2}}
2063
- @ds.insert(@valid_row.merge(:minlen=>'1234567'))
2064
- end
2065
-
2066
- it "should set up automatic validations inside the model" do
2067
- c = Class.new(Sequel::Model(@ds))
2068
- c.plugin :constraint_validations
2069
- c.dataset.delete
2070
- c.create(@valid_row)
2071
-
2072
- # Test for unique validation
2073
- c.new(@valid_row).wont_be :valid?
2074
-
2075
- c.dataset.delete
2076
- @violations.each do |col, vals|
2077
- try = @valid_row.dup
2078
- vals.each do |val|
2079
- next if val.nil? && @validation_opts[:allow_nil]
2080
- try[col] = val
2081
- c.new(try).wont_be :valid?
2082
- end
2083
- end
2084
- c.db.constraint_validations = nil
2085
- end
2086
- end
2087
-
2088
- describe "via create_table" do
2089
- before(:all) do
2090
- @table_block = proc do
2091
- regexp = @regexp
2092
- validate_block = @validate_block
2093
- @db.create_table!(:cv_test) do
2094
- primary_key :id
2095
- String :pre
2096
- String :exactlen
2097
- String :minlen
2098
- String :maxlen
2099
- String :lenrange
2100
- if regexp
2101
- String :form
2102
- end
2103
- String :lik
2104
- String :ilik
2105
- String :inc
2106
- String :uniq, :null=>false
2107
- Integer :num
2108
- validate(&validate_block)
2109
- end
2110
- end
2111
- end
2112
- after(:all) do
2113
- @db.drop_table?(:cv_test)
2114
- @db.drop_constraint_validations_for(:table=>:cv_test)
2115
- end
2116
-
2117
- describe "with :allow_nil=>true" do
2118
- before(:all) do
2119
- @validation_opts = {:allow_nil=>true}
2120
- @table_block.call
2121
- end
2122
- include ConstraintValidationsSpecs
2123
- end
2124
- describe "with :allow_nil=>false" do
2125
- before(:all) do
2126
- @table_block.call
2127
- end
2128
- include ConstraintValidationsSpecs
2129
- end
2130
- end
2131
-
2132
- describe "via alter_table" do
2133
- before(:all) do
2134
- @table_block = proc do
2135
- regexp = @regexp
2136
- validate_block = @validate_block
2137
- @db.create_table!(:cv_test) do
2138
- primary_key :id
2139
- String :lik
2140
- String :ilik
2141
- String :inc
2142
- String :uniq, :null=>false
2143
- end
2144
- @db.alter_table(:cv_test) do
2145
- add_column :pre, String
2146
- add_column :exactlen, String
2147
- add_column :minlen, String
2148
- add_column :maxlen, String
2149
- add_column :lenrange, String
2150
- if regexp
2151
- add_column :form, String
2152
- end
2153
- add_column :num, Integer
2154
- validate(&validate_block)
2155
- end
2156
- end
2157
- end
2158
- after(:all) do
2159
- @db.drop_table?(:cv_test)
2160
- @db.drop_constraint_validations_for(:table=>:cv_test)
2161
- end
2162
-
2163
- describe "with :allow_nil=>true" do
2164
- before(:all) do
2165
- @validation_opts = {:allow_nil=>true}
2166
- @table_block.call
2167
- end
2168
- include ConstraintValidationsSpecs
2169
- end
2170
- describe "with :allow_nil=>false" do
2171
- before(:all) do
2172
- @table_block.call
2173
- end
2174
- include ConstraintValidationsSpecs
2175
- end
2176
- end
2177
- end
2178
-
2179
- describe "date_arithmetic extension" do
2180
- asd = begin
2181
- require 'active_support/duration'
2182
- require 'active_support/inflector'
2183
- require 'active_support/core_ext/string/inflections'
2184
- true
2185
- rescue LoadError
2186
- false
2187
- end
2188
-
2189
- before(:all) do
2190
- @db = DB
2191
- @db.extension(:date_arithmetic)
2192
- if @db.database_type == :sqlite
2193
- @db.use_timestamp_timezones = false
2194
- end
2195
- @date = Date.civil(2010, 7, 12)
2196
- @dt = Time.local(2010, 7, 12)
2197
- if asd
2198
- @d0 = ActiveSupport::Duration.new(0, [[:days, 0]])
2199
- @d1 = ActiveSupport::Duration.new(1, [[:days, 1]])
2200
- @d2 = ActiveSupport::Duration.new(1, [[:years, 1], [:months, 1], [:days, 1], [:minutes, 61], [:seconds, 1]])
2201
- end
2202
- @h0 = {:days=>0}
2203
- @h1 = {:days=>1, :years=>nil, :hours=>0}
2204
- @h2 = {:years=>1, :months=>1, :days=>1, :hours=>1, :minutes=>1, :seconds=>1}
2205
- @a1 = Time.local(2010, 7, 13)
2206
- @a2 = Time.local(2011, 8, 13, 1, 1, 1)
2207
- @s1 = Time.local(2010, 7, 11)
2208
- @s2 = Time.local(2009, 6, 10, 22, 58, 59)
2209
- @check = lambda do |meth, in_date, in_interval, should|
2210
- output = @db.get(Sequel.send(meth, in_date, in_interval))
2211
- output = Time.parse(output.to_s) unless output.is_a?(Time) || output.is_a?(DateTime)
2212
- output.year.must_equal should.year
2213
- output.month.must_equal should.month
2214
- output.day.must_equal should.day
2215
- output.hour.must_equal should.hour
2216
- output.min.must_equal should.min
2217
- output.sec.must_equal should.sec
2218
- end
2219
- end
2220
- after(:all) do
2221
- if @db.database_type == :sqlite
2222
- @db.use_timestamp_timezones = true
2223
- end
2224
- end
2225
-
2226
- if asd
2227
- it "be able to use Sequel.date_add to add ActiveSupport::Duration objects to dates and datetimes" do
2228
- @check.call(:date_add, @date, @d0, @dt)
2229
- @check.call(:date_add, @date, @d1, @a1)
2230
- @check.call(:date_add, @date, @d2, @a2)
2231
-
2232
- @check.call(:date_add, @dt, @d0, @dt)
2233
- @check.call(:date_add, @dt, @d1, @a1)
2234
- @check.call(:date_add, @dt, @d2, @a2)
2235
- end
2236
-
2237
- it "be able to use Sequel.date_sub to subtract ActiveSupport::Duration objects from dates and datetimes" do
2238
- @check.call(:date_sub, @date, @d0, @dt)
2239
- @check.call(:date_sub, @date, @d1, @s1)
2240
- @check.call(:date_sub, @date, @d2, @s2)
2241
-
2242
- @check.call(:date_sub, @dt, @d0, @dt)
2243
- @check.call(:date_sub, @dt, @d1, @s1)
2244
- @check.call(:date_sub, @dt, @d2, @s2)
2245
- end
2246
- end
2247
-
2248
- it "be able to use Sequel.date_add to add interval hashes to dates and datetimes" do
2249
- @check.call(:date_add, @date, @h0, @dt)
2250
- @check.call(:date_add, @date, @h1, @a1)
2251
- @check.call(:date_add, @date, @h2, @a2)
2252
-
2253
- @check.call(:date_add, @dt, @h0, @dt)
2254
- @check.call(:date_add, @dt, @h1, @a1)
2255
- @check.call(:date_add, @dt, @h2, @a2)
2256
- end
2257
-
2258
- it "be able to use Sequel.date_sub to subtract interval hashes from dates and datetimes" do
2259
- @check.call(:date_sub, @date, @h0, @dt)
2260
- @check.call(:date_sub, @date, @h1, @s1)
2261
- @check.call(:date_sub, @date, @h2, @s2)
2262
-
2263
- @check.call(:date_sub, @dt, @h0, @dt)
2264
- @check.call(:date_sub, @dt, @h1, @s1)
2265
- @check.call(:date_sub, @dt, @h2, @s2)
2266
- end
2267
- end
2268
-
2269
- describe "string_agg extension" do
2270
- before(:all) do
2271
- @db = DB
2272
- @db.extension(:string_agg)
2273
- @db.create_table!(:string_agg_test) do
2274
- Integer :id
2275
- String :s
2276
- Integer :o
2277
- end
2278
- @db[:string_agg_test].import([:id, :s, :o], [[1, 'a', 3], [1, 'a', 3], [1, 'b', 5], [1, 'c', 4], [2, 'aa', 2], [2, 'bb', 1]])
2279
- @ds = @db[:string_agg_test].select_group(:id).order(:id)
2280
- end
2281
- after(:all) do
2282
- @db.drop_table?(:string_agg_test)
2283
- end
2284
-
2285
- cspecify "should have string_agg return aggregated concatenation", :mssql, :sqlite, :derby do
2286
- h = @ds.select_append(Sequel.string_agg(:s).as(:v)).to_hash(:id, :v)
2287
- h[1].must_match(/\A[abc],[abc],[abc],[abc]\z/)
2288
- h[2].must_match(/\A(aa|bb),(aa|bb)\z/)
2289
-
2290
- @ds.select_append(Sequel.string_agg(:s).order(:o).as(:v)).map([:id, :v]).must_equal [[1, 'a,a,c,b'], [2, 'bb,aa']]
2291
- @ds.select_append(Sequel.string_agg(:s, '-').order(:o).as(:v)).map([:id, :v]).must_equal [[1, 'a-a-c-b'], [2, 'bb-aa']]
2292
- end
2293
-
2294
- cspecify "should have string_agg return aggregated concatenation for distinct values", :mssql, :sqlite, :oracle, :db2, :derby do
2295
- @ds.select_group(:id).select_append(Sequel.string_agg(:s).order(:s).distinct.as(:v)).map([:id, :v]).must_equal [[1, 'a,b,c'], [2, 'aa,bb']]
2296
- end
2297
- end