sequel 4.41.0 → 4.42.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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +98 -0
  3. data/README.rdoc +23 -10
  4. data/doc/active_record.rdoc +4 -4
  5. data/doc/advanced_associations.rdoc +2 -2
  6. data/doc/association_basics.rdoc +5 -2
  7. data/doc/cheat_sheet.rdoc +3 -3
  8. data/doc/core_extensions.rdoc +2 -2
  9. data/doc/dataset_basics.rdoc +4 -4
  10. data/doc/dataset_filtering.rdoc +1 -1
  11. data/doc/migration.rdoc +19 -1
  12. data/doc/prepared_statements.rdoc +2 -2
  13. data/doc/release_notes/4.42.0.txt +221 -0
  14. data/doc/testing.rdoc +3 -1
  15. data/lib/sequel/adapters/ado/access.rb +0 -1
  16. data/lib/sequel/adapters/ado/mssql.rb +0 -1
  17. data/lib/sequel/adapters/do/mysql.rb +0 -1
  18. data/lib/sequel/adapters/do/postgres.rb +0 -1
  19. data/lib/sequel/adapters/do/sqlite3.rb +0 -1
  20. data/lib/sequel/adapters/ibmdb.rb +21 -25
  21. data/lib/sequel/adapters/jdbc.rb +8 -16
  22. data/lib/sequel/adapters/jdbc/as400.rb +0 -1
  23. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -1
  24. data/lib/sequel/adapters/jdbc/db2.rb +0 -1
  25. data/lib/sequel/adapters/jdbc/derby.rb +0 -1
  26. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -1
  27. data/lib/sequel/adapters/jdbc/h2.rb +0 -1
  28. data/lib/sequel/adapters/jdbc/hsqldb.rb +0 -1
  29. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -1
  30. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -1
  31. data/lib/sequel/adapters/jdbc/jtds.rb +0 -1
  32. data/lib/sequel/adapters/jdbc/mssql.rb +0 -1
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -1
  34. data/lib/sequel/adapters/jdbc/oracle.rb +0 -1
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -13
  36. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +0 -1
  37. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -1
  38. data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -4
  39. data/lib/sequel/adapters/mock.rb +54 -12
  40. data/lib/sequel/adapters/mysql.rb +1 -1
  41. data/lib/sequel/adapters/mysql2.rb +11 -17
  42. data/lib/sequel/adapters/odbc/mssql.rb +0 -1
  43. data/lib/sequel/adapters/oracle.rb +8 -20
  44. data/lib/sequel/adapters/postgres.rb +11 -29
  45. data/lib/sequel/adapters/shared/access.rb +5 -12
  46. data/lib/sequel/adapters/shared/cubrid.rb +4 -13
  47. data/lib/sequel/adapters/shared/db2.rb +4 -2
  48. data/lib/sequel/adapters/shared/firebird.rb +2 -4
  49. data/lib/sequel/adapters/shared/informix.rb +4 -2
  50. data/lib/sequel/adapters/shared/mssql.rb +3 -5
  51. data/lib/sequel/adapters/shared/mysql.rb +4 -14
  52. data/lib/sequel/adapters/shared/oracle.rb +1 -3
  53. data/lib/sequel/adapters/shared/postgres.rb +16 -38
  54. data/lib/sequel/adapters/shared/progress.rb +0 -2
  55. data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -2
  56. data/lib/sequel/adapters/shared/sqlite.rb +20 -16
  57. data/lib/sequel/adapters/sqlite.rb +8 -20
  58. data/lib/sequel/adapters/swift/mysql.rb +0 -1
  59. data/lib/sequel/adapters/swift/postgres.rb +0 -1
  60. data/lib/sequel/adapters/swift/sqlite.rb +0 -1
  61. data/lib/sequel/adapters/tinytds.rb +4 -12
  62. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  63. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -2
  64. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +11 -34
  65. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  66. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +26 -0
  67. data/lib/sequel/ast_transformer.rb +2 -2
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +0 -66
  70. data/lib/sequel/database/features.rb +6 -0
  71. data/lib/sequel/database/misc.rb +31 -17
  72. data/lib/sequel/database/query.rb +7 -4
  73. data/lib/sequel/database/schema_methods.rb +1 -1
  74. data/lib/sequel/dataset.rb +8 -8
  75. data/lib/sequel/dataset/actions.rb +140 -46
  76. data/lib/sequel/dataset/features.rb +1 -5
  77. data/lib/sequel/dataset/graph.rb +7 -8
  78. data/lib/sequel/dataset/misc.rb +127 -56
  79. data/lib/sequel/dataset/mutation.rb +9 -20
  80. data/lib/sequel/dataset/placeholder_literalizer.rb +10 -1
  81. data/lib/sequel/dataset/prepared_statements.rb +102 -46
  82. data/lib/sequel/dataset/query.rb +155 -72
  83. data/lib/sequel/dataset/sql.rb +26 -9
  84. data/lib/sequel/extensions/columns_introspection.rb +3 -1
  85. data/lib/sequel/extensions/core_extensions.rb +5 -5
  86. data/lib/sequel/extensions/core_refinements.rb +5 -5
  87. data/lib/sequel/extensions/duplicate_columns_handler.rb +4 -2
  88. data/lib/sequel/extensions/freeze_datasets.rb +69 -0
  89. data/lib/sequel/extensions/identifier_mangling.rb +196 -0
  90. data/lib/sequel/extensions/looser_typecasting.rb +11 -7
  91. data/lib/sequel/extensions/migration.rb +1 -1
  92. data/lib/sequel/extensions/null_dataset.rb +5 -2
  93. data/lib/sequel/extensions/pagination.rb +42 -23
  94. data/lib/sequel/extensions/pg_enum.rb +3 -3
  95. data/lib/sequel/extensions/query.rb +3 -3
  96. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +15 -8
  97. data/lib/sequel/model/associations.rb +25 -8
  98. data/lib/sequel/model/base.rb +88 -29
  99. data/lib/sequel/model/dataset_module.rb +37 -0
  100. data/lib/sequel/plugins/association_pks.rb +4 -4
  101. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  102. data/lib/sequel/plugins/constraint_validations.rb +1 -2
  103. data/lib/sequel/plugins/csv_serializer.rb +2 -2
  104. data/lib/sequel/plugins/dataset_associations.rb +8 -8
  105. data/lib/sequel/plugins/eager_each.rb +2 -2
  106. data/lib/sequel/plugins/instance_filters.rb +1 -1
  107. data/lib/sequel/plugins/json_serializer.rb +2 -2
  108. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  109. data/lib/sequel/plugins/list.rb +4 -4
  110. data/lib/sequel/plugins/prepared_statements.rb +2 -4
  111. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -3
  112. data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
  113. data/lib/sequel/plugins/rcte_tree.rb +13 -13
  114. data/lib/sequel/plugins/sharding.rb +1 -1
  115. data/lib/sequel/plugins/single_table_inheritance.rb +9 -4
  116. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  117. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  118. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  119. data/lib/sequel/plugins/xml_serializer.rb +2 -2
  120. data/lib/sequel/sql.rb +69 -36
  121. data/lib/sequel/version.rb +1 -1
  122. data/spec/adapters/db2_spec.rb +10 -0
  123. data/spec/adapters/firebird_spec.rb +1 -1
  124. data/spec/adapters/mssql_spec.rb +4 -5
  125. data/spec/adapters/mysql_spec.rb +9 -9
  126. data/spec/adapters/postgres_spec.rb +67 -68
  127. data/spec/adapters/spec_helper.rb +6 -1
  128. data/spec/adapters/sqlite_spec.rb +29 -15
  129. data/spec/core/connection_pool_spec.rb +14 -14
  130. data/spec/core/database_spec.rb +38 -180
  131. data/spec/core/dataset_mutation_spec.rb +253 -0
  132. data/spec/core/dataset_spec.rb +394 -537
  133. data/spec/core/expression_filters_spec.rb +34 -32
  134. data/spec/core/mock_adapter_spec.rb +27 -35
  135. data/spec/core/placeholder_literalizer_spec.rb +2 -4
  136. data/spec/core/schema_generator_spec.rb +4 -4
  137. data/spec/core/schema_spec.rb +1 -2
  138. data/spec/core_extensions_spec.rb +22 -29
  139. data/spec/extensions/active_model_spec.rb +6 -6
  140. data/spec/extensions/association_dependencies_spec.rb +2 -2
  141. data/spec/extensions/blacklist_security_spec.rb +3 -3
  142. data/spec/extensions/boolean_readers_spec.rb +12 -12
  143. data/spec/extensions/caching_spec.rb +13 -10
  144. data/spec/extensions/class_table_inheritance_spec.rb +38 -43
  145. data/spec/extensions/column_conflicts_spec.rb +1 -3
  146. data/spec/extensions/columns_introspection_spec.rb +2 -3
  147. data/spec/extensions/composition_spec.rb +5 -3
  148. data/spec/extensions/constraint_validations_plugin_spec.rb +5 -5
  149. data/spec/extensions/constraint_validations_spec.rb +14 -8
  150. data/spec/extensions/core_refinements_spec.rb +22 -29
  151. data/spec/extensions/csv_serializer_spec.rb +7 -6
  152. data/spec/extensions/date_arithmetic_spec.rb +15 -15
  153. data/spec/extensions/defaults_setter_spec.rb +2 -2
  154. data/spec/extensions/delay_add_association_spec.rb +1 -1
  155. data/spec/extensions/dirty_spec.rb +19 -10
  156. data/spec/extensions/duplicate_columns_handler_spec.rb +12 -18
  157. data/spec/extensions/eager_each_spec.rb +12 -16
  158. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  159. data/spec/extensions/eval_inspect_spec.rb +4 -3
  160. data/spec/extensions/force_encoding_spec.rb +12 -12
  161. data/spec/extensions/freeze_datasets_spec.rb +31 -0
  162. data/spec/extensions/graph_each_spec.rb +6 -18
  163. data/spec/extensions/hook_class_methods_spec.rb +7 -7
  164. data/spec/extensions/identifier_mangling_spec.rb +307 -0
  165. data/spec/extensions/instance_filters_spec.rb +5 -6
  166. data/spec/extensions/instance_hooks_spec.rb +12 -12
  167. data/spec/extensions/json_serializer_spec.rb +12 -15
  168. data/spec/extensions/lazy_attributes_spec.rb +4 -4
  169. data/spec/extensions/list_spec.rb +19 -21
  170. data/spec/extensions/many_through_many_spec.rb +108 -163
  171. data/spec/extensions/meta_def_spec.rb +7 -2
  172. data/spec/extensions/migration_spec.rb +10 -12
  173. data/spec/extensions/mssql_optimistic_locking_spec.rb +4 -3
  174. data/spec/extensions/named_timezones_spec.rb +4 -3
  175. data/spec/extensions/nested_attributes_spec.rb +2 -2
  176. data/spec/extensions/null_dataset_spec.rb +17 -12
  177. data/spec/extensions/optimistic_locking_spec.rb +4 -5
  178. data/spec/extensions/pagination_spec.rb +8 -10
  179. data/spec/extensions/pg_array_associations_spec.rb +28 -27
  180. data/spec/extensions/pg_array_ops_spec.rb +2 -1
  181. data/spec/extensions/pg_array_spec.rb +6 -2
  182. data/spec/extensions/pg_enum_spec.rb +5 -3
  183. data/spec/extensions/pg_hstore_ops_spec.rb +3 -1
  184. data/spec/extensions/pg_hstore_spec.rb +7 -6
  185. data/spec/extensions/pg_inet_ops_spec.rb +2 -1
  186. data/spec/extensions/pg_inet_spec.rb +2 -1
  187. data/spec/extensions/pg_interval_spec.rb +2 -1
  188. data/spec/extensions/pg_json_ops_spec.rb +2 -1
  189. data/spec/extensions/pg_json_spec.rb +6 -3
  190. data/spec/extensions/pg_loose_count_spec.rb +1 -0
  191. data/spec/extensions/pg_range_ops_spec.rb +3 -1
  192. data/spec/extensions/pg_range_spec.rb +9 -5
  193. data/spec/extensions/pg_row_ops_spec.rb +2 -1
  194. data/spec/extensions/pg_row_plugin_spec.rb +4 -6
  195. data/spec/extensions/pg_row_spec.rb +5 -3
  196. data/spec/extensions/pg_static_cache_updater_spec.rb +2 -1
  197. data/spec/extensions/pg_typecast_on_load_spec.rb +1 -1
  198. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  199. data/spec/extensions/prepared_statements_spec.rb +12 -11
  200. data/spec/extensions/pretty_table_spec.rb +1 -1
  201. data/spec/extensions/query_spec.rb +8 -5
  202. data/spec/extensions/rcte_tree_spec.rb +39 -39
  203. data/spec/extensions/round_timestamps_spec.rb +2 -2
  204. data/spec/extensions/schema_dumper_spec.rb +3 -2
  205. data/spec/extensions/schema_spec.rb +2 -2
  206. data/spec/extensions/scissors_spec.rb +1 -2
  207. data/spec/extensions/sequel_3_dataset_methods_spec.rb +30 -17
  208. data/spec/extensions/serialization_modification_detection_spec.rb +2 -2
  209. data/spec/extensions/serialization_spec.rb +15 -13
  210. data/spec/extensions/set_overrides_spec.rb +14 -8
  211. data/spec/extensions/sharding_spec.rb +9 -18
  212. data/spec/extensions/shared_caching_spec.rb +3 -4
  213. data/spec/extensions/single_table_inheritance_spec.rb +11 -11
  214. data/spec/extensions/skip_create_refresh_spec.rb +2 -1
  215. data/spec/extensions/spec_helper.rb +1 -1
  216. data/spec/extensions/split_values_spec.rb +2 -2
  217. data/spec/extensions/sql_comments_spec.rb +6 -0
  218. data/spec/extensions/static_cache_spec.rb +7 -9
  219. data/spec/extensions/string_agg_spec.rb +30 -29
  220. data/spec/extensions/tactical_eager_loading_spec.rb +4 -5
  221. data/spec/extensions/thread_local_timezones_spec.rb +2 -2
  222. data/spec/extensions/timestamps_spec.rb +28 -3
  223. data/spec/extensions/to_dot_spec.rb +1 -2
  224. data/spec/extensions/tree_spec.rb +33 -29
  225. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  226. data/spec/extensions/unlimited_update_spec.rb +1 -0
  227. data/spec/extensions/update_primary_key_spec.rb +11 -7
  228. data/spec/extensions/update_refresh_spec.rb +1 -1
  229. data/spec/extensions/uuid_spec.rb +0 -1
  230. data/spec/extensions/validate_associated_spec.rb +1 -1
  231. data/spec/extensions/validation_class_methods_spec.rb +10 -10
  232. data/spec/extensions/validation_helpers_spec.rb +10 -10
  233. data/spec/extensions/xml_serializer_spec.rb +7 -3
  234. data/spec/integration/associations_test.rb +31 -31
  235. data/spec/integration/dataset_test.rb +17 -19
  236. data/spec/integration/eager_loader_test.rb +24 -24
  237. data/spec/integration/model_test.rb +6 -6
  238. data/spec/integration/plugin_test.rb +43 -43
  239. data/spec/integration/prepared_statement_test.rb +6 -6
  240. data/spec/integration/schema_test.rb +63 -52
  241. data/spec/integration/spec_helper.rb +6 -1
  242. data/spec/integration/transaction_test.rb +13 -13
  243. data/spec/model/association_reflection_spec.rb +17 -17
  244. data/spec/model/associations_spec.rb +101 -96
  245. data/spec/model/base_spec.rb +175 -49
  246. data/spec/model/class_dataset_methods_spec.rb +5 -9
  247. data/spec/model/dataset_methods_spec.rb +5 -5
  248. data/spec/model/eager_loading_spec.rb +209 -235
  249. data/spec/model/hooks_spec.rb +15 -15
  250. data/spec/model/model_spec.rb +28 -21
  251. data/spec/model/plugins_spec.rb +4 -5
  252. data/spec/model/record_spec.rb +59 -57
  253. data/spec/model/spec_helper.rb +1 -1
  254. data/spec/model/validations_spec.rb +6 -6
  255. data/spec/spec_config.rb +1 -1
  256. metadata +10 -2
