sequel 5.29.0 → 5.34.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 (387) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -1922
  3. data/README.rdoc +1 -1
  4. data/doc/advanced_associations.rdoc +4 -4
  5. data/doc/association_basics.rdoc +3 -3
  6. data/doc/code_order.rdoc +12 -2
  7. data/doc/model_dataset_method_design.rdoc +1 -1
  8. data/doc/postgresql.rdoc +71 -0
  9. data/doc/release_notes/5.30.0.txt +20 -0
  10. data/doc/release_notes/5.31.0.txt +148 -0
  11. data/doc/release_notes/5.32.0.txt +46 -0
  12. data/doc/release_notes/5.33.0.txt +24 -0
  13. data/doc/release_notes/5.34.0.txt +40 -0
  14. data/doc/testing.rdoc +1 -1
  15. data/lib/sequel/adapters/shared/access.rb +6 -6
  16. data/lib/sequel/adapters/shared/mssql.rb +5 -5
  17. data/lib/sequel/adapters/shared/mysql.rb +9 -9
  18. data/lib/sequel/adapters/shared/oracle.rb +16 -16
  19. data/lib/sequel/adapters/shared/postgres.rb +169 -14
  20. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  21. data/lib/sequel/adapters/shared/sqlite.rb +32 -5
  22. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  23. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  24. data/lib/sequel/connection_pool/single.rb +1 -1
  25. data/lib/sequel/connection_pool/threaded.rb +2 -2
  26. data/lib/sequel/core.rb +318 -314
  27. data/lib/sequel/database/connecting.rb +1 -1
  28. data/lib/sequel/database/misc.rb +16 -10
  29. data/lib/sequel/database/query.rb +3 -1
  30. data/lib/sequel/database/schema_generator.rb +0 -1
  31. data/lib/sequel/database/schema_methods.rb +15 -16
  32. data/lib/sequel/database/transactions.rb +12 -13
  33. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  34. data/lib/sequel/dataset/query.rb +4 -3
  35. data/lib/sequel/deprecated.rb +2 -0
  36. data/lib/sequel/exceptions.rb +2 -0
  37. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  38. data/lib/sequel/extensions/connection_validator.rb +2 -2
  39. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  40. data/lib/sequel/extensions/index_caching.rb +9 -7
  41. data/lib/sequel/extensions/integer64.rb +2 -0
  42. data/lib/sequel/extensions/migration.rb +1 -1
  43. data/lib/sequel/extensions/pg_enum.rb +5 -2
  44. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  45. data/lib/sequel/extensions/pg_inet.rb +13 -5
  46. data/lib/sequel/extensions/pg_interval.rb +2 -0
  47. data/lib/sequel/extensions/pg_range.rb +2 -0
  48. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  49. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  50. data/lib/sequel/extensions/schema_dumper.rb +10 -4
  51. data/lib/sequel/extensions/server_block.rb +3 -3
  52. data/lib/sequel/model.rb +2 -0
  53. data/lib/sequel/model/associations.rb +30 -18
  54. data/lib/sequel/model/base.rb +64 -55
  55. data/lib/sequel/model/plugins.rb +3 -3
  56. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  57. data/lib/sequel/plugins/association_multi_add_remove.rb +2 -0
  58. data/lib/sequel/plugins/association_pks.rb +57 -16
  59. data/lib/sequel/plugins/association_proxies.rb +2 -0
  60. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  61. data/lib/sequel/plugins/class_table_inheritance.rb +26 -26
  62. data/lib/sequel/plugins/dirty.rb +13 -13
  63. data/lib/sequel/plugins/forbid_lazy_load.rb +214 -0
  64. data/lib/sequel/plugins/json_serializer.rb +3 -7
  65. data/lib/sequel/plugins/rcte_tree.rb +2 -2
  66. data/lib/sequel/plugins/single_table_inheritance.rb +15 -15
  67. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  68. data/lib/sequel/plugins/subclasses.rb +2 -0
  69. data/lib/sequel/timezones.rb +6 -4
  70. data/lib/sequel/version.rb +1 -1
  71. metadata +17 -368
  72. data/Rakefile +0 -151
  73. data/doc/release_notes/4.0.0.txt +0 -262
  74. data/doc/release_notes/4.1.0.txt +0 -85
  75. data/doc/release_notes/4.10.0.txt +0 -226
  76. data/doc/release_notes/4.11.0.txt +0 -147
  77. data/doc/release_notes/4.12.0.txt +0 -105
  78. data/doc/release_notes/4.13.0.txt +0 -169
  79. data/doc/release_notes/4.14.0.txt +0 -68
  80. data/doc/release_notes/4.15.0.txt +0 -56
  81. data/doc/release_notes/4.16.0.txt +0 -36
  82. data/doc/release_notes/4.17.0.txt +0 -38
  83. data/doc/release_notes/4.18.0.txt +0 -36
  84. data/doc/release_notes/4.19.0.txt +0 -45
  85. data/doc/release_notes/4.2.0.txt +0 -129
  86. data/doc/release_notes/4.20.0.txt +0 -79
  87. data/doc/release_notes/4.21.0.txt +0 -94
  88. data/doc/release_notes/4.22.0.txt +0 -72
  89. data/doc/release_notes/4.23.0.txt +0 -65
  90. data/doc/release_notes/4.24.0.txt +0 -99
  91. data/doc/release_notes/4.25.0.txt +0 -181
  92. data/doc/release_notes/4.26.0.txt +0 -44
  93. data/doc/release_notes/4.27.0.txt +0 -78
  94. data/doc/release_notes/4.28.0.txt +0 -57
  95. data/doc/release_notes/4.29.0.txt +0 -41
  96. data/doc/release_notes/4.3.0.txt +0 -40
  97. data/doc/release_notes/4.30.0.txt +0 -37
  98. data/doc/release_notes/4.31.0.txt +0 -57
  99. data/doc/release_notes/4.32.0.txt +0 -132
  100. data/doc/release_notes/4.33.0.txt +0 -88
  101. data/doc/release_notes/4.34.0.txt +0 -86
  102. data/doc/release_notes/4.35.0.txt +0 -130
  103. data/doc/release_notes/4.36.0.txt +0 -116
  104. data/doc/release_notes/4.37.0.txt +0 -50
  105. data/doc/release_notes/4.38.0.txt +0 -67
  106. data/doc/release_notes/4.39.0.txt +0 -127
  107. data/doc/release_notes/4.4.0.txt +0 -92
  108. data/doc/release_notes/4.40.0.txt +0 -179
  109. data/doc/release_notes/4.41.0.txt +0 -77
  110. data/doc/release_notes/4.42.0.txt +0 -221
  111. data/doc/release_notes/4.43.0.txt +0 -87
  112. data/doc/release_notes/4.44.0.txt +0 -125
  113. data/doc/release_notes/4.45.0.txt +0 -370
  114. data/doc/release_notes/4.46.0.txt +0 -404
  115. data/doc/release_notes/4.47.0.txt +0 -56
  116. data/doc/release_notes/4.48.0.txt +0 -293
  117. data/doc/release_notes/4.49.0.txt +0 -222
  118. data/doc/release_notes/4.5.0.txt +0 -34
  119. data/doc/release_notes/4.6.0.txt +0 -30
  120. data/doc/release_notes/4.7.0.txt +0 -103
  121. data/doc/release_notes/4.8.0.txt +0 -175
  122. data/doc/release_notes/4.9.0.txt +0 -190
  123. data/spec/adapter_spec.rb +0 -4
  124. data/spec/adapters/db2_spec.rb +0 -170
  125. data/spec/adapters/mssql_spec.rb +0 -828
  126. data/spec/adapters/mysql_spec.rb +0 -1060
  127. data/spec/adapters/oracle_spec.rb +0 -371
  128. data/spec/adapters/postgres_spec.rb +0 -4476
  129. data/spec/adapters/spec_helper.rb +0 -44
  130. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  131. data/spec/adapters/sqlite_spec.rb +0 -652
  132. data/spec/bin_spec.rb +0 -278
  133. data/spec/core/connection_pool_spec.rb +0 -1250
  134. data/spec/core/database_spec.rb +0 -2915
  135. data/spec/core/dataset_spec.rb +0 -5544
  136. data/spec/core/deprecated_spec.rb +0 -70
  137. data/spec/core/expression_filters_spec.rb +0 -1498
  138. data/spec/core/mock_adapter_spec.rb +0 -722
  139. data/spec/core/object_graph_spec.rb +0 -336
  140. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  141. data/spec/core/schema_generator_spec.rb +0 -214
  142. data/spec/core/schema_spec.rb +0 -1844
  143. data/spec/core/spec_helper.rb +0 -24
  144. data/spec/core/version_spec.rb +0 -14
  145. data/spec/core_extensions_spec.rb +0 -763
  146. data/spec/core_model_spec.rb +0 -2
  147. data/spec/core_spec.rb +0 -1
  148. data/spec/deprecation_helper.rb +0 -30
  149. data/spec/extensions/accessed_columns_spec.rb +0 -51
  150. data/spec/extensions/active_model_spec.rb +0 -99
  151. data/spec/extensions/after_initialize_spec.rb +0 -28
  152. data/spec/extensions/any_not_empty_spec.rb +0 -23
  153. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  154. data/spec/extensions/association_dependencies_spec.rb +0 -125
  155. data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
  156. data/spec/extensions/association_pks_spec.rb +0 -423
  157. data/spec/extensions/association_proxies_spec.rb +0 -100
  158. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  159. data/spec/extensions/auto_validations_spec.rb +0 -229
  160. data/spec/extensions/blacklist_security_spec.rb +0 -95
  161. data/spec/extensions/blank_spec.rb +0 -69
  162. data/spec/extensions/boolean_readers_spec.rb +0 -93
  163. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  164. data/spec/extensions/caching_spec.rb +0 -273
  165. data/spec/extensions/caller_logging_spec.rb +0 -52
  166. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  167. data/spec/extensions/column_conflicts_spec.rb +0 -75
  168. data/spec/extensions/column_select_spec.rb +0 -129
  169. data/spec/extensions/columns_introspection_spec.rb +0 -90
  170. data/spec/extensions/columns_updated_spec.rb +0 -35
  171. data/spec/extensions/composition_spec.rb +0 -248
  172. data/spec/extensions/connection_expiration_spec.rb +0 -151
  173. data/spec/extensions/connection_validator_spec.rb +0 -144
  174. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  175. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  176. data/spec/extensions/constraint_validations_spec.rb +0 -439
  177. data/spec/extensions/core_refinements_spec.rb +0 -528
  178. data/spec/extensions/csv_serializer_spec.rb +0 -183
  179. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  180. data/spec/extensions/dataset_associations_spec.rb +0 -365
  181. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  182. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  183. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  184. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  185. data/spec/extensions/defaults_setter_spec.rb +0 -150
  186. data/spec/extensions/delay_add_association_spec.rb +0 -73
  187. data/spec/extensions/dirty_spec.rb +0 -222
  188. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  189. data/spec/extensions/eager_each_spec.rb +0 -62
  190. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  191. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  192. data/spec/extensions/empty_failure_backtraces_spec.rb +0 -60
  193. data/spec/extensions/error_splitter_spec.rb +0 -18
  194. data/spec/extensions/error_sql_spec.rb +0 -20
  195. data/spec/extensions/escaped_like_spec.rb +0 -40
  196. data/spec/extensions/eval_inspect_spec.rb +0 -81
  197. data/spec/extensions/exclude_or_null_spec.rb +0 -15
  198. data/spec/extensions/finder_spec.rb +0 -260
  199. data/spec/extensions/force_encoding_spec.rb +0 -126
  200. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  201. data/spec/extensions/graph_each_spec.rb +0 -113
  202. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  203. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  204. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  205. data/spec/extensions/index_caching_spec.rb +0 -66
  206. data/spec/extensions/inflector_spec.rb +0 -183
  207. data/spec/extensions/input_transformer_spec.rb +0 -69
  208. data/spec/extensions/insert_conflict_spec.rb +0 -103
  209. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  210. data/spec/extensions/instance_filters_spec.rb +0 -79
  211. data/spec/extensions/instance_hooks_spec.rb +0 -246
  212. data/spec/extensions/integer64_spec.rb +0 -22
  213. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  214. data/spec/extensions/json_serializer_spec.rb +0 -346
  215. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  216. data/spec/extensions/list_spec.rb +0 -291
  217. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  218. data/spec/extensions/many_through_many_spec.rb +0 -2177
  219. data/spec/extensions/migration_spec.rb +0 -864
  220. data/spec/extensions/modification_detection_spec.rb +0 -93
  221. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  222. data/spec/extensions/named_timezones_spec.rb +0 -218
  223. data/spec/extensions/nested_attributes_spec.rb +0 -815
  224. data/spec/extensions/null_dataset_spec.rb +0 -85
  225. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  226. data/spec/extensions/pagination_spec.rb +0 -116
  227. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  228. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  229. data/spec/extensions/pg_array_spec.rb +0 -398
  230. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
  231. data/spec/extensions/pg_enum_spec.rb +0 -118
  232. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  233. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  234. data/spec/extensions/pg_hstore_spec.rb +0 -219
  235. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  236. data/spec/extensions/pg_inet_spec.rb +0 -72
  237. data/spec/extensions/pg_interval_spec.rb +0 -103
  238. data/spec/extensions/pg_json_ops_spec.rb +0 -356
  239. data/spec/extensions/pg_json_spec.rb +0 -451
  240. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  241. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  242. data/spec/extensions/pg_range_spec.rb +0 -600
  243. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  244. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  245. data/spec/extensions/pg_row_spec.rb +0 -363
  246. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  247. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  248. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  249. data/spec/extensions/prepared_statements_spec.rb +0 -177
  250. data/spec/extensions/pretty_table_spec.rb +0 -123
  251. data/spec/extensions/query_spec.rb +0 -94
  252. data/spec/extensions/rcte_tree_spec.rb +0 -387
  253. data/spec/extensions/round_timestamps_spec.rb +0 -39
  254. data/spec/extensions/s_spec.rb +0 -60
  255. data/spec/extensions/schema_caching_spec.rb +0 -64
  256. data/spec/extensions/schema_dumper_spec.rb +0 -870
  257. data/spec/extensions/select_remove_spec.rb +0 -38
  258. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  259. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  260. data/spec/extensions/serialization_spec.rb +0 -365
  261. data/spec/extensions/server_block_spec.rb +0 -135
  262. data/spec/extensions/server_logging_spec.rb +0 -45
  263. data/spec/extensions/sharding_spec.rb +0 -197
  264. data/spec/extensions/shared_caching_spec.rb +0 -151
  265. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  266. data/spec/extensions/singular_table_names_spec.rb +0 -22
  267. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  268. data/spec/extensions/spec_helper.rb +0 -70
  269. data/spec/extensions/split_array_nil_spec.rb +0 -24
  270. data/spec/extensions/split_values_spec.rb +0 -57
  271. data/spec/extensions/sql_comments_spec.rb +0 -33
  272. data/spec/extensions/sql_expr_spec.rb +0 -59
  273. data/spec/extensions/static_cache_cache_spec.rb +0 -35
  274. data/spec/extensions/static_cache_spec.rb +0 -471
  275. data/spec/extensions/string_agg_spec.rb +0 -90
  276. data/spec/extensions/string_date_time_spec.rb +0 -95
  277. data/spec/extensions/string_stripper_spec.rb +0 -68
  278. data/spec/extensions/subclasses_spec.rb +0 -79
  279. data/spec/extensions/subset_conditions_spec.rb +0 -38
  280. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  281. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  282. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  283. data/spec/extensions/table_select_spec.rb +0 -83
  284. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  285. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  286. data/spec/extensions/throw_failures_spec.rb +0 -74
  287. data/spec/extensions/timestamps_spec.rb +0 -209
  288. data/spec/extensions/to_dot_spec.rb +0 -153
  289. data/spec/extensions/touch_spec.rb +0 -226
  290. data/spec/extensions/tree_spec.rb +0 -334
  291. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  292. data/spec/extensions/unlimited_update_spec.rb +0 -21
  293. data/spec/extensions/update_or_create_spec.rb +0 -83
  294. data/spec/extensions/update_primary_key_spec.rb +0 -105
  295. data/spec/extensions/update_refresh_spec.rb +0 -59
  296. data/spec/extensions/uuid_spec.rb +0 -101
  297. data/spec/extensions/validate_associated_spec.rb +0 -52
  298. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  299. data/spec/extensions/validation_contexts_spec.rb +0 -31
  300. data/spec/extensions/validation_helpers_spec.rb +0 -525
  301. data/spec/extensions/whitelist_security_spec.rb +0 -157
  302. data/spec/extensions/xml_serializer_spec.rb +0 -213
  303. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  304. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  305. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  306. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  307. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  308. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  309. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  310. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  311. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  312. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  313. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  314. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  315. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  316. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  317. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  318. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  319. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  320. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  321. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  322. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  323. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  324. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  325. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  326. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  327. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  328. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  329. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  330. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  331. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  332. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  333. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  334. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  335. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  336. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  337. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  338. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  339. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  340. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  341. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  342. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  343. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  344. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  345. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  346. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  347. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  348. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  349. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  350. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  351. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  352. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  353. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  354. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  355. data/spec/guards_helper.rb +0 -59
  356. data/spec/integration/associations_test.rb +0 -2597
  357. data/spec/integration/database_test.rb +0 -113
  358. data/spec/integration/dataset_test.rb +0 -2037
  359. data/spec/integration/eager_loader_test.rb +0 -687
  360. data/spec/integration/migrator_test.rb +0 -262
  361. data/spec/integration/model_test.rb +0 -203
  362. data/spec/integration/plugin_test.rb +0 -2423
  363. data/spec/integration/prepared_statement_test.rb +0 -405
  364. data/spec/integration/schema_test.rb +0 -903
  365. data/spec/integration/spec_helper.rb +0 -71
  366. data/spec/integration/timezone_test.rb +0 -86
  367. data/spec/integration/transaction_test.rb +0 -603
  368. data/spec/integration/type_test.rb +0 -127
  369. data/spec/model/association_reflection_spec.rb +0 -803
  370. data/spec/model/associations_spec.rb +0 -4738
  371. data/spec/model/base_spec.rb +0 -875
  372. data/spec/model/class_dataset_methods_spec.rb +0 -146
  373. data/spec/model/dataset_methods_spec.rb +0 -198
  374. data/spec/model/eager_loading_spec.rb +0 -2377
  375. data/spec/model/hooks_spec.rb +0 -370
  376. data/spec/model/inflector_spec.rb +0 -26
  377. data/spec/model/model_spec.rb +0 -956
  378. data/spec/model/plugins_spec.rb +0 -429
  379. data/spec/model/record_spec.rb +0 -2118
  380. data/spec/model/spec_helper.rb +0 -46
  381. data/spec/model/validations_spec.rb +0 -220
  382. data/spec/model_no_assoc_spec.rb +0 -1
  383. data/spec/model_spec.rb +0 -1
  384. data/spec/plugin_spec.rb +0 -1
  385. data/spec/sequel_coverage.rb +0 -15
  386. data/spec/sequel_warning.rb +0 -5
  387. data/spec/spec_config.rb +0 -12