@@ -3,7 +3,6 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
3
3
  describe "instance_filters plugin" do
4
4
  before do
5
5
  @c = Class.new(Sequel::Model(:people))
6
- @c.dataset.quote_identifiers = false
7
6
  @c.columns :id, :name, :num
8
7
  @c.plugin :instance_filters
9
8
  @p = @c.load(:id=>1, :name=>'John', :num=>1)
@@ -14,7 +13,7 @@ describe "instance_filters plugin" do
14
13
  @p.update(:name=>'Bob')
15
14
  DB.sqls.must_equal ["UPDATE people SET name = 'Bob' WHERE (id = 1)"]
16
15
  @p.instance_filter(:name=>'Jim')
17
- @p.this.numrows = 0
16
+ @p.instance_variable_set(:@this, @p.this.with_numrows(0))
18
17
  proc{@p.update(:name=>'Joe')}.must_raise(Sequel::Plugins::InstanceFilters::Error)
19
18
  DB.sqls.must_equal ["UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Jim'))"]
20
19
  end
@@ -23,7 +22,7 @@ describe "instance_filters plugin" do
23
22
  @p.destroy
24
23
  DB.sqls.must_equal ["DELETE FROM people WHERE id = 1"]
25
24
  @p.instance_filter(:name=>'Jim')
26
- @p.this.numrows = 0
25
+ @p.instance_variable_set(:@this, @p.this.with_numrows(0))
27
26
  proc{@p.destroy}.must_raise(Sequel::Plugins::InstanceFilters::Error)
28
27
  DB.sqls.must_equal ["DELETE FROM people WHERE ((id = 1) AND (name = 'Jim'))"]
29
28
  end
@@ -34,16 +33,16 @@ describe "instance_filters plugin" do
34
33
  @p.update(:name=>'Bob')
35
34
  DB.sqls.must_equal ["UPDATE people SET name = 'Bob' WHERE (id = 1)"]
36
35
  @p.instance_filter(:name=>'Jim')
37
- @p.this.numrows = 0
36
+ @p.instance_variable_set(:@this, @p.this.with_numrows(0))
38
37
  proc{@p.update(:name=>'Joe')}.must_raise(Sequel::Plugins::InstanceFilters::Error)
39
38
  DB.sqls.must_equal ["UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Jim'))"]
40
39
 
41
40
  @p = @c.load(:id=>1, :name=>'John', :num=>1)
42
- @p.this.numrows = 1
41
+ @p.instance_variable_set(:@this, @p.this.with_numrows(1))
43
42
  @p.destroy
44
43
  DB.sqls.must_equal ["DELETE FROM people WHERE (id = 1)"]
45
44
  @p.instance_filter(:name=>'Jim')
46
- @p.this.numrows = 0
45
+ @p.instance_variable_set(:@this, @p.this.with_numrows(0))
47
46
  proc{@p.destroy}.must_raise(Sequel::Plugins::InstanceFilters::Error)
48
47
  DB.sqls.must_equal ["DELETE FROM people WHERE ((id = 1) AND (name = 'Jim'))"]
49
48
 
@@ -28,10 +28,10 @@ describe "InstanceHooks plugin" do
28
28
  @o.after_create_hook{r 1}
29
29
  @o.before_create_hook{r false}
30
30
  @o.before_create_hook{r 4}
31
- @o.save.must_equal nil
31
+ @o.save.must_be_nil
32
32
  @r.must_equal [4, false]
33
33
  @r.clear
34
- @o.save.must_equal nil
34
+ @o.save.must_be_nil
35
35
  @r.must_equal [4, false]
36
36
  end
37
37
 
@@ -50,10 +50,10 @@ describe "InstanceHooks plugin" do
50
50
  @x.after_update_hook{r 1}
51
51
  @x.before_update_hook{r false}
52
52
  @x.before_update_hook{r 4}
53
- @x.save.must_equal nil
53
+ @x.save.must_be_nil
54
54
  @r.must_equal [4, false]
55
55
  @r.clear
56
- @x.save.must_equal nil
56
+ @x.save.must_be_nil
57
57
  @r.must_equal [4, false]
58
58
  end
59
59
 
@@ -80,17 +80,17 @@ describe "InstanceHooks plugin" do
80
80
  @x.after_save_hook{r 1}
81
81
  @x.before_save_hook{r false}
82
82
  @x.before_save_hook{r 4}
83
- @x.save.must_equal nil
83
+ @x.save.must_be_nil
84
84
  @r.must_equal [4, false]
85
85
  @r.clear
86
86
 
87
87
  @x.after_save_hook{r 1}
88
88
  @x.before_save_hook{r false}
89
89
  @x.before_save_hook{r 4}
90
- @x.save.must_equal nil
90
+ @x.save.must_be_nil
91
91
  @r.must_equal [4, false]
92
92
  @r.clear
93
- @x.save.must_equal nil
93
+ @x.save.must_be_nil
94
94
  @r.must_equal [4, false]
95
95
  end
96
96
 
@@ -107,7 +107,7 @@ describe "InstanceHooks plugin" do
107
107
  @x.after_destroy_hook{r 1}
108
108
  @x.before_destroy_hook{r false}
109
109
  @x.before_destroy_hook{r 4}
110
- @x.destroy.must_equal nil
110
+ @x.destroy.must_be_nil
111
111
  @r.must_equal [4, false]
112
112
  end
113
113
 
@@ -180,9 +180,9 @@ describe "InstanceHooks plugin" do
180
180
  it "should not clear validations hooks on successful save" do
181
181
  @x.after_validation_hook{@x.errors.add(:id, 'a') if @x.id == 1; r 1}
182
182
  @x.before_validation_hook{r 2}
183
- @x.save.must_equal nil
183
+ @x.save.must_be_nil
184
184
  @r.must_equal [2, 1]
185
- @x.save.must_equal nil
185
+ @x.save.must_be_nil
186
186
  @r.must_equal [2, 1, 2, 1]
187
187
  @x.id = 2
188
188
  @x.save.must_equal @x
@@ -237,7 +237,7 @@ describe "InstanceHooks plugin with transactions" do
237
237
  it "should support after_rollback_hook" do
238
238
  @or.after_rollback_hook{@db.execute('ar1')}
239
239
  @or.after_rollback_hook{@db.execute('ar2')}
240
- @or.save.must_equal nil
240
+ @or.save.must_be_nil
241
241
  @db.sqls.must_equal ['BEGIN', 'as', 'ROLLBACK', 'ar1', 'ar2']
242
242
  end
243
243
 
@@ -251,7 +251,7 @@ describe "InstanceHooks plugin with transactions" do
251
251
  it "should support after_rollback_hook" do
252
252
  @or.after_destroy_rollback_hook{@db.execute('adr1')}
253
253
  @or.after_destroy_rollback_hook{@db.execute('adr2')}
254
- @or.destroy.must_equal nil
254
+ @or.destroy.must_be_nil
255
255
  @db.sqls.must_equal ['BEGIN', "DELETE FROM items WHERE (id = 1)", 'ad', 'ROLLBACK', 'adr1', 'adr2']
256
256
  end
257
257
 
@@ -174,16 +174,15 @@ describe "Sequel::Plugins::JsonSerializer" do
174
174
  end
175
175
 
176
176
  it "should support a to_json class and dataset method" do
177
- Album.dataset._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
178
- Artist.dataset._fetch = {:id=>2, :name=>'YJM'}
177
+ Album.dataset = Album.dataset.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
178
+ Artist.dataset = Artist.dataset.with_fetch(:id=>2, :name=>'YJM')
179
179
  Album.array_from_json(Album.to_json).must_equal [@album]
180
180
  Album.array_from_json(Album.to_json(:include=>:artist), :associations=>:artist).map{|x| x.artist}.must_equal [@artist]
181
181
  Album.array_from_json(Album.dataset.to_json(:only=>:name)).must_equal [Album.load(:name=>@album.name)]
182
182
  end
183
183
 
184
184
  it "should have dataset to_json method work with naked datasets" do
185
- ds = Album.dataset.naked
186
- ds._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
185
+ ds = Album.dataset.naked.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
187
186
  Sequel.parse_json(ds.to_json).must_equal [@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}]
188
187
  end
189
188
 
@@ -227,7 +226,7 @@ describe "Sequel::Plugins::JsonSerializer" do
227
226
  end
228
227
  end
229
228
  Namespace::Album.new({}).to_json(:root=>true).to_s.must_equal '{"album":{}}'
230
- Namespace::Album.dataset._fetch = [{}]
229
+ Namespace::Album.dataset = Namespace::Album.dataset.with_fetch([{}])
231
230
  Namespace::Album.dataset.to_json(:root=>:collection).to_s.must_equal '{"albums":[{}]}'
232
231
  Namespace::Album.dataset.to_json(:root=>:both).to_s.must_equal '{"albums":[{"album":{}}]}'
233
232
  Object.send(:remove_const, :Namespace)
@@ -239,25 +238,23 @@ describe "Sequel::Plugins::JsonSerializer" do
239
238
  end
240
239
 
241
240
  it "should handle the :root=>:both option to qualify a dataset of records" do
242
- Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
243
- Album.dataset.to_json(:root=>:both, :only => :id).to_s.must_equal '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
241
+ Album.dataset.with_fetch([{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]).to_json(:root=>:both, :only => :id).to_s.must_equal '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
244
242
  end
245
243
 
246
244
  it "should handle the :root=>:collection option to qualify just the collection" do
247
- Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
248
- Album.dataset.to_json(:root=>:collection, :only => :id).to_s.must_equal '{"albums":[{"id":1},{"id":1}]}'
249
- Album.dataset.to_json(:root=>true, :only => :id).to_s.must_equal '{"albums":[{"id":1},{"id":1}]}'
245
+ ds = Album.dataset.with_fetch([{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}])
246
+ ds.to_json(:root=>:collection, :only => :id).to_s.must_equal '{"albums":[{"id":1},{"id":1}]}'
247
+ ds.to_json(:root=>true, :only => :id).to_s.must_equal '{"albums":[{"id":1},{"id":1}]}'
250
248
  end
251
249
 
252
250
  it "should handle the :root=>:instance option to qualify just the instances" do
253
- Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
254
- Album.dataset.to_json(:root=>:instance, :only => :id).to_s.must_equal '[{"album":{"id":1}},{"album":{"id":1}}]'
251
+ Album.dataset.with_fetch([{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]).to_json(:root=>:instance, :only => :id).to_s.must_equal '[{"album":{"id":1}},{"album":{"id":1}}]'
255
252
  end
256
253
 
257
254
  it "should handle the :root=>string option to qualify just the collection using the string as the key" do
258
- Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
259
- Album.dataset.to_json(:root=>"foos", :only => :id).to_s.must_equal '{"foos":[{"id":1},{"id":1}]}'
260
- Album.dataset.to_json(:root=>"bars", :only => :id).to_s.must_equal '{"bars":[{"id":1},{"id":1}]}'
255
+ ds = Album.dataset.with_fetch([{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}])
256
+ ds.to_json(:root=>"foos", :only => :id).to_s.must_equal '{"foos":[{"id":1},{"id":1}]}'
257
+ ds.to_json(:root=>"bars", :only => :id).to_s.must_equal '{"bars":[{"id":1},{"id":1}]}'
261
258
  end
262
259
 
263
260
  it "should use an alias for an included asscociation to qualify an association" do
@@ -12,7 +12,7 @@ describe "Sequel::Plugins::LazyAttributes" do
12
12
  meta_def(:columns){[:id, :name]}
13
13
  lazy_attributes :name
14
14
  meta_def(:columns){[:id]}
15
- instance_dataset._fetch = dataset._fetch = proc do |sql|
15
+ set_dataset dataset.with_fetch(proc do |sql|
16
16
  if sql !~ /WHERE/
17
17
  if sql =~ /name/
18
18
  [{:id=>1, :name=>'1'}, {:id=>2, :name=>'2'}]
@@ -32,7 +32,7 @@ describe "Sequel::Plugins::LazyAttributes" do
32
32
  end
33
33
  end
34
34
  end
35
- end
35
+ end)
36
36
  end
37
37
  @c = ::LazyAttributesModel
38
38
  @ds = LazyAttributesModel.dataset
@@ -108,7 +108,7 @@ describe "Sequel::Plugins::LazyAttributes" do
108
108
  it "should not lazily load the attribute for a single model object if it is a new record" do
109
109
  m = @c.new
110
110
  m.values.must_equal({})
111
- m.name.must_equal nil
111
+ m.name.must_be_nil
112
112
  @db.sqls.must_equal []
113
113
  end
114
114
 
@@ -148,7 +148,7 @@ describe "Sequel::Plugins::LazyAttributes" do
148
148
 
149
149
  it "should work with the serialization plugin" do
150
150
  @c.plugin :serialization, :yaml, :name
151
- @c.instance_dataset._fetch = @ds._fetch = [[{:id=>1}, {:id=>2}], [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}], [{:id=>1}], [{:name=>"--- 3\n"}]]
151
+ @ds = @c.dataset = @ds.with_fetch([[{:id=>1}, {:id=>2}], [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}], [{:id=>1}], [{:name=>"--- 3\n"}]])
152
152
  ms = @ds.all
153
153
  ms.map{|m| m.values}.must_equal [{:id=>1}, {:id=>2}]
154
154
  ms.map{|m| m.name}.must_equal [3,6]
@@ -56,7 +56,7 @@ describe "List plugin" do
56
56
  end
57
57
 
58
58
  it "should be able to access the scope proc as a class attribute" do
59
- @c.scope_proc.must_equal nil
59
+ @c.scope_proc.must_be_nil
60
60
  @sc.scope_proc[@sc.new(:scope_id=>4)].sql.must_equal 'SELECT * FROM items WHERE (scope_id = 4) ORDER BY scope_id, position'
61
61
  end
62
62
 
@@ -67,17 +67,16 @@ describe "List plugin" do
67
67
  end
68
68
 
69
69
  it "should have at_position return the model object at the given position" do
70
- @c.dataset._fetch = {:id=>1, :position=>1}
70
+ @c.dataset = @c.dataset.with_fetch(:id=>1, :position=>1)
71
71
  @o.at_position(10).must_equal @c.load(:id=>1, :position=>1)
72
- @sc.dataset._fetch = {:id=>2, :position=>2, :scope_id=>5}
72
+ @sc.dataset = @sc.dataset.with_fetch(:id=>2, :position=>2, :scope_id=>5)
73
73
  @so.at_position(20).must_equal @sc.load(:id=>2, :position=>2, :scope_id=>5)
74
74
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 10) ORDER BY position LIMIT 1",
75
75
  "SELECT * FROM items WHERE ((scope_id = 5) AND (position = 20)) ORDER BY scope_id, position LIMIT 1"]
76
76
  end
77
77
 
78
78
  it "should have position field set to max+1 when creating if not already set" do
79
- @c.instance_dataset._fetch = @c.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :position=>2}]]
80
- @c.instance_dataset.autoid = @c.dataset.autoid = 1
79
+ @c.dataset = @c.dataset.with_autoid(1).with_fetch([[{:pos=>nil}], [{:id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :position=>2}]])
81
80
  @c.create.values.must_equal(:id=>1, :position=>1)
82
81
  @c.create.values.must_equal(:id=>2, :position=>2)
83
82
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
@@ -89,8 +88,7 @@ describe "List plugin" do
89
88
  end
90
89
 
91
90
  it "should have position field set to max+1 in scope when creating if not already set" do
92
- @sc.instance_dataset._fetch = @sc.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :scope_id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :scope_id=>1, :position=>2}], [{:pos=>nil}], [{:id=>3, :scope_id=>2, :position=>1}]]
93
- @sc.instance_dataset.autoid = @sc.dataset.autoid = 1
91
+ @sc.dataset = @sc.dataset.with_autoid(1).with_fetch([[{:pos=>nil}], [{:id=>1, :scope_id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :scope_id=>1, :position=>2}], [{:pos=>nil}], [{:id=>3, :scope_id=>2, :position=>1}]])
94
92
  @sc.create(:scope_id=>1).values.must_equal(:id=>1, :scope_id=>1, :position=>1)
95
93
  @sc.create(:scope_id=>1).values.must_equal(:id=>2, :scope_id=>1, :position=>2)
96
94
  @sc.create(:scope_id=>2).values.must_equal(:id=>3, :scope_id=>2, :position=>1)
@@ -112,9 +110,9 @@ describe "List plugin" do
112
110
  end
113
111
 
114
112
  it "should have last_position return the last position in the list" do
115
- @c.dataset._fetch = {:max=>10}
113
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
116
114
  @o.last_position.must_equal 10
117
- @sc.dataset._fetch = {:max=>20}
115
+ @sc.dataset = @sc.dataset.with_fetch(:max=>20)
118
116
  @so.last_position.must_equal 20
119
117
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
120
118
  "SELECT max(position) AS max FROM items WHERE (scope_id = 5) LIMIT 1"]
@@ -129,7 +127,7 @@ describe "List plugin" do
129
127
  end
130
128
 
131
129
  it "should have move_down without an argument move down a single position" do
132
- @c.dataset._fetch = {:max=>10}
130
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
133
131
  @o.move_down.must_equal @o
134
132
  @o.position.must_equal 4
135
133
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
@@ -138,7 +136,7 @@ describe "List plugin" do
138
136
  end
139
137
 
140
138
  it "should have move_down with an argument move down the given number of positions" do
141
- @c.dataset._fetch = {:max=>10}
139
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
142
140
  @o.move_down(3).must_equal @o
143
141
  @o.position.must_equal 6
144
142
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
@@ -156,7 +154,7 @@ describe "List plugin" do
156
154
  it "should have move_to handle out of range targets" do
157
155
  @o.move_to(0)
158
156
  @o.position.must_equal 1
159
- @c.dataset._fetch = {:max=>10}
157
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
160
158
  @o.move_to(11)
161
159
  @o.position.must_equal 10