@@ -1,85 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "null_dataset extension" do
4
- before do
5
- @db = Sequel::mock(:fetch=>{:id=>1}, :autoid=>1, :numrows=>1, :columns=>[:id]).extension(:null_dataset)
6
- @ds = @db[:table].nullify
7
- @i = 0
8
- @pr = proc{|*a| @i += 1}
9
- end
10
- after do
11
- @db.sqls.must_equal [] unless @skip_check
12
- end
13
-
14
- it "should make each be a noop" do
15
- @ds.each(&@pr).must_be_same_as(@ds)
16
- @i.must_equal 0
17
- end
18
-
19
- it "should make fetch_rows be a noop" do
20
- @ds.fetch_rows("SELECT 1", &@pr).must_be_nil
21
- @i.must_equal 0
22
- end
23
-
24
- it "nullify should be a cached dataset" do
25
- ds = @db[:table]
26
- ds.nullify.object_id.must_equal(ds.nullify.object_id)
27
- end
28
-
29
- it "should make insert be a noop" do
30
- @ds.insert(1).must_be_nil
31
- end
32
-
33
- it "should make update be a noop" do
34
- @ds.update(:a=>1).must_equal 0
35
- end
36
-
37
- it "should make delete be a noop" do
38
- @ds.delete.must_equal 0
39
- end
40
-
41
- it "should make truncate be a noop" do
42
- @ds.truncate.must_be_nil
43
- end
44
-
45
- it "should make execute_* be a noop" do
46
- @ds.send(:execute_ddl,'FOO').must_be_nil
47
- @ds.send(:execute_insert,'FOO').must_be_nil
48
- @ds.send(:execute_dui,'FOO').must_be_nil
49
- @ds.send(:execute,'FOO').must_be_nil
50
- end
51
-
52
- it "should have working columns" do
53
- @skip_check = true
54
- 2.times do
55
- @ds.columns.must_equal [:id]
56
- end
57
- @db.sqls.must_equal ['SELECT * FROM table LIMIT 1']
58
- end
59
-
60
- it "should have count return 0" do
61
- @ds.count.must_equal 0
62
- end
63
-
64
- it "should have empty return true" do
65
- @ds.empty?.must_equal true
66
- end
67
-
68
- it "should make import a noop" do
69
- @ds.import([:id], [[1], [2], [3]]).must_be_nil
70
- end
71
-
72
- it "should have nullify method returned modified receiver" do
73
- @skip_check = true
74
- ds = @db[:table]
75
- ds.nullify.wont_be_same_as(ds)
76
- ds.each(&@pr)
77
- @db.sqls.must_equal ['SELECT * FROM table']
78
- @i.must_equal 1
79
- end
80
-
81
- it "should work with method chaining" do
82
- @ds.where(:a=>1).select(:b).each(&@pr)
83
- @i.must_equal 0
84
- end
85
- end
@@ -1,127 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "optimistic_locking plugin" do
4
- before do
5
- @c = Class.new(Sequel::Model(:people)) do
6
- end
7
- h = {1=>{:id=>1, :name=>'John', :lock_version=>2}}
8
- lv = @lv = "lock_version".dup
9
- @c.dataset = @c.dataset.with_numrows(proc do |sql|
10
- case sql
11
- when /UPDATE people SET (name|#{lv}) = ('Jim'|'Bob'|\d+), (?:name|#{lv}) = ('Jim'|'Bob'|\d+) WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
12
- name, nlv = $1 == 'name' ? [$2, $3] : [$3, $2]
13
- m = h[$4.to_i]
14
- if m && m[:lock_version] == $5.to_i
15
- m.merge!(:name=>name.gsub("'", ''), :lock_version=>nlv.to_i)
16
- 1
17
- else
18
- 0
19
- end
20
- when /UPDATE people SET #{lv} = (\d+) WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
21
- m = h[$2.to_i]
22
- if m && m[:lock_version] == $3.to_i
23
- m.merge!(:lock_version=>$1.to_i)
24
- 1
25
- else
26
- 0
27
- end
28
- when /DELETE FROM people WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
29
- m = h[$1.to_i]
30
- if m && m[lv.to_sym] == $2.to_i
31
- h.delete[$1.to_i]
32
- 1
33
- else
34
- 0
35
- end
36
- else
37
- puts sql
38
- end
39
- end).with_fetch(proc do |sql|
40
- m = h[1].dup
41
- v = m.delete(:lock_version)
42
- m[lv.to_sym] = v
43
- m
44
- end)
45
- @c.columns :id, :name, :lock_version
46
- @c.plugin :optimistic_locking
47
- end
48
-
49
- it "should raise an error when updating a stale record" do
50
- p1 = @c[1]
51
- p2 = @c[1]
52
- p1.update(:name=>'Jim')
53
- proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
54
- end
55
-
56
- it "should raise an error when destroying a stale record" do
57
- p1 = @c[1]
58
- p2 = @c[1]
59
- p1.update(:name=>'Jim')
60
- proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
61
- end
62
-
63
- it "should not raise an error when updating the same record twice" do
64
- p1 = @c[1]
65
- p1.update(:name=>'Jim')
66
- p1.update(:name=>'Bob')
67
- end
68
-
69
- it "should allow changing the lock column via model.lock_column=" do
70
- @lv.replace('lv')
71
- @c.columns :id, :name, :lv
72
- @c.lock_column = :lv
73
- p1 = @c[1]
74
- p2 = @c[1]
75
- p1.update(:name=>'Jim')
76
- proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
77
- end
78
-
79
- it "should allow changing the lock column via plugin option" do
80
- @lv.replace('lv')
81
- @c.columns :id, :name, :lv
82
- @c.plugin :optimistic_locking, :lock_column=>:lv
83
- p1 = @c[1]
84
- p2 = @c[1]
85
- p1.update(:name=>'Jim')
86
- proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
87
- end
88
-
89
- it "should work when subclassing" do
90
- c = Class.new(@c)
91
- p1 = c[1]
92
- p2 = c[1]
93
- p1.update(:name=>'Jim')
94
- proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
95
- end
96
-
97
- it "should work correctly if attempting to refresh and save again after a failed save" do
98
- p1 = @c[1]
99
- p2 = @c[1]
100
- p1.update(:name=>'Jim')
101
- begin
102
- p2.update(:name=>'Bob')
103
- rescue Sequel::Plugins::OptimisticLocking::Error
104
- p2.refresh
105
- @c.db.sqls
106
- p2.update(:name=>'Bob')
107
- end
108
- @c.db.sqls.must_equal ["UPDATE people SET name = 'Bob', lock_version = 4 WHERE ((id = 1) AND (lock_version = 3))"]
109
- end
110
-
111
- it "should increment the lock column when #modified! even if no columns are changed" do
112
- p1 = @c[1]
113
- p1.modified!
114
- lv = p1.lock_version
115
- p1.save_changes
116
- p1.lock_version.must_equal lv + 1
117
- end
118
-
119
- it "should not increment the lock column when the update fails" do
120
- @c.dataset = @c.dataset.with_extend{def update(_) raise end}
121
- p1 = @c[1]
122
- p1.modified!
123
- lv = p1.lock_version
124
- proc{p1.save_changes}.must_raise(RuntimeError)
125
- p1.lock_version.must_equal lv
126
- end
127
- end
@@ -1,116 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "A paginated dataset" do
4
- before do
5
- count = @count = [153]
6
- @d = Sequel.mock.dataset.extension(:pagination).with_extend{define_method(:count){count.first}}
7
- @paginated = @d.paginate(1, 20)
8
- end
9
-
10
- it "should raise an error if the dataset already has a limit" do
11
- proc{@d.limit(10).paginate(1,10)}.must_raise(Sequel::Error)
12
- proc{@paginated.paginate(2,20)}.must_raise(Sequel::Error)
13
- proc{@d.limit(10).each_page(10){|ds|}}.must_raise(Sequel::Error)
14
- proc{@d.limit(10).each_page(10)}.must_raise(Sequel::Error)
15
- end
16
-
17
- it "should set the limit and offset options correctly" do
18
- @paginated.opts[:limit].must_equal 20
19
- @paginated.opts[:offset].must_equal 0
20
- end
21
-
22
- it "should set the page count correctly" do
23
- @paginated.page_count.must_equal 8
24
- @d.paginate(1, 50).page_count.must_equal 4
25
-
26
- @count[0] = 0
27
- @d.paginate(1, 50).page_count.must_equal 1
28
- end
29
-
30
- it "should set the current page number correctly" do
31
- @paginated.current_page.must_equal 1
32
- @d.paginate(3, 50).current_page.must_equal 3
33
- end
34
-
35
- it "should return the next page number or nil if we're on the last" do
36
- @paginated.next_page.must_equal 2
37
- @d.paginate(4, 50).next_page.must_be_nil
38
- end
39
-
40
- it "should return the previous page number or nil if we're on the first" do
41
- @paginated.prev_page.must_be_nil
42
- @d.paginate(4, 50).prev_page.must_equal 3
43
- end
44
-
45
- it "should return the page range" do
46
- @paginated.page_range.must_equal(1..8)
47
- @d.paginate(4, 50).page_range.must_equal(1..4)
48
- end
49
-
50
- it "should return the record range for the current page" do
51
- @paginated.current_page_record_range.must_equal(1..20)
52
- @d.paginate(4, 50).current_page_record_range.must_equal(151..153)
53
- @d.paginate(5, 50).current_page_record_range.must_equal(0..0)
54
- end
55
-
56
- it "should return the record count for the current page" do
57
- @paginated.current_page_record_count.must_equal 20
58
- @d.paginate(3, 50).current_page_record_count.must_equal 50
59
- @d.paginate(4, 50).current_page_record_count.must_equal 3
60
- @d.paginate(5, 50).current_page_record_count.must_equal 0
61
- end
62
-
63
- it "should know if current page is last page" do
64
- @paginated.last_page?.must_equal false
65
- @d.paginate(2, 20).last_page?.must_equal false
66
- @d.paginate(5, 30).last_page?.must_equal false
67
- @d.paginate(6, 30).last_page?.must_equal true
68
-
69
- @count[0] = 0
70
- @d.paginate(1, 30).last_page?.must_equal true
71
- @d.paginate(2, 30).last_page?.must_equal false
72
- end
73
-
74
- it "should know if current page is first page" do
75
- @paginated.first_page?.must_equal true
76
- @d.paginate(1, 20).first_page?.must_equal true
77
- @d.paginate(2, 20).first_page?.must_equal false
78
- end
79
-
80
- it "should work with fixed sql" do
81
- ds = @d.clone(:sql => 'select * from blah')
82
- @count[0] = 150
83
- ds.paginate(2, 50).sql.must_equal 'SELECT * FROM (select * from blah) AS t1 LIMIT 50 OFFSET 50'
84
- end
85
- end
86
-
87
- describe "Dataset#each_page" do
88
- before do
89
- @d = Sequel.mock[:items].extension(:pagination).with_extend{def count; 153 end}
90
- end
91
-
92
- it "should raise an error if the dataset already has a limit" do
93
- proc{@d.limit(10).each_page(10){}}.must_raise(Sequel::Error)
94
- end
95
-
96
- it "should iterate over each page in the resultset as a paginated dataset" do
97
- a = []
98
- @d.each_page(50) {|p| a << p}
99
- a.map {|p| p.sql}.must_equal [
100
- 'SELECT * FROM items LIMIT 50 OFFSET 0',
101
- 'SELECT * FROM items LIMIT 50 OFFSET 50',
102
- 'SELECT * FROM items LIMIT 50 OFFSET 100',
103
- 'SELECT * FROM items LIMIT 50 OFFSET 150',
104
- ]
105
- end
106
-
107
- it "should return an enumerator if no block is given" do
108
- enum = @d.each_page(50)
109
- enum.map {|p| p.sql}.must_equal [
110
- 'SELECT * FROM items LIMIT 50 OFFSET 0',
111
- 'SELECT * FROM items LIMIT 50 OFFSET 50',
112
- 'SELECT * FROM items LIMIT 50 OFFSET 100',
113
- 'SELECT * FROM items LIMIT 50 OFFSET 150',
114
- ]
115
- end
116
- end
@@ -1,802 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe Sequel::Model, "pg_array_associations" do
4
- before do
5
- @db = Sequel.mock(:host=>'postgres', :numrows=>1)
6
- @db.extend_datasets{def quote_identifiers?; false end}
7
- class ::Artist < Sequel::Model(@db)
8
- attr_accessor :yyy
9
- columns :id, :tag_ids
10
- plugin :pg_array_associations
11
- pg_array_to_many :tags
12
- pg_array_to_many :a_tags, :clone=>:tags, :conditions=>{:name=>'A'}, :key=>:tag_ids
13
- end
14
- class ::Tag < Sequel::Model(@db)
15
- columns :id
16
- plugin :pg_array_associations
17
- many_to_pg_array :artists
18
- many_to_pg_array :a_artists, :clone=>:artists, :conditions=>{:name=>'A'}
19
- def id3
20
- id*3
21
- end
22
- end
23
- @c1 = Artist
24
- @c2 = Tag
25
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tag_ids=>Sequel.pg_array([1,2,3]))
26
- @c2.dataset = @c2.dataset.with_fetch(:id=>2)
27
- @o1 = @c1.first
28
- @o2 = @c2.first
29
- @n1 = @c1.new
30
- @n2 = @c2.new
31
- @db.sqls
32
- end
33
- after do
34
- Object.send(:remove_const, :Artist)
35
- Object.send(:remove_const, :Tag)
36
- end
37
-
38
- it "should populate :key_hash and :id_map option correctly for custom eager loaders" do
39
- khs = []
40
- pr = proc{|h| khs << [h[:key_hash], h[:id_map]]}
41
- @c1.pg_array_to_many :tags, :clone=>:tags, :eager_loader=>pr
42
- @c2.many_to_pg_array :artists, :clone=>:artists, :eager_loader=>pr
43
- @c1.eager(:tags).all
44
- @c2.eager(:artists).all
45
- khs.must_equal [[{}, nil], [{:id=>{2=>[Tag.load(:id=>2)]}}, {2=>[Tag.load(:id=>2)]}]]
46
- end
47
-
48
- it "should not issue queries if the object cannot have associated objects" do
49
- @n1.tags.must_equal []
50
- @c1.load(:tag_ids=>[]).tags.must_equal []
51
- @n2.artists.must_equal []
52
- @db.sqls.must_equal []
53
- end
54
-
55
- it "should use correct SQL when loading associations lazily" do
56
- @o1.tags.must_equal [@o2]
57
- @o2.artists.must_equal [@o1]
58
- @db.sqls.must_equal ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])"]
59
- end
60
-
61
- it "should accept :primary_key option for primary keys to use in current and associated table" do
62
- @c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel./(:id, 3)
63
- @c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3
64
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((tags.id / 3) IN (1, 2, 3))"
65
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[6]::integer[])"
66
- end
67
-
68
- it "should allowing filtering by associations" do
69
- @c1.filter(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])"
70
- @c2.filter(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))"
71
- end
72
-
73
- it "should allowing filtering by associations with :conditions" do
74
- @c1.filter(:a_tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), false)"
75
- @c2.filter(:a_artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1))))"
76
- end
77
-
78
- it "should allowing excluding by associations" do
79
- @c1.exclude(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (NOT (artists.tag_ids @> ARRAY[2]::integer[]) OR (artists.tag_ids IS NULL))"
80
- @c2.exclude(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (1, 2, 3)) OR (tags.id IS NULL))"
81
- end
82
-
83
- it "should allowing excluding by associations with :conditions" do
84
- @c1.exclude(:a_tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), false) OR (artists.tag_ids IS NULL))"
85
- @c2.exclude(:a_artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1)))) OR (tags.id IS NULL))"
86
- end
87
-
88
- it "should allowing filtering by multiple associations" do
89
- @c1.filter(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2]::integer[])"
90
- @c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (3, 4, 5))"
91
- end
92
-
93
- it "should allowing filtering by multiple associations with :conditions" do
94
- @c1.filter(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), false)"
95
- @c2.filter(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8)))))"
96
- end
97
-
98
- it "should allowing excluding by multiple associations" do
99
- @c1.exclude(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (NOT (artists.tag_ids && ARRAY[1,2]::integer[]) OR (artists.tag_ids IS NULL))"
100
- @c2.exclude(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (3, 4, 5)) OR (tags.id IS NULL))"
101
- end
102
-
103
- it "should allowing excluding by multiple associations with :conditions" do
104
- @c1.exclude(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), false) OR (artists.tag_ids IS NULL))"
105
- @c2.exclude(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8))))) OR (tags.id IS NULL))"
106
- end
107
-
108
- it "should allowing filtering/excluding associations with NULL or empty values" do
109
- @c1.filter(:tags=>@c2.new).sql.must_equal 'SELECT * FROM artists WHERE false'
110
- @c1.exclude(:tags=>@c2.new).sql.must_equal 'SELECT * FROM artists WHERE true'
111
- @c2.filter(:artists=>@c1.new).sql.must_equal 'SELECT * FROM tags WHERE false'
112
- @c2.exclude(:artists=>@c1.new).sql.must_equal 'SELECT * FROM tags WHERE true'
113
-
114
- @c2.filter(:artists=>@c1.load(:tag_ids=>[])).sql.must_equal 'SELECT * FROM tags WHERE false'
115
- @c2.exclude(:artists=>@c1.load(:tag_ids=>[])).sql.must_equal 'SELECT * FROM tags WHERE true'
116
-
117
- @c1.filter(:tags=>[@c2.new, @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"
118
- @c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.new]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (3, 4))"
119
- end
120
-
121
- it "should allowing filtering by association datasets" do
122
- @c1.filter(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), false)"
123
- @c2.filter(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (EXISTS (SELECT 1 FROM (SELECT artists.tag_ids AS key FROM artists WHERE (id = 1)) AS t1 WHERE (tags.id = any(key))))"
124
- end
125
-
126
- it "should allowing filtering by association datasets with :conditions" do
127
- @c1.filter(:a_tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), false)"
128
- @c2.filter(:a_artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1))))))"
129
- end
130
-
131
- it "should allowing excluding by association datasets" do
132
- @c1.exclude(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), false) OR (artists.tag_ids IS NULL))"
133
- @c2.exclude(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (NOT (EXISTS (SELECT 1 FROM (SELECT artists.tag_ids AS key FROM artists WHERE (id = 1)) AS t1 WHERE (tags.id = any(key)))) OR (tags.id IS NULL))"
134
- end
135
-
136
- it "should allowing excluding by association datasets with :conditions" do
137
- @c1.exclude(:a_tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), false) OR (artists.tag_ids IS NULL))"
138
- @c2.exclude(:a_artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT _smtopgaa_key_ FROM artists CROSS JOIN unnest(artists.tag_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1)))))) OR (tags.id IS NULL))"
139
- end
140
-
141
- it "filter by associations should respect key options" do
142
- @c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
143
- @c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
144
- @c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
145
-
146
- @c1.filter(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE ((artists.tag_ids)[1:2] @> ARRAY[6]::integer[])"
147
- @c2.filter(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id * 3) IN (3, 6, 9))"
148
- @c1.filter(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce(((artists.tag_ids)[1:2] && (SELECT array_agg((tags.id * 3)) FROM tags WHERE (id = 1))), false)"
149
- @c2.filter(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (EXISTS (SELECT 1 FROM (SELECT (artists.tag_ids)[1:2] AS key FROM artists WHERE (id = 1)) AS t1 WHERE ((tags.id * 3) = any(key))))"
150
- end
151
-
152
- it "should raise an error if associated model does not have a primary key, and :primary_key is not specified" do
153
- @c1.no_primary_key
154
- @c2.no_primary_key
155
- @c1.pg_array_to_many :tags, :clone=>:tags
156
- proc{@o1.tags}.must_raise(Sequel::Error)
157
- proc{@c2.many_to_pg_array :artists, :clone=>:artists}.must_raise(Sequel::Error)
158
- @db.sqls.must_equal []
159
- end
160
-
161
- it "should support a :key option" do
162
- @c1.pg_array_to_many :tags, :clone=>:tags, :key=>:tag2_ids
163
- @c2.many_to_pg_array :artists, :clone=>:artists, :key=>:tag2_ids
164
- @c1.class_eval{def tag2_ids; tag_ids.map{|x| x * 2} end}
165
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (2, 4, 6))"
166
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag2_ids @> ARRAY[2]::integer[])"
167
- end
168
-
169
- it "should support a :key_column option" do
170
- @c2.many_to_pg_array :artists, :clone=>:artists, :key_column=>Sequel.pg_array(:tag_ids)[1..2], :key=>:tag2_ids
171
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((artists.tag_ids)[1:2] @> ARRAY[2]::integer[])"
172
- end
173
-
174
- it "should support a :primary_key option" do
175
- @c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>:id2
176
- @c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id2
177
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id2 IN (1, 2, 3))"
178
- @c2.class_eval{def id2; id*2 end}
179
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[4]::integer[])"
180
- end
181
-
182
- it "should support a :conditions option" do
183
- @c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
184
- @c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
185
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((a = 1) AND (tags.id IN (1, 2, 3)))"
186
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((a = 1) AND (artists.tag_ids @> ARRAY[2]::integer[]))"
187
- end
188
-
189
- it "should support an :order option" do
190
- @c1.pg_array_to_many :tags, :clone=>:tags, :order=>[:a, :b]
191
- @c2.many_to_pg_array :artists, :clone=>:artists, :order=>[:a, :b]
192
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) ORDER BY a, b"
193
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[]) ORDER BY a, b"
194
- end
195
-
196
- it "should support a select option" do
197
- @c1.pg_array_to_many :tags, :clone=>:tags, :select=>[:a, :b]
198
- @c2.many_to_pg_array :artists, :clone=>:artists, :select=>[:a, :b]
199
- @c1.load(:tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.must_equal "SELECT a, b FROM tags WHERE (tags.id IN (1, 2, 3))"
200
- @c2.load(:id=>1).artists_dataset.sql.must_equal "SELECT a, b FROM artists WHERE (artists.tag_ids @> ARRAY[1]::integer[])"
201
- end
202
-
203
- it "should accept a block" do
204
- @c1.pg_array_to_many :tags, :clone=>:tags do |ds| ds.filter(:yyy=>@yyy) end
205
- @c2.many_to_pg_array :artists, :clone=>:artists do |ds| ds.filter(:a=>1) end
206
- @c1.new(:yyy=>6, :tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((tags.id IN (1, 2, 3)) AND (yyy = 6))"
207
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((artists.tag_ids @> ARRAY[2]::integer[]) AND (a = 1))"
208
- end
209
-
210
- it "should support a :dataset option that is used instead of the default" do
211
- @c1.pg_array_to_many :tags, :clone=>:tags, :dataset=>proc{Tag.where(:id=>tag_ids.map{|x| x*2})}
212
- @c2.many_to_pg_array :artists, :clone=>:artists, :dataset=>proc{Artist.where(Sequel.pg_array(Sequel.pg_array(:tag_ids)[1..2]).contains([id]))}
213
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (id IN (2, 4, 6))"
214
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((tag_ids)[1:2] @> ARRAY[2])"
215
- end
216
-
217
- it "should support a :limit option" do
218
- @c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[2, 3]
219
- @c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[3, 2]
220
- @o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) LIMIT 2 OFFSET 3"
221
- @o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[]) LIMIT 3 OFFSET 2"
222
- end
223
-
224
- it "should support a :uniq option that removes duplicates from the association" do
225
- @c1.pg_array_to_many :tags, :clone=>:tags, :uniq=>true
226
- @c2.many_to_pg_array :artists, :clone=>:artists, :uniq=>true
227
- @c1.dataset = @c1.dataset.with_fetch([{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}])
228
- @c2.dataset = @c1.dataset.with_fetch([{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}])
229
- @o1.tags.must_equal [@c2.load(:id=>20), @c2.load(:id=>30)]
230
- @o2.artists.must_equal [@c1.load(:id=>20), @c1.load(:id=>30)]
231
- end
232
-
233
- it "reflection associated_object_keys should return correct values" do
234
- @c1.association_reflection(:tags).associated_object_keys.must_equal [:id]
235
- @c2.association_reflection(:artists).associated_object_keys.must_equal [:tag_ids]
236
- end
237
-
238
- it "reflection remove_before_destroy? should return correct values" do
239
- @c1.association_reflection(:tags).remove_before_destroy?.must_equal true
240
- @c2.association_reflection(:artists).remove_before_destroy?.must_equal false
241
- end
242
-
243
- it "reflection reciprocal should be correct" do
244
- @c1.association_reflection(:tags).reciprocal.must_equal :artists
245
- @c2.association_reflection(:artists).reciprocal.must_equal :tags
246
- end
247
-
248
- it "should eagerly load correctly" do
249
- a = @c1.eager(:tags).all
250
- a.must_equal [@o1]
251
- @db.sqls.must_equal ["SELECT * FROM artists",
252
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))']
253
- a.first.tags.must_equal [@o2]
254
- @db.sqls.must_equal []
255
-
256
- a = @c2.eager(:artists).all
257
- a.must_equal [@o2]
258
- @db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
259
- a.first.artists.must_equal [@o1]
260
- @db.sqls.must_equal []
261
- end
262
-
263
- it "should support using custom key options when eager loading associations" do
264
- @c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
265
- @c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids
266
- @c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
267
-
268
- a = @c1.eager(:tags).all
269
- a.must_equal [@o1]
270
- @db.sqls.must_equal ["SELECT * FROM artists",
271
- 'SELECT * FROM tags WHERE ((tags.id * 3) IN (3, 6, 9))']
272
- a.first.tags.must_equal [@o2]
273
- @db.sqls.must_equal []
274
-
275
- a = @c2.eager(:artists).all
276
- a.must_equal [@o2]
277
- @db.sqls.must_equal ["SELECT * FROM tags", "SELECT * FROM artists WHERE ((artists.tag_ids)[1:2] && ARRAY[6]::integer[])"]
278
- a.first.artists.must_equal [@o1]
279
- @db.sqls.must_equal []
280
- end
281
-
282
- it "should allow cascading of eager loading for associations of associated models" do
283
- a = @c1.eager(:tags=>:artists).all
284
- a.must_equal [@o1]
285
- @db.sqls.must_equal ["SELECT * FROM artists",
286
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))',
287
- "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
288
- a.first.tags.must_equal [@o2]
289
- a.first.tags.first.artists.must_equal [@o1]
290
- @db.sqls.must_equal []
291
- end
292
-
293
- it "should respect :eager when lazily loading an association" do
294
- @c1.pg_array_to_many :tags2, :clone=>:tags, :eager=>:artists, :key=>:tag_ids
295
- @c2.many_to_pg_array :artists2, :clone=>:artists, :eager=>:tags
296
-
297
- @o1.tags2.must_equal [@o2]
298
- @db.sqls.must_equal ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
299
- @o1.tags2.first.artists.must_equal [@o1]
300
- @db.sqls.must_equal []
301
-
302
- @o2.artists2.must_equal [@o1]
303
- @db.sqls.must_equal ["SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])",
304
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))']
305
- @o2.artists2.first.tags.must_equal [@o2]
306
- @db.sqls.must_equal []
307
- end
308
-
309
- it "should cascade eagerly loading when the :eager_graph association option is used" do
310
- @c1.pg_array_to_many :tags2, :clone=>:tags, :eager_graph=>:artists, :key=>:tag_ids
311
- @c2.many_to_pg_array :artists2, :clone=>:artists, :eager_graph=>:tags
312
-
313
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]))
314
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]))
315
- @db.sqls
316
-
317
- @o1.tags2.must_equal [@o2]
318
- @db.sqls.must_equal ['SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (tags.id IN (1, 2, 3))']
319
- @o1.tags2.first.artists.must_equal [@o1]
320
- @db.sqls.must_equal []
321
-
322
- @o2.artists2.must_equal [@o1]
323
- @db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (artists.tag_ids @> ARRAY[2]::integer[])"]
324
- @o2.artists2.first.tags.must_equal [@o2]
325
- @db.sqls.must_equal []
326
-
327
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]))
328
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tag_ids=>Sequel.pg_array([1,2,3]))
329
- @db.sqls
330
-
331
- a = @c1.eager(:tags2).all
332
- @db.sqls.must_equal ["SELECT * FROM artists",
333
- 'SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (tags.id IN (1, 2, 3))']
334
- a.must_equal [@o1]
335
- a.first.tags2.must_equal [@o2]
336
- a.first.tags2.first.artists.must_equal [@o1]
337
- @db.sqls.must_equal []
338
-
339
- @c2.dataset = @c2.dataset.with_fetch(:id=>2)
340
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]))
341
- @db.sqls
342
-
343
- a = @c2.eager(:artists2).all
344
- @db.sqls.must_equal ["SELECT * FROM tags", "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
345
- a.must_equal [@o2]
346
- a.first.artists2.must_equal [@o1]
347
- a.first.artists2.first.tags.must_equal [@o2]
348
- @db.sqls.must_equal []
349
- end
350
-
351
- it "should respect the :limit option when eager loading" do
352
- @c2.dataset = @c2.dataset.with_fetch([{:id=>1},{:id=>2}, {:id=>3}])
353
- @db.sqls
354
-
355
- @c1.pg_array_to_many :tags, :clone=>:tags, :limit=>2
356
- a = @c1.eager(:tags).all
357
- a.must_equal [@o1]
358
- @db.sqls.must_equal ["SELECT * FROM artists",
359
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))']
360
- a.first.tags.must_equal [@c2.load(:id=>1), @c2.load(:id=>2)]
361
- @db.sqls.must_equal []
362
-
363
- @c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[1, 1]
364
- a = @c1.eager(:tags).all
365
- a.must_equal [@o1]
366
- @db.sqls.must_equal ["SELECT * FROM artists",
367
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))']
368
- a.first.tags.must_equal [@c2.load(:id=>2)]
369
- @db.sqls.must_equal []
370
-
371
- @c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[nil, 1]
372
- a = @c1.eager(:tags).all
373
- a.must_equal [@o1]
374
- @db.sqls.must_equal ["SELECT * FROM artists",
375
- 'SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))']
376
- a.first.tags.must_equal [@c2.load(:id=>2), @c2.load(:id=>3)]
377
- @db.sqls.length.must_equal 0
378
-
379
- @c2.dataset = @c2.dataset.with_fetch(:id=>2)
380
- @c1.dataset = @c1.dataset.with_fetch([{:id=>5, :tag_ids=>Sequel.pg_array([1,2,3])},{:id=>6, :tag_ids=>Sequel.pg_array([2,3])}, {:id=>7, :tag_ids=>Sequel.pg_array([1,2])}])
381
- @db.sqls
382
-
383
- @c2.many_to_pg_array :artists, :clone=>:artists, :limit=>2
384
- a = @c2.eager(:artists).all
385
- a.must_equal [@o2]
386
- @db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
387
- a.first.artists.must_equal [@c1.load(:id=>5, :tag_ids=>Sequel.pg_array([1,2,3])), @c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
388
- @db.sqls.must_equal []
389
-
390
- @c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[1, 1]
391
- a = @c2.eager(:artists).all
392
- a.must_equal [@o2]
393
- @db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
394
- a.first.artists.must_equal [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
395
- @db.sqls.must_equal []
396
-
397
- @c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[nil, 1]
398
- a = @c2.eager(:artists).all
399
- a.must_equal [@o2]
400
- @db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
401
- a.first.artists.must_equal [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3])), @c1.load(:id=>7, :tag_ids=>Sequel.pg_array([1,2]))]
402
- @db.sqls.must_equal []
403
- end
404
-
405
- it "should support association_join" do
406
- @c1.association_join(:tags).sql.must_equal "SELECT * FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
407
- @c2.association_join(:artists).sql.must_equal "SELECT * FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
408
- end
409
-
410
- it "should support custom selects when using association_join" do
411
- @c1.select{a(b)}.association_join(:tags).sql.must_equal "SELECT a(b) FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
412
- @c2.select{a(b)}.association_join(:artists).sql.must_equal "SELECT a(b) FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
413
- end
414
-
415
- it "should eagerly graph associations" do
416
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]))
417
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]))
418
- @db.sqls
419
-
420
- a = @c1.eager_graph(:tags).all
421
- @db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
422
- a.must_equal [@o1]
423
- a.first.tags.must_equal [@o2]
424
- @db.sqls.must_equal []
425
-
426
- a = @c2.eager_graph(:artists).all
427
- @db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
428
- a.must_equal [@o2]
429
- a.first.artists.must_equal [@o1]
430
- @db.sqls.must_equal []
431
- end
432
-
433
- it "should allow cascading of eager graphing for associations of associated models" do
434
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]), :tags_0_id=>2)
435
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]), :artists_0_id=>1, :artists_0_tag_ids=>Sequel.pg_array([1,2,3]))
436
- @db.sqls
437
-
438
- a = @c1.eager_graph(:tags=>:artists).all
439
- @db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id, artists_0.id AS artists_0_id, artists_0.tag_ids AS artists_0_tag_ids FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) LEFT OUTER JOIN artists AS artists_0 ON (artists_0.tag_ids @> ARRAY[tags.id])"]
440
- a.must_equal [@o1]
441
- a.first.tags.must_equal [@o2]
442
- a.first.tags.first.artists.must_equal [@o1]
443
- @db.sqls.must_equal []
444
-
445
- a = @c2.eager_graph(:artists=>:tags).all
446
- @db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids, tags_0.id AS tags_0_id FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id]) LEFT OUTER JOIN tags AS tags_0 ON (artists.tag_ids @> ARRAY[tags_0.id])"]
447
- a.must_equal [@o2]
448
- a.first.artists.must_equal [@o1]
449
- a.first.artists.first.tags.must_equal [@o2]
450
- @db.sqls.must_equal []
451
- end
452
-
453
- it "eager graphing should respect key options" do
454
- @c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
455
- @c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
456
- @c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
457
-
458
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]), :tags_0_id=>2)
459
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]), :artists_0_id=>1, :artists_0_tag_ids=>Sequel.pg_array([1,2,3]))
460
- @db.sqls
461
-
462
- a = @c1.eager_graph(:tags).all
463
- a.must_equal [@o1]
464
- @db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((artists.tag_ids)[1:2] @> ARRAY[(tags.id * 3)])"]
465
- a.first.tags.must_equal [@o2]
466
- @db.sqls.must_equal []
467
-
468
- a = @c2.eager_graph(:artists).all
469
- a.must_equal [@o2]
470
- @db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.tag_ids)[1:2] @> ARRAY[tags.id3])"]
471
- a.first.artists.must_equal [@o1]
472
- @db.sqls.must_equal []
473
- end
474
-
475
- it "should respect the association's :graph_select option" do
476
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_select=>:id2
477
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_select=>:id
478
-
479
- @c2.dataset = @c2.dataset.with_fetch(:id=>2, :artists_id=>1)
480
- @c1.dataset = @c1.dataset.with_fetch(:id=>1, :id2=>2, :tag_ids=>Sequel.pg_array([1,2,3]))
481
- @db.sqls
482
-
483
- a = @c1.eager_graph(:tags).all
484
- @db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id2 FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
485
- a.must_equal [@o1]
486
- a.first.tags.must_equal [@c2.load(:id2=>2)]
487
- @db.sqls.must_equal []
488
-
489
- a = @c2.eager_graph(:artists).all
490
- @db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
491
- a.must_equal [@o2]
492
- a.first.artists.must_equal [@c1.load(:id=>1)]
493
- @db.sqls.must_equal []
494
- end
495
-
496
- it "should respect the association's :graph_join_type option" do
497
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_join_type=>:inner
498
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_join_type=>:inner
499
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
500
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
501
- end
502
-
503
- it "should respect the association's :conditions option" do
504
- @c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
505
- @c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
506
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
507
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
508
- end
509
-
510
- it "should respect the association's :graph_conditions option" do
511
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_conditions=>{:a=>1}
512
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_conditions=>{:a=>1}
513
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
514
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
515
- end
516
-
517
- it "should respect the association's :graph_block option" do
518
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
519
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
520
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
521
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
522
- end
523
-
524
- it "should respect the association's :graph_only_conditions option" do
525
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}
526
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}
527
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (tags.a = 1)"
528
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.a = 1)"
529
- end
530
-
531
- it "should respect the association's :graph_only_conditions with :graph_block option" do
532
- @c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
533
- @c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
534
- @c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.b = 1))"
535
- @c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (tags.b = 1))"
536
- end
537
-
538
- it "should define an add_ method for adding associated objects" do
539
- @o1.add_tag(@c2.load(:id=>4))
540
- @o1.tag_ids.must_equal [1,2,3,4]
541
- @db.sqls.must_equal []
542
- @o1.save_changes
543
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
544
-
545
- @o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([4])))
546
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4,2] WHERE (id = 1)"]
547
- end
548
-
549
- it "should define a remove_ method for removing associated objects" do
550
- @o1.remove_tag(@o2)
551
- @o1.tag_ids.must_equal [1,3]
552
- @db.sqls.must_equal []
553
- @o1.save_changes
554
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3] WHERE (id = 1)"]
555
-
556
- @o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([1,2,3,4])))
557
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
558
- end
559
-
560
- it "should define a remove_all_ method for removing all associated objects" do
561
- @o1.remove_all_tags
562
- @o1.tag_ids.must_equal []
563
- @db.sqls.must_equal []
564
- @o1.save_changes
565
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
566
-
567
- @o2.remove_all_artists
568
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = array_remove(tag_ids, CAST(2 AS integer)) WHERE (tag_ids @> ARRAY[2]::integer[])"]
569
- end
570
-
571
- it "should define a remove_all_ method for removing all associated objects respecting database type" do
572
- @c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:bigint
573
- @o1.remove_all_tags
574
- @o1.tag_ids.must_equal []
575
- @db.sqls.must_equal []
576
- @o1.save_changes
577
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
578
-
579
- @o2.remove_all_artists
580
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = array_remove(tag_ids, CAST(2 AS bigint)) WHERE (tag_ids @> ARRAY[2]::bigint[])"]
581
- end
582
-
583
- it "should allow calling add_ and remove_ methods on new objects for pg_array_to_many associations" do
584
- a = Artist.new
585
- a.add_tag(@c2.load(:id=>4))
586
- a.tag_ids.must_equal [4]
587
- a.remove_tag(@c2.load(:id=>4))
588
- a.tag_ids.must_equal []
589
- a.add_tag(@c2.load(:id=>4))
590
- a.tag_ids.must_equal [4]
591
- a.remove_all_tags
592
- a.tag_ids.must_equal []
593
- end
594
-
595
- it "should have pg_array_to_many association modification methods save if :save_after_modify option is used" do
596
- @c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
597
-
598
- @o1.add_tag(@c2.load(:id=>4))
599
- @o1.tag_ids.must_equal [1,2,3,4]
600
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
601
-
602
- @o1.remove_tag(@o2)
603
- @o1.tag_ids.must_equal [1,3,4]
604
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
605
-
606
- @o1.remove_all_tags
607
- @o1.tag_ids.must_equal []
608
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
609
- end
610
-
611
- it "should have association modification methods deal with nil values" do
612
- v = @c1.load(:id=>1)
613
- v.add_tag(@c2.load(:id=>4))
614
- v.tag_ids.must_equal [4]
615
- @db.sqls.must_equal []
616
- v.save_changes
617
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4]::integer[] WHERE (id = 1)"]
618
-
619
- @o2.add_artist(@c1.load(:id=>1))
620
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2]::integer[] WHERE (id = 1)"]
621
-
622
- v = @c1.load(:id=>1)
623
- v.remove_tag(@c2.load(:id=>4))
624
- v.tag_ids.must_be_nil
625
- @db.sqls.must_equal []
626
- v.save_changes
627
- @db.sqls.must_equal []
628
-
629
- @o2.remove_artist(@c1.load(:id=>1))
630
- @db.sqls.must_equal []
631
-
632
- v = @c1.load(:id=>1)
633
- v.remove_all_tags
634
- v.tag_ids.must_be_nil
635
- @db.sqls.must_equal []
636
- v.save_changes
637
- @db.sqls.must_equal []
638
- end
639
-
640
- it "should have association modification methods deal with empty arrays values" do
641
- v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
642
- v.add_tag(@c2.load(:id=>4))
643
- v.tag_ids.must_equal [4]
644
- @db.sqls.must_equal []
645
- v.save_changes
646
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4] WHERE (id = 1)"]
647
-
648
- @o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
649
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2] WHERE (id = 1)"]
650
-
651
- v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
652
- v.remove_tag(@c2.load(:id=>4))
653
- v.tag_ids.must_equal []
654
- @db.sqls.must_equal []
655
- v.save_changes
656
- @db.sqls.must_equal []
657
-
658
- @o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
659
- @db.sqls.must_equal []
660
-
661
- v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
662
- v.remove_all_tags
663
- v.tag_ids.must_equal []
664
- @db.sqls.must_equal []
665
- v.save_changes
666
- @db.sqls.must_equal []
667
- end
668
-
669
- it "should respect the :array_type option when manually creating arrays" do
670
- @c1.pg_array_to_many :tags, :clone=>:tags, :array_type=>:int8
671
- @c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
672
- v = @c1.load(:id=>1)
673
- v.add_tag(@c2.load(:id=>4))
674
- v.tag_ids.must_equal [4]
675
- @db.sqls.must_equal []
676
- v.save_changes
677
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4]::int8[] WHERE (id = 1)"]
678
-
679
- @o2.add_artist(@c1.load(:id=>1))
680
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2]::int8[] WHERE (id = 1)"]
681
- end
682
-
683
- it "should respect the :array_type option in the associations dataset" do
684
- @c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
685
- @c2.load(:id=>1).artists_dataset.sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
686
- end
687
-
688
- it "should respect the :array_type option when eager loading" do
689
- @c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
690
- @c2.eager(:artists).all
691
- @db.sqls.must_equal ["SELECT * FROM tags", "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::int8[])"]
692
- end
693
-
694
- it "should respect the :array_type option when filtering by associations" do
695
- @c1.pg_array_to_many :tags, :clone=>:tags, :array_type=>:int8
696
- @c1.where(:tags=>@c2.load(:id=>1)).sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
697
- @c1.where(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2]::int8[])'
698
- end
699
-
700
- it "should automatically determine the array type by looking at the schema" do
701
- @c1.db_schema[:tag_ids][:db_type] = 'int8[]'
702
- @c2.many_to_pg_array :artists, :clone=>:artists
703
- @c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
704
- @c2.load(:id=>1).artists_dataset.sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
705
- @c1.load(:id=>1).add_tag(@c2.load(:id=>1))
706
- @db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1]::int8[] WHERE (id = 1)"]
707
- end
708
-
709
- it "should automatically determine the array type by looking at the schema" do
710
- end
711
-
712
- it "should not validate the current/associated object in add_ and remove_ if the :validate=>false option is used" do
713
- @c1.pg_array_to_many :tags, :clone=>:tags, :validate=>false, :save_after_modify=>true
714
- @c2.many_to_pg_array :artists, :clone=>:artists, :validate=>false
715
- a = @c1.load(:id=>1)
716
- t = @c2.load(:id=>2)
717
- def a.validate() errors.add(:id, 'foo') end
718
- a.associations[:tags] = []
719
- a.add_tag(t).must_equal t
720
- a.tags.must_equal [t]
721
- a.remove_tag(t).must_equal t
722
- a.tags.must_equal []
723
-
724
- t.associations[:artists] = []
725
- t.add_artist(a).must_equal a
726
- t.artists.must_equal [a]
727
- t.remove_artist(a).must_equal a
728
- t.artists.must_equal []
729
- end
730
-
731
- it "should not raise exception in add_ and remove_ if the :raise_on_save_failure=>false option is used" do
732
- @c1.pg_array_to_many :tags, :clone=>:tags, :raise_on_save_failure=>false, :save_after_modify=>true
733
- @c2.many_to_pg_array :artists, :clone=>:artists, :raise_on_save_failure=>false
734
- a = @c1.load(:id=>1)
735
- t = @c2.load(:id=>2)
736
- def a.validate() errors.add(:id, 'foo') end
737
- a.associations[:tags] = []
738
- a.add_tag(t).must_be_nil
739
- a.tags.must_equal []
740
- a.associations[:tags] = [t]
741
- a.remove_tag(t).must_be_nil
742
- a.tags.must_equal [t]
743
-
744
- t.associations[:artists] = []
745
- t.add_artist(a).must_be_nil
746
- t.artists.must_equal []
747
- t.associations[:artists] = [a]
748
- t.remove_artist(a).must_be_nil
749
- t.artists.must_equal [a]
750
- end
751
- end
752
-
753
- describe "Sequel::Model.finalize_associations" do
754
- before do
755
- @db = Sequel.mock(:host=>'postgres', :numrows=>1)
756
- @db.extend_datasets do
757
- def quote_identifiers?; false end
758
- end
759
- class ::Foo < Sequel::Model(@db)
760
- plugin :pg_array_associations
761
- many_to_pg_array :items
762
- end
763
- class ::Item < Sequel::Model(@db)
764
- plugin :pg_array_associations
765
- pg_array_to_many :foos
766
- end
767
- [Foo, Item].each(&:finalize_associations)
768
- @db.sqls
769
- end
770
- after do
771
- Object.send(:remove_const, :Item)
772
- Object.send(:remove_const, :Foo)
773
- end
774
-
775
- it "should finalize pg_array_to_many associations" do
776
- r = Item.association_reflection(:foos)
777
- r[:class].must_equal Foo
778
- r[:_dataset].sql.must_equal "SELECT * FROM foos"
779
- r[:associated_eager_dataset].sql.must_equal "SELECT * FROM foos"
780
- r.fetch(:_eager_limit_strategy).must_be_nil
781
- r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT array_agg(foos.id) FROM foos WHERE (foos.id IS NOT NULL)"
782
- r[:predicate_key].must_equal Sequel.qualify(:foos, :id)
783
- r[:predicate_keys].must_equal [Sequel.qualify(:foos, :id)]
784
- r[:reciprocal].must_equal :items
785
- r[:array_type].must_equal :integer
786
- r[:primary_key].must_equal :id
787
- r[:primary_key_method].must_equal :id
788
- end
789
-
790
- it "should finalize many_to_pg_array associations" do
791
- r = Foo.association_reflection(:items)
792
- r[:class].must_equal Item
793
- r[:_dataset].sql.must_equal "SELECT * FROM items"
794
- r[:associated_eager_dataset].sql.must_equal "SELECT * FROM items"
795
- r.fetch(:_eager_limit_strategy).must_be_nil
796
- r[:filter_by_associations_conditions_dataset].sql.must_equal "SELECT _smtopgaa_key_ FROM items CROSS JOIN unnest(items.foo_ids) AS _smtopgaa_(_smtopgaa_key_) WHERE (items.foo_ids IS NOT NULL)"
797
- r[:predicate_key].must_equal Sequel.qualify(:items, :foo_ids)
798
- r[:predicate_keys].must_equal [Sequel.qualify(:items, :foo_ids)]
799
- r[:reciprocal].must_equal :foos
800
- r[:array_type].must_equal :integer
801
- end
802
- end