162
160
  end
@@ -183,13 +181,13 @@ describe "List plugin" do
183
181
  end
184
182
 
185
183
  it "should have move to shift entries correctly between current and target if moving down" do
186
- @c.dataset._fetch = {:max=>10}
184
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
187
185
  @o.move_to(4)
188
186
  @db.sqls[1].must_equal "UPDATE items SET position = (position - 1) WHERE ((position >= 4) AND (position <= 4))"
189
187
  end
190
188
 
191
189
  it "should have move_to_bottom move the item to the last position" do
192
- @c.dataset._fetch = {:max=>10}
190
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
193
191
  @o.move_to_bottom
194
192
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
195
193
  "UPDATE items SET position = (position - 1) WHERE ((position >= 4) AND (position <= 10))",
@@ -217,7 +215,7 @@ describe "List plugin" do
217
215
  end
218
216
 
219
217
  it "should have move_up with a negative argument move down the given number of positions" do
220
- @c.dataset._fetch = {:max=>10}
218
+ @c.dataset = @c.dataset.with_fetch(:max=>10)
221
219
  @o.move_up(-1).must_equal @o
222
220
  @o.position.must_equal 4
223
221
  @db.sqls.must_equal ["SELECT max(position) AS max FROM items LIMIT 1",
@@ -226,19 +224,19 @@ describe "List plugin" do
226
224
  end
227
225
 
228
226
  it "should have next return the next entry in the list if not given an argument" do
229
- @c.dataset._fetch = {:id=>9, :position=>4}
227
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>4)
230
228
  @o.next.must_equal @c.load(:id=>9, :position=>4)
231
229
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 4) ORDER BY position LIMIT 1"]
232
230
  end
233
231
 
234
232
  it "should have next return the entry the given number of positions below the instance if given an argument" do
235
- @c.dataset._fetch = {:id=>9, :position=>5}
233
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>5)
236
234
  @o.next(2).must_equal @c.load(:id=>9, :position=>5)
237
235
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 5) ORDER BY position LIMIT 1"]
238
236
  end
239
237
 
240
238
  it "should have next return a previous entry if given a negative argument" do
241
- @c.dataset._fetch = {:id=>9, :position=>2}
239
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>2)
242
240
  @o.next(-1).must_equal @c.load(:id=>9, :position=>2)
243
241
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 2) ORDER BY position LIMIT 1"]
244
242
  end
@@ -248,19 +246,19 @@ describe "List plugin" do
248
246
  end
249
247
 
250
248
  it "should have prev return the previous entry in the list if not given an argument" do
251
- @c.dataset._fetch = {:id=>9, :position=>2}
249
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>2)
252
250
  @o.prev.must_equal @c.load(:id=>9, :position=>2)
253
251
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 2) ORDER BY position LIMIT 1"]
254
252
  end
255
253
 
256
254
  it "should have prev return the entry the given number of positions above the instance if given an argument" do
257
- @c.dataset._fetch = {:id=>9, :position=>1}
255
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>1)
258
256
  @o.prev(2).must_equal @c.load(:id=>9, :position=>1)
259
257
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 1) ORDER BY position LIMIT 1"]
260
258
  end
261
259
 
262
260
  it "should have prev return a following entry if given a negative argument" do
263
- @c.dataset._fetch = {:id=>9, :position=>4}
261
+ @c.dataset = @c.dataset.with_fetch(:id=>9, :position=>4)
264
262
  @o.prev(-1).must_equal @c.load(:id=>9, :position=>4)
265
263
  @db.sqls.must_equal ["SELECT * FROM items WHERE (position = 4) ORDER BY position LIMIT 1"]
266
264
  end
@@ -12,8 +12,7 @@ describe Sequel::Model, "many_through_many" do
12
12
  end
13
13
  @c1 = Artist
14
14
  @c2 = Tag
15
- @dataset = @c2.dataset
16
- @dataset._fetch = {:id=>1}
15
+ @dataset = @c2.dataset = @c2.dataset.with_fetch(:id=>1)
17
16
  DB.reset
18
17
  end
19
18
  after do
@@ -50,8 +49,8 @@ describe Sequel::Model, "many_through_many" do
50
49
 
51
50
  it "should support using a custom :left_primary_key option when eager loading many_to_many associations" do
52
51
  @c1.send(:define_method, :id3){id*3}
53
- @c1.dataset._fetch = {:id=>1}
54
- @c2.dataset._fetch = {:id=>4, :x_foreign_key_x=>3}
52
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1)
53
+ @c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>3)
55
54
  @c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:id3
56
55
  a = @c1.eager(:tags).all
57
56
  a.must_equal [@c1.load(:id => 1)]
@@ -61,8 +60,8 @@ describe Sequel::Model, "many_through_many" do
61
60
  end
62
61
 
63
62
  it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup" do
64
- @c1.dataset._fetch = {:id=>1}
65
- @c2.dataset._fetch = {:id=>4, :x_foreign_key_x=>1}
63
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1)
64
+ @c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
66
65
  @c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>Sequel./(:albums_artists__artist_id, 3)
67
66
  a = @c1.eager(:tags).all
68
67
  a.must_equal [@c1.load(:id => 1)]
@@ -74,12 +73,13 @@ describe Sequel::Model, "many_through_many" do
74
73
  @c1.many_through_many :tags, :through=>[[:myschema__albums_artists, :artist_id, :album_id], [:myschema__albums, :id, :id], [:myschema__albums_tags, :album_id, :tag_id]]
75
74
  @c1.load(:id=>1).tags_dataset.sql.must_equal "SELECT tags.* FROM tags INNER JOIN myschema.albums_tags ON (myschema.albums_tags.tag_id = tags.id) INNER JOIN myschema.albums ON (myschema.albums.id = myschema.albums_tags.album_id) INNER JOIN myschema.albums_artists ON (myschema.albums_artists.album_id = myschema.albums.id) WHERE (myschema.albums_artists.artist_id = 1)"
76
75
 
77
- @c1.dataset._fetch = {:id=>1}
78
- @c2.dataset._fetch = {:id=>4, :x_foreign_key_x=>1}
76
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1)
77
+ @c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
79
78
  a = @c1.eager(:tags).all
80
79
  a.must_equal [@c1.load(:id => 1)]
81
80
  DB.sqls.must_equal ['SELECT * FROM artists', "SELECT tags.*, myschema.albums_artists.artist_id AS x_foreign_key_x FROM tags INNER JOIN myschema.albums_tags ON (myschema.albums_tags.tag_id = tags.id) INNER JOIN myschema.albums ON (myschema.albums.id = myschema.albums_tags.album_id) INNER JOIN myschema.albums_artists ON (myschema.albums_artists.album_id = myschema.albums.id) WHERE (myschema.albums_artists.artist_id IN (1))"]
82
81
 
82
+ Tag.dataset.columns(:id, :h1, :h2)
83
83
  @c1.eager_graph(:tags).sql.must_equal 'SELECT artists.id, tags.id AS tags_id, tags.h1, tags.h2 FROM artists LEFT OUTER JOIN myschema.albums_artists AS albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN myschema.albums AS albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN myschema.albums_tags AS albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id)'
84
84
  end
85
85
 
@@ -200,25 +200,25 @@ describe Sequel::Model, "many_through_many" do
200
200
  end
201
201
 
202
202
  it "should allowing filtering by many_through_many associations with :limit" do
203
- def (@c2.dataset).supports_window_functions?; true end
203
+ @c2.dataset = @c2.dataset.with_extend{def supports_window_functions?; true end}
204
204
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :limit=>10
205
205
  @c1.filter(:tags=>@c2.load(:id=>1234)).sql.must_equal 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((albums_artists.artist_id IS NOT NULL) AND ((albums_artists.artist_id, tags.id) IN (SELECT b, c FROM (SELECT albums_artists.artist_id AS b, tags.id AS c, row_number() OVER (PARTITION BY albums_artists.artist_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id)) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 1234))))'
206
206
  end
207
207
 
208
208
  it "should allowing filtering by many_through_many associations with :limit and composite keys" do
209
- def (@c2.dataset).supports_window_functions?; true end
209
+ @c2.dataset = @c2.dataset.with_extend{def supports_window_functions?; true end}
210
210
  @c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :limit=>10
211
211
  @c1.filter(:tags=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.must_equal 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL) AND ((albums_artists.b1, albums_artists.b2, tags.id) IN (SELECT b, c, d FROM (SELECT albums_artists.b1 AS b, albums_artists.b2 AS c, tags.id AS d, row_number() OVER (PARTITION BY albums_artists.b1, albums_artists.b2) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2))) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 1))))'
212
212
  end
213
213
 
214
214
  it "should allowing filtering by many_through_many associations with :limit and :conditions" do
215
- def (@c2.dataset).supports_window_functions?; true end
215
+ @c2.dataset = @c2.dataset.with_extend{def supports_window_functions?; true end}
216
216
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}, :limit=>10
217
217
  @c1.filter(:tags=>@c2.load(:id=>1234)).sql.must_equal "SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (albums_artists.artist_id IS NOT NULL) AND ((albums_artists.artist_id, tags.id) IN (SELECT b, c FROM (SELECT albums_artists.artist_id AS b, tags.id AS c, row_number() OVER (PARTITION BY albums_artists.artist_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 1234))))"
218
218
  end
219
219
 
220
220
  it "should allowing filtering by many_through_many associations with :limit and :conditions and composite keys" do
221
- def (@c2.dataset).supports_window_functions?; true end
221
+ @c2.dataset = @c2.dataset.with_extend{def supports_window_functions?; true end}
222
222
  @c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}, :limit=>10
223
223
  @c1.filter(:tags=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.must_equal "SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL) AND ((albums_artists.b1, albums_artists.b2, tags.id) IN (SELECT b, c, d FROM (SELECT albums_artists.b1 AS b, albums_artists.b2 AS c, tags.id AS d, row_number() OVER (PARTITION BY albums_artists.b1, albums_artists.b2) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE (name = 'A')) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tags.id = 1))))"
224
224
  end
@@ -419,7 +419,7 @@ describe Sequel::Model, "many_through_many" do
419
419
  it "should populate cache when accessed" do
420
420
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
421
421
  n = @c1.load(:id => 1234)
422
- n.associations[:tags].must_equal nil
422
+ n.associations[:tags].must_be_nil
423
423
  DB.sqls.must_equal []
424
424
  n.tags.must_equal [@c2.load(:id=>1)]
425
425
  DB.sqls.must_equal ['SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (albums_artists.artist_id = 1234)']
@@ -465,7 +465,7 @@ describe Sequel::Model, "many_through_many" do
465
465
  v.each{|x| model::Foo << x.pk * 20}
466
466
  end
467
467
  end
468
- @c2.dataset._fetch = [{:id=>20}, {:id=>30}]
468
+ @c2.dataset = @c2.dataset.with_fetch([{:id=>20}, {:id=>30}])
469
469
  p = @c1.load(:id=>10, :parent_id=>20)
470
470
  p.tags
471
471
  h.must_equal [400, 600]
@@ -474,7 +474,7 @@ describe Sequel::Model, "many_through_many" do
474
474
 
475
475
  it "should support a :uniq option that removes duplicates from the association" do
476
476
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :uniq=>true
477
- @c2.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
477
+ @c2.dataset = @c2.dataset.with_fetch([{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}])
478
478
  @c1.load(:id=>10).tags.must_equal [@c2.load(:id=>20), @c2.load(:id=>30)]
479
479
  end
480
480
  end
@@ -514,7 +514,7 @@ describe 'Sequel::Plugins::ManyThroughMany::ManyThroughManyAssociationReflection
514
514
  end
515
515
 
516
516
  it "#reciprocal should be nil" do
517
- @ar.reciprocal.must_equal nil
517
+ @ar.reciprocal.must_be_nil
518
518
  end
519
519
  end
520
520
 
@@ -535,7 +535,7 @@ describe "many_through_many eager loading methods" do
535
535
  end
536
536
  class ::Track < Sequel::Model
537
537
  end
538
- Artist.dataset.columns(:id)._fetch = proc do |sql|
538
+ Artist.dataset = Artist.dataset.with_fetch(proc do |sql|
539
539
  h = {:id => 1}
540
540
  if sql =~ /FROM artists LEFT OUTER JOIN albums_artists/
541
541
  h[:tags_id] = 2
@@ -545,9 +545,10 @@ describe "many_through_many eager loading methods" do
545
545
  h[:artists_0_id] = 10 if sql =~ /artists_0\.id AS artists_0_id/
546
546
  end
547
547
  h
548
- end
548
+ end)
549
+ Artist.dataset.columns(:id)
549
550
 
550
- Tag.dataset._fetch = proc do |sql|
551
+ Tag.dataset = Tag.dataset.with_fetch(proc do |sql|
551
552
  h = {:id => 2}
552
553
  if sql =~ /albums_artists.artist_id IN \(([18])\)/
553
554
  h[:x_foreign_key_x] = $1.to_i
@@ -556,19 +557,19 @@ describe "many_through_many eager loading methods" do
556
557
  end
557
558
  h[:tag_id] = h.delete(:id) if sql =~ /albums_artists.artist_id IN \(8\)/
558
559
  h
559
- end
560
+ end)
560
561
 
561
- Album.dataset._fetch = proc do |sql|
562
+ Album.dataset = Album.dataset.with_fetch(proc do |sql|
562
563
  h = {:id => 3}
563
564
  h[:x_foreign_key_x] = 1 if sql =~ /albums_artists.artist_id IN \(1\)/
564
565
  h
565
- end
566
+ end)
566
567
 
567
- Track.dataset._fetch = proc do |sql|
568
+ Track.dataset = Track.dataset.with_fetch(proc do |sql|
568
569
  h = {:id => 4}
569
570
  h[:x_foreign_key_x] = 2 if sql =~ /albums_tags.tag_id IN \(2\)/
570
571
  h
571
- end
572
+ end)
572
573
 
573
574
  @c1 = Artist
574
575
  DB.reset
@@ -654,12 +655,7 @@ describe "many_through_many eager loading methods" do
654
655
  end
655
656
 
656
657
  it "should respect :eager_graph when lazily loading an association" do
657
- Tag.dataset._fetch = {:id=>2, :tracks_id=>4}
658
- Tag.dataset.extend(Module.new {
659
- def columns
660
- [:id]
661
- end
662
- })
658
+ Tag.dataset = Tag.dataset.with_fetch(:id=>2, :tracks_id=>4).with_extend{def columns; [:id] end}
663
659
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_graph=>:tracks
664
660
  a = @c1.load(:id=>1)
665
661
  a.tags
@@ -711,7 +707,7 @@ describe "many_through_many eager loading methods" do
711
707
 
712
708
  it "should respect the :limit option on a many_through_many association" do
713
709
  @c1.many_through_many :first_two_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>2
714
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}]
710
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}])
715
711
  a = @c1.eager(:first_two_tags).all
716
712
  a.must_equal [@c1.load(:id=>1)]
717
713
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -720,7 +716,7 @@ describe "many_through_many eager loading methods" do
720
716
  DB.sqls.length.must_equal 0
721
717
 
722
718
  @c1.many_through_many :first_two_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[1,1]
723
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>6}]
719
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>6}])
724
720
  a = @c1.eager(:first_two_tags).all
725
721
  a.must_equal [@c1.load(:id=>1)]
726
722
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -729,7 +725,7 @@ describe "many_through_many eager loading methods" do
729
725
  DB.sqls.length.must_equal 0
730
726
 
731
727
  @c1.many_through_many :first_two_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1]
732
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>6}, {:x_foreign_key_x=>1, :id=>7}]
728
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>6}, {:x_foreign_key_x=>1, :id=>7}])
733
729
  a = @c1.eager(:first_two_tags).all
734
730
  a.must_equal [@c1.load(:id=>1)]
735
731
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -740,7 +736,7 @@ describe "many_through_many eager loading methods" do
740
736
 
741
737
  it "should respect the :limit option on a many_through_many association using a :ruby strategy" do
742
738
  @c1.many_through_many :first_two_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>2, :eager_limit_strategy=>:ruby
743
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}, {:x_foreign_key_x=>1, :id=>7}]
739
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}, {:x_foreign_key_x=>1, :id=>7}])
744
740
  a = @c1.eager(:first_two_tags).all
745
741
  a.must_equal [@c1.load(:id=>1)]
746
742
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -766,9 +762,8 @@ describe "many_through_many eager loading methods" do
766
762
  end
767
763
 
768
764
  it "should respect the :limit option on a many_through_many association using a :window_function strategy" do
769
- Tag.dataset.meta_def(:supports_window_functions?){true}
770
765
  @c1.many_through_many :first_two_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>2, :order=>:name, :eager_limit_strategy=>:window_function
771
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}]
766
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}]).with_extend{def supports_window_functions?; true end}
772
767
  a = @c1.eager(:first_two_tags).all
773
768
  a.must_equal [@c1.load(:id=>1)]
774
769
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -794,12 +789,11 @@ describe "many_through_many eager loading methods" do
794
789
  end
795
790
 
796
791
  it "should respect the :limit option on a many_through_many association with composite primary keys on the main table" do
797
- Tag.dataset.meta_def(:supports_window_functions?){true}
792
+ @c1.dataset = @c1.dataset.with_fetch([{:id1=>1, :id2=>2}])
793
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}, {:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>6}]).with_extend{def supports_window_functions?; true end}
798
794
  @c1.set_primary_key([:id1, :id2])
799
795
  @c1.columns :id1, :id2
800
796
  @c1.many_through_many :first_two_tags, [[:albums_artists, [:artist_id1, :artist_id2], :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>2, :order=>:name
801
- @c1.dataset._fetch = [{:id1=>1, :id2=>2}]
802
- Tag.dataset._fetch = [{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}, {:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>6}]
803
797
  a = @c1.eager(:first_two_tags).all
804
798
  a.must_equal [@c1.load(:id1=>1, :id2=>2)]
805
799
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -817,12 +811,11 @@ describe "many_through_many eager loading methods" do
817
811
  end
818
812
 
819
813
  it "should respect the :limit option on a many_through_many association with composite primary keys on the main table using a :window_function strategy" do
820
- Tag.dataset.meta_def(:supports_window_functions?){true}
814
+ @c1.dataset = @c1.dataset.with_fetch([{:id1=>1, :id2=>2}])
815
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}, {:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>6}]).with_extend{def supports_window_functions?; true end}
821
816
  @c1.set_primary_key([:id1, :id2])
822
817
  @c1.columns :id1, :id2
823
818
  @c1.many_through_many :first_two_tags, [[:albums_artists, [:artist_id1, :artist_id2], :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>2, :order=>:name, :eager_limit_strategy=>:window_function
824
- @c1.dataset._fetch = [{:id1=>1, :id2=>2}]
825
- Tag.dataset._fetch = [{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}, {:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>6}]
826
819
  a = @c1.eager(:first_two_tags).all
827
820
  a.must_equal [@c1.load(:id1=>1, :id2=>2)]
828
821
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -857,8 +850,7 @@ describe "many_through_many eager loading methods" do
857
850
 
858
851
  it "should respect many_through_many association's :left_primary_key and :right_primary_key options" do
859
852
  @c1.send(:define_method, :yyy){values[:yyy]}
860
- @c1.dataset._fetch = {:id=>1, :yyy=>8}
861
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
853
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1, :yyy=>8).with_extend{def columns; [:id, :yyy] end}
862
854
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:yyy, :right_primary_key=>:tag_id
863
855
  a = @c1.eager(:tags).all
864
856
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
@@ -870,8 +862,7 @@ describe "many_through_many eager loading methods" do
870
862
 
871
863
  it "should handle composite keys" do
872
864
  @c1.send(:define_method, :yyy){values[:yyy]}
873
- @c1.dataset._fetch = {:id=>1, :yyy=>8}
874
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
865
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1, :yyy=>8).with_extend{def columns; [:id, :yyy] end}
875
866
  @c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy]
876
867
  a = @c1.eager(:tags).all
877
868
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
@@ -912,12 +903,12 @@ describe "many_through_many eager loading methods" do
912
903
  end
913
904
 
914
905
  it "should eagerly graph a single many_through_many association using the :window_function strategy" do
915
- def (Tag.dataset).supports_window_functions?() true end
916
- def (Tag.dataset).columns() literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
906
+ Tag.dataset = Tag.dataset.with_extend do
907
+ def supports_window_functions?; true end
908
+ def columns; literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
909
+ end
917
910
  @c1.many_through_many :tags, :clone=>:tags, :limit=>2
918
- ds = @c1.eager_graph_with_options(:tags, :limit_strategy=>true)
919
- ds._fetch = {:id=>1, :tags_id=>2}
920
- a = ds.all
911
+ a = @c1.eager_graph_with_options(:tags, :limit_strategy=>true).with_fetch(:id=>1, :tags_id=>2).all
921
912
  a.must_equal [@c1.load(:id=>1)]
922
913
  DB.sqls.must_equal ['SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN (SELECT id, x_foreign_key_x FROM (SELECT tags.*, albums_artists.artist_id AS x_foreign_key_x, row_number() OVER (PARTITION BY albums_artists.artist_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id)) AS t1 WHERE (x_sequel_row_number_x <= 2)) AS tags ON (tags.x_foreign_key_x = artists.id)']
923
914
  a.first.tags.must_equal [Tag.load(:id=>2)]
@@ -955,10 +946,7 @@ describe "many_through_many eager loading methods" do
955
946
  end
956
947
 
957
948
  it "eager graphing should eliminate duplicates caused by cartesian products" do
958
- ds = @c1.eager_graph(:tags)
959
- # Assume artist has 2 albums each with 2 tags
960
- ds._fetch = [{:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}, {:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}]
961
- a = ds.all
949
+ a = @c1.eager_graph(:tags).with_fetch([{:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}, {:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}]).all
962
950
  a.must_equal [@c1.load(:id=>1)]
963
951
  DB.sqls.must_equal ['SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id)']
964
952
  a.first.tags.must_equal [Tag.load(:id=>2), Tag.load(:id=>3)]
@@ -1001,9 +989,7 @@ describe "many_through_many eager loading methods" do
1001
989
  end
1002
990
 
1003
991
  it "should handle no associated records when eagerly graphing a single many_through_many association" do
1004
- ds = @c1.eager_graph(:tags)
1005
- ds._fetch = {:id=>1, :tags_id=>nil}
1006
- a = ds.all
992
+ a = @c1.eager_graph(:tags).with_fetch(:id=>1, :tags_id=>nil).all
1007
993
  a.must_equal [@c1.load(:id=>1)]
1008
994
  DB.sqls.must_equal ['SELECT artists.id, tags.id AS tags_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id)']
1009
995
  a.first.tags.must_equal []
@@ -1011,9 +997,7 @@ describe "many_through_many eager loading methods" do
1011
997
  end
1012
998
 
1013
999
  it "should handle no associated records when eagerly graphing multiple many_through_many associations" do
1014
- ds = @c1.eager_graph(:tags, :albums)
1015
- ds._fetch = [{:id=>1, :tags_id=>nil, :albums_0_id=>3}, {:id=>1, :tags_id=>2, :albums_0_id=>nil}, {:id=>1, :tags_id=>5, :albums_0_id=>6}, {:id=>7, :tags_id=>nil, :albums_0_id=>nil}]
1016
- a = ds.all
1000
+ a = @c1.eager_graph(:tags, :albums).with_fetch([{:id=>1, :tags_id=>nil, :albums_0_id=>3}, {:id=>1, :tags_id=>2, :albums_0_id=>nil}, {:id=>1, :tags_id=>5, :albums_0_id=>6}, {:id=>7, :tags_id=>nil, :albums_0_id=>nil}]).all
1017
1001
  a.must_equal [@c1.load(:id=>1), @c1.load(:id=>7)]
1018
1002
  DB.sqls.must_equal ['SELECT artists.id, tags.id AS tags_id, albums_0.id AS albums_0_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) LEFT OUTER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.artist_id = artists.id) LEFT OUTER JOIN albums AS albums_0 ON (albums_0.id = albums_artists_0.album_id)']
1019
1003
  a.first.tags.must_equal [Tag.load(:id=>2), Tag.load(:id=>5)]
@@ -1024,9 +1008,7 @@ describe "many_through_many eager loading methods" do
1024
1008
  end
1025
1009
 
1026
1010
  it "should handle missing associated records when cascading eager graphing for associations of associated models" do
1027
- ds = @c1.eager_graph(:tags=>:tracks)
1028
- ds._fetch = [{:id=>1, :tags_id=>2, :tracks_id=>4}, {:id=>1, :tags_id=>3, :tracks_id=>nil}, {:id=>2, :tags_id=>nil, :tracks_id=>nil}]
1029
- a = ds.all
1011
+ a = @c1.eager_graph(:tags=>:tracks).with_fetch([{:id=>1, :tags_id=>2, :tracks_id=>4}, {:id=>1, :tags_id=>3, :tracks_id=>nil}, {:id=>2, :tags_id=>nil, :tracks_id=>nil}]).all
1030
1012
  a.must_equal [@c1.load(:id=>1), @c1.load(:id=>2)]
1031
1013
  DB.sqls.must_equal ['SELECT artists.id, tags.id AS tags_id, tracks.id AS tracks_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id) LEFT OUTER JOIN albums_tags AS albums_tags_0 ON (albums_tags_0.tag_id = tags.id) LEFT OUTER JOIN albums AS albums_0 ON (albums_0.id = albums_tags_0.album_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums_0.id)']
1032
1014
  a.last.tags.must_equal []
@@ -1039,11 +1021,9 @@ describe "many_through_many eager loading methods" do
1039
1021
 
1040
1022
  it "eager graphing should respect :left_primary_key and :right_primary_key options" do
1041
1023
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:yyy, :right_primary_key=>:tag_id
1042
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
1043
- Tag.dataset.meta_def(:columns){[:id, :tag_id]}
1044
- ds = @c1.eager_graph(:tags)
1045
- ds._fetch = {:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4}
1046
- a = ds.all
1024
+ @c1.dataset = @c1.dataset.with_extend{def columns; [:id, :yyy] end}
1025
+ Tag.dataset = Tag.dataset.with_extend{def columns; [:id, :tag_id] end}
1026
+ a = @c1.eager_graph(:tags).with_fetch(:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4).all
1047
1027
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
1048
1028
  DB.sqls.must_equal ['SELECT artists.id, artists.yyy, tags.id AS tags_id, tags.tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.yyy) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.tag_id = albums_tags.tag_id)']
1049
1029
  a.first.tags.must_equal [Tag.load(:id=>2, :tag_id=>4)]
@@ -1052,11 +1032,9 @@ describe "many_through_many eager loading methods" do
1052
1032
 
1053
1033
  it "eager graphing should respect composite keys" do
1054
1034
  @c1.many_through_many :tags, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:id, :tag_id], :left_primary_key=>[:id, :yyy]
1055
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
1056
- Tag.dataset.meta_def(:columns){[:id, :tag_id]}
1057
- ds = @c1.eager_graph(:tags)
1058
- ds._fetch = {:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4}
1059
- a = ds.all
1035
+ @c1.dataset = @c1.dataset.with_extend{def columns; [:id, :yyy] end}
1036
+ Tag.dataset = Tag.dataset.with_extend{def columns; [:id, :tag_id] end}
1037
+ a = @c1.eager_graph(:tags).with_fetch(:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4).all
1060
1038
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
1061
1039
  DB.sqls.must_equal ['SELECT artists.id, artists.yyy, tags.id AS tags_id, tags.tag_id FROM artists LEFT OUTER JOIN albums_artists ON ((albums_artists.b1 = artists.id) AND (albums_artists.b2 = artists.yyy)) LEFT OUTER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) LEFT OUTER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) LEFT OUTER JOIN tags ON ((tags.id = albums_tags.g1) AND (tags.tag_id = albums_tags.g2))']
1062
1040
  a.first.tags.must_equal [Tag.load(:id=>2, :tag_id=>4)]
@@ -1065,9 +1043,7 @@ describe "many_through_many eager loading methods" do
1065
1043
 
1066
1044
  it "should respect the association's :graph_select option" do
1067
1045
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :graph_select=>:b
1068
- ds = @c1.eager_graph(:tags)
1069
- ds._fetch = {:id=>1, :b=>2}
1070
- a = ds.all
1046
+ a = @c1.eager_graph(:tags).with_fetch(:id=>1, :b=>2).all
1071
1047
  a.must_equal [@c1.load(:id=>1)]
1072
1048
  DB.sqls.must_equal ['SELECT artists.id, tags.b FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags ON (tags.id = albums_tags.tag_id)']
1073
1049
  a.first.tags.must_equal [Tag.load(:b=>2)]
@@ -1216,8 +1192,7 @@ describe Sequel::Model, "one_through_many" do
1216
1192
  end
1217
1193
  @c1 = Artist
1218
1194
  @c2 = Tag
1219
- @dataset = @c2.dataset
1220
- @dataset._fetch = {:id=>1}
1195
+ @dataset = @c2.dataset = @c2.dataset.with_fetch(:id=>1)
1221
1196
  DB.reset
1222
1197
  end
1223
1198
  after do
@@ -1227,8 +1202,8 @@ describe Sequel::Model, "one_through_many" do
1227
1202
 
1228
1203
  it "should support using a custom :left_primary_key option when eager loading many_to_many associations" do
1229
1204
  @c1.send(:define_method, :id3){id*3}
1230
- @c1.dataset._fetch = {:id=>1}
1231
- @c2.dataset._fetch = {:id=>4, :x_foreign_key_x=>3}
1205
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1)
1206
+ @c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>3)
1232
1207
  @c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:id3
1233
1208
  a = @c1.eager(:tag).all
1234
1209
  a.must_equal [@c1.load(:id => 1)]
@@ -1238,8 +1213,8 @@ describe Sequel::Model, "one_through_many" do
1238
1213
  end
1239
1214
 
1240
1215
  it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup" do
1241
- @c1.dataset._fetch = {:id=>1}
1242
- @c2.dataset._fetch = {:id=>4, :x_foreign_key_x=>1}
1216
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1)
1217
+ @c2.dataset = @c2.dataset.with_fetch(:id=>4, :x_foreign_key_x=>1)
1243
1218
  @c1.one_through_many :tag, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_loading_predicate_key=>Sequel./(:albums_artists__artist_id, 3)
1244
1219
  a = @c1.eager(:tag).all
1245
1220
  a.must_equal [@c1.load(:id => 1)]
@@ -1348,25 +1323,25 @@ describe Sequel::Model, "one_through_many" do
1348
1323
  end
1349
1324
 
1350
1325
  it "should allowing filtering by one_through_many associations with :order" do
1351
- def (@c2.dataset).supports_distinct_on?; true end
1326
+ @c2.dataset = @c2.dataset.with_extend{def supports_distinct_on?; true end}
1352
1327
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :order=>:name
1353
1328
  @c1.filter(:tag=>@c2.load(:id=>1234)).sql.must_equal 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((albums_artists.artist_id IS NOT NULL) AND ((albums_artists.artist_id, tags.id) IN (SELECT DISTINCT ON (albums_artists.artist_id) albums_artists.artist_id, tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) ORDER BY albums_artists.artist_id, name)) AND (tags.id = 1234))))'
1354
1329
  end
1355
1330
 
1356
1331
  it "should allowing filtering by one_through_many associations with :order and composite keys" do
1357
- def (@c2.dataset).supports_distinct_on?; true end
1332
+ @c2.dataset = @c2.dataset.with_extend{def supports_distinct_on?; true end}
1358
1333
  @c1.one_through_many :tag, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :order=>:name
1359
1334
  @c1.filter(:tag=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.must_equal 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL) AND ((albums_artists.b1, albums_artists.b2, tags.id) IN (SELECT DISTINCT ON (albums_artists.b1, albums_artists.b2) albums_artists.b1, albums_artists.b2, tags.id FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) ORDER BY albums_artists.b1, albums_artists.b2, name)) AND (tags.id = 1))))'
1360
1335
  end
1361
1336
 
1362
1337
  it "should allowing filtering by one_through_many associations with :order and :conditions" do
1363
- def (@c2.dataset).supports_distinct_on?; true end
1338
+ @c2.dataset = @c2.dataset.with_extend{def supports_distinct_on?; true end}
1364
1339
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:name=>'A'}, :order=>:name
1365
1340
  @c1.filter(:tag=>@c2.load(:id=>1234)).sql.must_equal "SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((name = 'A') AND (albums_artists.artist_id IS NOT NULL) AND ((albums_artists.artist_id, tags.id) IN (SELECT DISTINCT ON (albums_artists.artist_id) albums_artists.artist_id, tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (name = 'A') ORDER BY albums_artists.artist_id, name)) AND (tags.id = 1234))))"
1366
1341
  end
1367
1342
 
1368
1343
  it "should allowing filtering by one_through_many associations with :order and :conditions and composite keys" do
1369
- def (@c2.dataset).supports_distinct_on?; true end
1344
+ @c2.dataset = @c2.dataset.with_extend{def supports_distinct_on?; true end}
1370
1345
  @c1.one_through_many :tag, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy], :conditions=>{:name=>'A'}, :order=>:name
1371
1346
  @c1.filter(:tag=>@c2.load(:id=>1, :h1=>1234, :h2=>85)).sql.must_equal "SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE ((name = 'A') AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL) AND ((albums_artists.b1, albums_artists.b2, tags.id) IN (SELECT DISTINCT ON (albums_artists.b1, albums_artists.b2) albums_artists.b1, albums_artists.b2, tags.id FROM tags INNER JOIN albums_tags ON ((albums_tags.g1 = tags.h1) AND (albums_tags.g2 = tags.h2)) INNER JOIN albums ON ((albums.e1 = albums_tags.f1) AND (albums.e2 = albums_tags.f2)) INNER JOIN albums_artists ON ((albums_artists.c1 = albums.d1) AND (albums_artists.c2 = albums.d2)) WHERE (name = 'A') ORDER BY albums_artists.b1, albums_artists.b2, name)) AND (tags.id = 1))))"
1372
1347
  end
@@ -1562,7 +1537,7 @@ describe Sequel::Model, "one_through_many" do
1562
1537
  it "should populate cache when accessed" do
1563
1538
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
1564
1539
  n = @c1.load(:id => 1234)
1565
- n.associations[:tag].must_equal nil
1540
+ n.associations[:tag].must_be_nil
1566
1541
  DB.sqls.must_equal []
1567
1542
  n.tag.must_equal @c2.load(:id=>1)
1568
1543
  DB.sqls.must_equal ['SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (albums_artists.artist_id = 1234) LIMIT 1']
@@ -1574,7 +1549,7 @@ describe Sequel::Model, "one_through_many" do
1574
1549
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
1575
1550
  n = @c1.load(:id => 1234)
1576
1551
  n.associations[:tag] = nil
1577
- n.tag.must_equal nil
1552
+ n.tag.must_be_nil
1578
1553
  DB.sqls.must_equal []
1579
1554
  end
1580
1555
 
@@ -1608,7 +1583,7 @@ describe Sequel::Model, "one_through_many" do
1608
1583
  model::Foo << v.pk * 20
1609
1584
  end
1610
1585
  end
1611
- @c2.dataset._fetch = [{:id=>20}]
1586
+ @c2.dataset = @c2.dataset.with_fetch(:id=>20)
1612
1587
  p = @c1.load(:id=>10, :parent_id=>20)
1613
1588
  p.tag
1614
1589
  h.must_equal [400]
@@ -1633,7 +1608,7 @@ describe "one_through_many eager loading methods" do
1633
1608
  end
1634
1609
  class ::Track < Sequel::Model
1635
1610
  end
1636
- Artist.dataset.columns(:id)._fetch = proc do |sql|
1611
+ Artist.dataset = Artist.dataset.with_fetch(proc do |sql|
1637
1612
  h = {:id => 1}
1638
1613
  if sql =~ /FROM artists LEFT OUTER JOIN albums_artists/
1639
1614
  h[:tag_id] = 2
@@ -1643,9 +1618,10 @@ describe "one_through_many eager loading methods" do
1643
1618
  h[:artist_id] = 10 if sql =~ /artists_0\.id AS artist_id/
1644
1619
  end
1645
1620
  h
1646
- end
1621
+ end)
1622
+ Artist.dataset.columns(:id)
1647
1623
 
1648
- Tag.dataset._fetch = proc do |sql|
1624
+ Tag.dataset = Tag.dataset.with_fetch(proc do |sql|
1649
1625
  h = {:id => 2}
1650
1626
  if sql =~ /albums_artists.artist_id IN \(([18])\)/
1651
1627
  h[:x_foreign_key_x] = $1.to_i
@@ -1654,19 +1630,19 @@ describe "one_through_many eager loading methods" do
1654
1630
  end
1655
1631
  h[:tag_id] = h.delete(:id) if sql =~ /albums_artists.artist_id IN \(8\)/
1656
1632
  h
1657
- end
1633
+ end)
1658
1634
 
1659
- Album.dataset._fetch = proc do |sql|
1635
+ Album.dataset = Album.dataset.with_fetch(proc do |sql|
1660
1636
  h = {:id => 3}
1661
1637
  h[:x_foreign_key_x] = 1 if sql =~ /albums_artists.artist_id IN \(1\)/
1662
1638
  h
1663
- end
1639
+ end)
1664
1640
 
1665
- Track.dataset._fetch = proc do |sql|
1641
+ Track.dataset = Track.dataset.with_fetch(proc do |sql|
1666
1642
  h = {:id => 4}
1667
1643
  h[:x_foreign_key_x] = 2 if sql =~ /albums_tags.tag_id IN \(2\)/
1668
1644
  h
1669
- end
1645
+ end)
1670
1646
 
1671
1647
  @c1 = Artist
1672
1648
  DB.reset
@@ -1752,12 +1728,7 @@ describe "one_through_many eager loading methods" do
1752
1728
  end
1753
1729
 
1754
1730
  it "should respect :eager_graph when lazily loading an association" do
1755
- Tag.dataset._fetch = {:id=>2, :track_id=>4}
1756
- Tag.dataset.extend(Module.new {
1757
- def columns
1758
- [:id]
1759
- end
1760
- })
1731
+ Tag.dataset = Tag.dataset.with_fetch(:id=>2, :track_id=>4).with_extend{def columns; [:id] end}
1761
1732
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_graph=>:track
1762
1733
  a = @c1.load(:id=>1)
1763
1734
  a.tag
@@ -1809,7 +1780,7 @@ describe "one_through_many eager loading methods" do
1809
1780
 
1810
1781
  it "should respect the :limit option on a one_through_many association" do
1811
1782
  @c1.one_through_many :second_tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1]
1812
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>6}]
1783
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>6}])
1813
1784
  a = @c1.eager(:second_tag).all
1814
1785
  a.must_equal [@c1.load(:id=>1)]
1815
1786
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -1820,7 +1791,7 @@ describe "one_through_many eager loading methods" do
1820
1791
 
1821
1792
  it "should respect the :limit option on a one_through_many association using the :ruby strategy" do
1822
1793
  @c1.one_through_many :second_tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1], :eager_limit_strategy=>:ruby
1823
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5}, {:x_foreign_key_x=>1, :id=>6}]
1794
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5}, {:x_foreign_key_x=>1, :id=>6}])
1824
1795
  a = @c1.eager(:second_tag).all
1825
1796
  a.must_equal [@c1.load(:id=>1)]
1826
1797
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -1830,9 +1801,8 @@ describe "one_through_many eager loading methods" do
1830
1801
  end
1831
1802
 
1832
1803
  it "should eagerly load a single one_through_many association using the :distinct_on strategy" do
1833
- Tag.dataset.meta_def(:supports_distinct_on?){true}
1834
1804
  @c1.one_through_many :second_tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :order=>:name, :eager_limit_strategy=>:distinct_on
1835
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5}]
1805
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5}]).with_extend{def supports_distinct_on?; true end}
1836
1806
  a = @c1.eager(:second_tag).all
1837
1807
  a.must_equal [@c1.load(:id=>1)]
1838
1808
  DB.sqls.must_equal ['SELECT * FROM artists', "SELECT DISTINCT ON (albums_artists.artist_id) tags.*, albums_artists.artist_id AS x_foreign_key_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (albums_artists.artist_id IN (1)) ORDER BY albums_artists.artist_id, name"]
@@ -1841,9 +1811,8 @@ describe "one_through_many eager loading methods" do
1841
1811
  end
1842
1812
 
1843
1813
  it "should eagerly load a single one_through_many association using the :window_function strategy" do
1844
- Tag.dataset.meta_def(:supports_window_functions?){true}
1845
1814
  @c1.one_through_many :second_tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1], :order=>:name, :eager_limit_strategy=>:window_function
1846
- Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5}]
1815
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_x=>1, :id=>5}]).with_extend{def supports_window_functions?; true end}
1847
1816
  a = @c1.eager(:second_tag).all
1848
1817
  a.must_equal [@c1.load(:id=>1)]
1849
1818
  DB.sqls.must_equal ['SELECT * FROM artists',
@@ -1853,15 +1822,12 @@ describe "one_through_many eager loading methods" do
1853
1822
  end
1854
1823
 
1855
1824
  it "should respect the :limit option on a one_through_many association with composite primary keys on the main table" do
1856
- Tag.dataset.meta_def(:supports_window_functions?){true}
1857
1825
  @c1.set_primary_key([:id1, :id2])
1858
1826
  @c1.columns :id1, :id2
1859
1827
 
1860
1828
  @c1.one_through_many :second_tag, [[:albums_artists, [:artist_id1, :artist_id2], :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1], :order=>:name
1861
- ds = @c1.eager(:second_tag)
1862
- ds._fetch = {:id1=>1, :id2=>2}
1863
- Tag.dataset._fetch = [{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}]
1864
- a = ds.all
1829
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}]).with_extend{def supports_window_functions?; true end}
1830
+ a = @c1.eager(:second_tag).with_fetch(:id1=>1, :id2=>2).all
1865
1831
  a.must_equal [@c1.load(:id1=>1, :id2=>2)]
1866
1832
  DB.sqls.must_equal ['SELECT * FROM artists',
1867
1833
  'SELECT * FROM (SELECT tags.*, albums_artists.artist_id1 AS x_foreign_key_0_x, albums_artists.artist_id2 AS x_foreign_key_1_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((1 = albums_artists.artist_id1) AND (2 = albums_artists.artist_id2)) ORDER BY name LIMIT 1 OFFSET 1) AS t1']
@@ -1870,15 +1836,12 @@ describe "one_through_many eager loading methods" do
1870
1836
  end
1871
1837
 
1872
1838
  it "should respect the :limit option on a one_through_many association with composite primary keys on the main table using a :window_function strategy" do
1873
- Tag.dataset.meta_def(:supports_window_functions?){true}
1874
1839
  @c1.set_primary_key([:id1, :id2])
1875
1840
  @c1.columns :id1, :id2
1876
1841
 
1877
1842
  @c1.one_through_many :second_tag, [[:albums_artists, [:artist_id1, :artist_id2], :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag, :limit=>[nil,1], :order=>:name, :eager_limit_strategy=>:window_function
1878
- ds = @c1.eager(:second_tag)
1879
- ds._fetch = {:id1=>1, :id2=>2}
1880
- Tag.dataset._fetch = [{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}]
1881
- a = ds.all
1843
+ Tag.dataset = Tag.dataset.with_fetch([{:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>2, :id=>5}]).with_extend{def supports_window_functions?; true end}
1844
+ a = @c1.eager(:second_tag).with_fetch(:id1=>1, :id2=>2).all
1882
1845
  a.must_equal [@c1.load(:id1=>1, :id2=>2)]
1883
1846
  DB.sqls.must_equal ['SELECT * FROM artists',
1884
1847
  'SELECT * FROM (SELECT tags.*, albums_artists.artist_id1 AS x_foreign_key_0_x, albums_artists.artist_id2 AS x_foreign_key_1_x, row_number() OVER (PARTITION BY albums_artists.artist_id1, albums_artists.artist_id2 ORDER BY name) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE ((albums_artists.artist_id1, albums_artists.artist_id2) IN ((1, 2)))) AS t1 WHERE (x_sequel_row_number_x = 2)']
@@ -1904,8 +1867,7 @@ describe "one_through_many eager loading methods" do
1904
1867
 
1905
1868
  it "should respect one_through_many association's :left_primary_key and :right_primary_key options" do
1906
1869
  @c1.send(:define_method, :yyy){values[:yyy]}
1907
- @c1.dataset._fetch = {:id=>1, :yyy=>8}
1908
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
1870
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1, :yyy=>8).with_extend{def columns; [:id, :yyy] end}
1909
1871
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:yyy, :right_primary_key=>:tag_id
1910
1872
  a = @c1.eager(:tag).all
1911
1873
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
@@ -1917,8 +1879,7 @@ describe "one_through_many eager loading methods" do
1917
1879
 
1918
1880
  it "should handle composite keys" do
1919
1881
  @c1.send(:define_method, :yyy){values[:yyy]}
1920
- @c1.dataset._fetch = {:id=>1, :yyy=>8}
1921
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
1882
+ @c1.dataset = @c1.dataset.with_fetch(:id=>1, :yyy=>8).with_extend{def columns; [:id, :yyy] end}
1922
1883
  @c1.one_through_many :tag, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:h1, :h2], :left_primary_key=>[:id, :yyy]
1923
1884
  a = @c1.eager(:tag).all
1924
1885
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
@@ -1951,10 +1912,8 @@ describe "one_through_many eager loading methods" do
1951
1912
  end
1952
1913
 
1953
1914
  it "should eagerly graph a single one_through_many association using the :distinct_on strategy" do
1954
- def (Tag.dataset).supports_distinct_on?() true end
1955
- ds = @c1.eager_graph_with_options(:tag, :limit_strategy=>true)
1956
- ds._fetch = {:id=>1, :tag_id=>2}
1957
- a = ds.all
1915
+ Tag.dataset = Tag.dataset.with_extend{def supports_distinct_on?; true end}
1916
+ a = @c1.eager_graph_with_options(:tag, :limit_strategy=>true).with_fetch(:id=>1, :tag_id=>2).all
1958
1917
  a.must_equal [@c1.load(:id=>1)]
1959
1918
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN (SELECT DISTINCT ON (albums_artists.artist_id) tags.*, albums_artists.artist_id AS x_foreign_key_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) ORDER BY albums_artists.artist_id) AS tag ON (tag.x_foreign_key_x = artists.id)']
1960
1919
  a.first.tag.must_equal Tag.load(:id=>2)
@@ -1962,11 +1921,11 @@ describe "one_through_many eager loading methods" do
1962
1921
  end
1963
1922
 
1964
1923
  it "should eagerly graph a single one_through_many association using the :window_function strategy" do
1965
- def (Tag.dataset).supports_window_functions?() true end
1966
- def (Tag.dataset).columns() literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
1967
- ds = @c1.eager_graph_with_options(:tag, :limit_strategy=>true)
1968
- ds._fetch = {:id=>1, :tag_id=>2}
1969
- a = ds.all
1924
+ Tag.dataset = Tag.dataset.with_extend do
1925
+ def supports_window_functions?; true end
1926
+ def columns; literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
1927
+ end
1928
+ a = @c1.eager_graph_with_options(:tag, :limit_strategy=>true).with_fetch(:id=>1, :tag_id=>2).all
1970
1929
  a.must_equal [@c1.load(:id=>1)]
1971
1930
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN (SELECT id, x_foreign_key_x FROM (SELECT tags.*, albums_artists.artist_id AS x_foreign_key_x, row_number() OVER (PARTITION BY albums_artists.artist_id) AS x_sequel_row_number_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id)) AS t1 WHERE (x_sequel_row_number_x = 1)) AS tag ON (tag.x_foreign_key_x = artists.id)']
1972
1931
  a.first.tag.must_equal Tag.load(:id=>2)
@@ -2014,9 +1973,7 @@ describe "one_through_many eager loading methods" do
2014
1973
  end
2015
1974
 
2016
1975
  it "should eager graph a self_referential association" do
2017
- ds = @c1.eager_graph(:tag, :artist)
2018
- ds._fetch = {:id=>1, :tag_id=>2, :artist_id=>10}
2019
- a = ds.all
1976
+ a = @c1.eager_graph(:tag, :artist).with_fetch(:id=>1, :tag_id=>2, :artist_id=>10).all
2020
1977
  a.must_equal [@c1.load(:id=>1)]
2021
1978
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id, artist.id AS artist_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) LEFT OUTER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.artist_id = artists.id) LEFT OUTER JOIN albums AS albums_0 ON (albums_0.id = albums_artists_0.album_id) LEFT OUTER JOIN albums_artists AS albums_artists_1 ON (albums_artists_1.album_id = albums_0.id) LEFT OUTER JOIN artists AS artist ON (artist.id = albums_artists_1.artist_id)']
2022
1979
  a = a.first
@@ -2037,48 +1994,40 @@ describe "one_through_many eager loading methods" do
2037
1994
  end
2038
1995
 
2039
1996
  it "should handle no associated records when eagerly graphing a single one_through_many association" do
2040
- ds = @c1.eager_graph(:tag)
2041
- ds._fetch = {:id=>1, :tag_id=>nil}
2042
- a = ds.all
1997
+ a = @c1.eager_graph(:tag).with_fetch(:id=>1, :tag_id=>nil).all
2043
1998
  a.must_equal [@c1.load(:id=>1)]
2044
1999
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id)']
2045
- a.first.tag.must_equal nil
2000
+ a.first.tag.must_be_nil
2046
2001
  DB.sqls.length.must_equal 0
2047
2002
  end
2048
2003
 
2049
2004
  it "should handle no associated records when eagerly graphing multiple one_through_many associations" do
2050
- ds = @c1.eager_graph(:tag, :album)
2051
- ds._fetch = [{:id=>1, :tag_id=>5, :album_id=>6}, {:id=>7, :tag_id=>nil, :albums_0_id=>nil}]
2052
- a = ds.all
2005
+ a = @c1.eager_graph(:tag, :album).with_fetch([{:id=>1, :tag_id=>5, :album_id=>6}, {:id=>7, :tag_id=>nil, :albums_0_id=>nil}]).all
2053
2006
  a.must_equal [@c1.load(:id=>1), @c1.load(:id=>7)]
2054
2007
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id, album.id AS album_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) LEFT OUTER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.artist_id = artists.id) LEFT OUTER JOIN albums AS album ON (album.id = albums_artists_0.album_id)']
2055
2008
  a.first.tag.must_equal Tag.load(:id=>5)
2056
2009
  a.first.album.must_equal Album.load(:id=>6)
2057
- a.last.tag.must_equal nil
2058
- a.last.album.must_equal nil
2010
+ a.last.tag.must_be_nil
2011
+ a.last.album.must_be_nil
2059
2012
  DB.sqls.length.must_equal 0
2060
2013
  end
2061
2014
 
2062
2015
  it "should handle missing associated records when cascading eager graphing for associations of associated models" do
2063
- ds = @c1.eager_graph(:tag=>:track)
2064
- ds._fetch = [{:id=>1, :tag_id=>2, :track_id=>nil}, {:id=>2, :tag_id=>nil, :tracks_id=>nil}]
2065
- a = ds.all
2016
+ a = @c1.eager_graph(:tag=>:track).with_fetch([{:id=>1, :tag_id=>2, :track_id=>nil}, {:id=>2, :tag_id=>nil, :tracks_id=>nil}]).all
2066
2017
  a.must_equal [@c1.load(:id=>1), @c1.load(:id=>2)]
2067
2018
  DB.sqls.must_equal ['SELECT artists.id, tag.id AS tag_id, track.id AS track_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id) LEFT OUTER JOIN albums_tags AS albums_tags_0 ON (albums_tags_0.tag_id = tag.id) LEFT OUTER JOIN albums AS albums_0 ON (albums_0.id = albums_tags_0.album_id) LEFT OUTER JOIN tracks AS track ON (track.album_id = albums_0.id)']
2068
- a.last.tag.must_equal nil
2019
+ a.last.tag.must_be_nil
2069
2020
  a = a.first
2070
2021
  a.tag.must_equal Tag.load(:id=>2)
2071
- a.tag.track.must_equal nil
2022
+ a.tag.track.must_be_nil
2072
2023
  DB.sqls.length.must_equal 0
2073
2024
  end
2074
2025
 
2075
2026
  it "eager graphing should respect :left_primary_key and :right_primary_key options" do
2076
2027
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :left_primary_key=>:yyy, :right_primary_key=>:tag_id
2077
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
2078
- Tag.dataset.meta_def(:columns){[:id, :tag_id]}
2079
- ds = @c1.eager_graph(:tag)
2080
- ds._fetch = {:id=>1, :yyy=>8, :tag_id=>2, :tag_tag_id=>4}
2081
- a = ds.all
2028
+ @c1.dataset = @c1.dataset.with_extend{def columns; [:id, :yyy] end}
2029
+ Tag.dataset = Tag.dataset.with_extend{def columns; [:id, :tag_id] end}
2030
+ a = @c1.eager_graph(:tag).with_fetch(:id=>1, :yyy=>8, :tag_id=>2, :tag_tag_id=>4).all
2082
2031
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
2083
2032
  DB.sqls.must_equal ['SELECT artists.id, artists.yyy, tag.id AS tag_id, tag.tag_id AS tag_tag_id FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.yyy) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.tag_id = albums_tags.tag_id)']
2084
2033
  a.first.tag.must_equal Tag.load(:id=>2, :tag_id=>4)
@@ -2087,11 +2036,9 @@ describe "one_through_many eager loading methods" do
2087
2036
 
2088
2037
  it "eager graphing should respect composite keys" do
2089
2038
  @c1.one_through_many :tag, [[:albums_artists, [:b1, :b2], [:c1, :c2]], [:albums, [:d1, :d2], [:e1, :e2]], [:albums_tags, [:f1, :f2], [:g1, :g2]]], :right_primary_key=>[:id, :tag_id], :left_primary_key=>[:id, :yyy]
2090
- @c1.dataset.meta_def(:columns){[:id, :yyy]}
2091
- Tag.dataset.meta_def(:columns){[:id, :tag_id]}
2092
- ds = @c1.eager_graph(:tag)
2093
- ds._fetch = {:id=>1, :yyy=>8, :tag_id=>2, :tag_tag_id=>4}
2094
- a = ds.all
2039
+ @c1.dataset = @c1.dataset.with_extend{def columns; [:id, :yyy] end}
2040
+ Tag.dataset = Tag.dataset.with_extend{def columns; [:id, :tag_id] end}
2041
+ a = @c1.eager_graph(:tag).with_fetch(:id=>1, :yyy=>8, :tag_id=>2, :tag_tag_id=>4).all
2095
2042
  a.must_equal [@c1.load(:id=>1, :yyy=>8)]
2096
2043
  DB.sqls.must_equal ['SELECT artists.id, artists.yyy, tag.id AS tag_id, tag.tag_id AS tag_tag_id FROM artists LEFT OUTER JOIN albums_artists ON ((albums_artists.b1 = artists.id) AND (albums_artists.b2 = artists.yyy)) LEFT OUTER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) LEFT OUTER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) LEFT OUTER JOIN tags AS tag ON ((tag.id = albums_tags.g1) AND (tag.tag_id = albums_tags.g2))']
2097
2044
  a.first.tag.must_equal Tag.load(:id=>2, :tag_id=>4)
@@ -2100,9 +2047,7 @@ describe "one_through_many eager loading methods" do
2100
2047
 
2101
2048
  it "should respect the association's :graph_select option" do
2102
2049
  @c1.one_through_many :tag, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :graph_select=>:b
2103
- ds = @c1.eager_graph(:tag)
2104
- ds._fetch = {:id=>1, :b=>2}
2105
- a = ds.all
2050
+ a = @c1.eager_graph(:tag).with_fetch(:id=>1, :b=>2).all
2106
2051
  a.must_equal [@c1.load(:id=>1)]
2107
2052
  DB.sqls.must_equal ['SELECT artists.id, tag.b FROM artists LEFT OUTER JOIN albums_artists ON (albums_artists.artist_id = artists.id) LEFT OUTER JOIN albums ON (albums.id = albums_artists.album_id) LEFT OUTER JOIN albums_tags ON (albums_tags.album_id = albums.id) LEFT OUTER JOIN tags AS tag ON (tag.id = albums_tags.tag_id)']
2108
2053
  a.first.tag.must_equal Tag.load(:b=>2)