sequel 3.21.0 → 3.36.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 (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -8,15 +8,13 @@ describe Sequel::Model, "many_through_many" do
8
8
  plugin :many_through_many
9
9
  end
10
10
  class ::Tag < Sequel::Model
11
+ columns :id, :h1, :h2
11
12
  end
12
- MODEL_DB.reset
13
13
  @c1 = Artist
14
14
  @c2 = Tag
15
15
  @dataset = @c2.dataset
16
- def @dataset.fetch_rows(sql)
17
- @db << sql
18
- yield({:id=>1})
19
- end
16
+ @dataset._fetch = {:id=>1}
17
+ MODEL_DB.reset
20
18
  end
21
19
  after do
22
20
  Object.send(:remove_const, :Artist)
@@ -24,16 +22,20 @@ describe Sequel::Model, "many_through_many" do
24
22
  end
25
23
 
26
24
  it "should default to associating to other models in the same scope" do
27
- class ::AssociationModuleTest
28
- class Artist < Sequel::Model
29
- plugin :many_through_many
30
- many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
31
- end
32
- class Tag < Sequel::Model
25
+ begin
26
+ class ::AssociationModuleTest
27
+ class Artist < Sequel::Model
28
+ plugin :many_through_many
29
+ many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
30
+ end
31
+ class Tag < Sequel::Model
32
+ end
33
33
  end
34
- end
35
-
36
- ::AssociationModuleTest::Artist.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag
34
+
35
+ ::AssociationModuleTest::Artist.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag
36
+ ensure
37
+ Object.send(:remove_const, :AssociationModuleTest)
38
+ end
37
39
  end
38
40
 
39
41
  it "should raise an error if in invalid form of through is used" do
@@ -45,9 +47,7 @@ describe Sequel::Model, "many_through_many" do
45
47
  it "should allow only two arguments with the :through option" do
46
48
  @c1.many_through_many :tags, :through=>[[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
47
49
  n = @c1.load(:id => 1234)
48
- a = n.tags_dataset
49
- a.should be_a_kind_of(Sequel::Dataset)
50
- a.sql.should == '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) AND (albums_artists.artist_id = 1234))'
50
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234))'
51
51
  n.tags.should == [@c2.load(:id=>1)]
52
52
  end
53
53
 
@@ -55,18 +55,14 @@ describe Sequel::Model, "many_through_many" do
55
55
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
56
56
  @c1.many_through_many :other_tags, :clone=>:tags
57
57
  n = @c1.load(:id => 1234)
58
- a = n.other_tags_dataset
59
- a.should be_a_kind_of(Sequel::Dataset)
60
- a.sql.should == '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) AND (albums_artists.artist_id = 1234))'
58
+ n.other_tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234))'
61
59
  n.tags.should == [@c2.load(:id=>1)]
62
60
  end
63
61
 
64
62
  it "should use join tables given" do
65
63
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
66
64
  n = @c1.load(:id => 1234)
67
- a = n.tags_dataset
68
- a.should be_a_kind_of(Sequel::Dataset)
69
- a.sql.should == '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) AND (albums_artists.artist_id = 1234))'
65
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234))'
70
66
  n.tags.should == [@c2.load(:id=>1)]
71
67
  end
72
68
 
@@ -75,9 +71,7 @@ describe Sequel::Model, "many_through_many" do
75
71
  end
76
72
  @c1.many_through_many :albums, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id], [:artists, :id, :id], [:albums_artists, :artist_id, :album_id]]
77
73
  n = @c1.load(:id => 1234)
78
- a = n.albums_dataset
79
- a.should be_a_kind_of(Sequel::Dataset)
80
- a.sql.should == 'SELECT albums.* FROM albums INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) INNER JOIN artists ON (artists.id = albums_artists.artist_id) INNER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.artist_id = artists.id) INNER JOIN albums AS albums_0 ON (albums_0.id = albums_artists_0.album_id) INNER JOIN albums_artists AS albums_artists_1 ON ((albums_artists_1.album_id = albums_0.id) AND (albums_artists_1.artist_id = 1234))'
74
+ n.albums_dataset.sql.should == 'SELECT albums.* FROM albums INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) INNER JOIN artists ON (artists.id = albums_artists.artist_id) INNER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.artist_id = artists.id) INNER JOIN albums AS albums_0 ON (albums_0.id = albums_artists_0.album_id) INNER JOIN albums_artists AS albums_artists_1 ON ((albums_artists_1.album_id = albums_0.id) AND (albums_artists_1.artist_id = 1234))'
81
75
  n.albums.should == [Album.load(:id=>1, :x=>1)]
82
76
  Object.send(:remove_const, :Album)
83
77
  end
@@ -85,9 +79,7 @@ describe Sequel::Model, "many_through_many" do
85
79
  it "should use explicit class if given" do
86
80
  @c1.many_through_many :albums_tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :class=>Tag
87
81
  n = @c1.load(:id => 1234)
88
- a = n.albums_tags_dataset
89
- a.should be_a_kind_of(Sequel::Dataset)
90
- a.sql.should == '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) AND (albums_artists.artist_id = 1234))'
82
+ n.albums_tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234))'
91
83
  n.albums_tags.should == [@c2.load(:id=>1)]
92
84
  end
93
85
 
@@ -95,9 +87,7 @@ describe Sequel::Model, "many_through_many" do
95
87
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :right_primary_key=>:tag_id, :left_primary_key=>:yyy
96
88
  n = @c1.load(:id => 1234)
97
89
  n.yyy = 85
98
- a = n.tags_dataset
99
- a.should be_a_kind_of(Sequel::Dataset)
100
- a.sql.should == 'SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.tag_id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id = 85))'
90
+ n.tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.tag_id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id = 85))'
101
91
  n.tags.should == [@c2.load(:id=>1)]
102
92
  end
103
93
 
@@ -105,61 +95,123 @@ describe Sequel::Model, "many_through_many" do
105
95
  @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]
106
96
  n = @c1.load(:id => 1234)
107
97
  n.yyy = 85
108
- a = n.tags_dataset
109
- a.should be_a_kind_of(Sequel::Dataset)
110
- a.sql.should == 'SELECT tags.* 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) AND (albums_artists.b1 = 1234) AND (albums_artists.b2 = 85))'
98
+ n.tags_dataset.sql.should == 'SELECT tags.* 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) AND (albums_artists.b1 = 1234) AND (albums_artists.b2 = 85))'
111
99
  n.tags.should == [@c2.load(:id=>1)]
112
100
  end
113
101
 
102
+ it "should allowing filtering by many_through_many associations" do
103
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
104
+ @c1.filter(:tags=>@c2.load(:id=>1234)).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL))))'
105
+ end
106
+
107
+ it "should allowing filtering by many_through_many associations with a single through table" do
108
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id]]
109
+ @c1.filter(:tags=>@c2.load(:id=>1234)).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists WHERE ((albums_artists.album_id = 1234) AND (albums_artists.artist_id IS NOT NULL))))'
110
+ end
111
+
112
+ it "should allowing filtering by many_through_many associations with aliased tables" do
113
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums_artists, :id, :id], [:albums_artists, :album_id, :tag_id]]
114
+ @c1.filter(:tags=>@c2.load(:id=>1234)).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums_artists AS albums_artists_0 ON (albums_artists_0.id = albums_artists.album_id) INNER JOIN albums_artists AS albums_artists_1 ON (albums_artists_1.album_id = albums_artists_0.id) WHERE ((albums_artists_1.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL))))'
115
+ end
116
+
117
+ it "should allowing filtering by many_through_many associations with composite keys" do
118
+ @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]
119
+ @c1.filter(:tags=>@c2.load(:h1=>1234, :h2=>85)).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
120
+ end
121
+
122
+ it "should allowing excluding by many_through_many associations" do
123
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
124
+ @c1.exclude(:tags=>@c2.load(:id=>1234)).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id = 1234) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
125
+ end
126
+
127
+ it "should allowing excluding by many_through_many associations with composite keys" do
128
+ @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]
129
+ @c1.exclude(:tags=>@c2.load(:h1=>1234, :h2=>85)).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE ((albums_tags.g1 = 1234) AND (albums_tags.g2 = 85) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
130
+ end
131
+
132
+ it "should allowing filtering by multiple many_through_many associations" do
133
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
134
+ @c1.filter(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL))))'
135
+ end
136
+
137
+ it "should allowing filtering by multiple many_through_many associations with composite keys" do
138
+ @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]
139
+ @c1.filter(:tags=>[@c2.load(:h1=>1234, :h2=>85), @c2.load(:h1=>2345, :h2=>95)]).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
140
+ end
141
+
142
+ it "should allowing excluding by multiple many_through_many associations" do
143
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
144
+ @c1.exclude(:tags=>[@c2.load(:id=>1234), @c2.load(:id=>2345)]).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (1234, 2345)) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
145
+ end
146
+
147
+ it "should allowing excluding by multiple many_through_many associations with composite keys" do
148
+ @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]
149
+ @c1.exclude(:tags=>[@c2.load(:h1=>1234, :h2=>85), @c2.load(:h1=>2345, :h2=>95)]).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN ((1234, 85), (2345, 95))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
150
+ end
151
+
152
+ it "should allowing filtering/excluding many_through_many associations with NULL values" do
153
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
154
+ @c1.filter(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'f\''
155
+ @c1.exclude(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'t\''
156
+ end
157
+
158
+ it "should allowing filtering by many_through_many association datasets" do
159
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
160
+ @c1.filter(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE (artists.id IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_artists.artist_id IS NOT NULL))))'
161
+ end
162
+
163
+ it "should allowing filtering by many_through_many association datasets with composite keys" do
164
+ @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]
165
+ @c1.filter(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE ((artists.id, artists.yyy) IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL))))'
166
+ end
167
+
168
+ it "should allowing excluding by many_through_many association datasets" do
169
+ @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]]
170
+ @c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE ((artists.id NOT IN (SELECT albums_artists.artist_id FROM albums_artists INNER JOIN albums ON (albums.id = albums_artists.album_id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_artists.artist_id IS NOT NULL)))) OR (artists.id IS NULL))'
171
+ end
172
+
173
+ it "should allowing excluding by many_through_many association datasets with composite keys" do
174
+ @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]
175
+ @c1.exclude(:tags=>@c2.filter(:x=>1)).sql.should == 'SELECT * FROM artists WHERE (((artists.id, artists.yyy) NOT IN (SELECT albums_artists.b1, albums_artists.b2 FROM albums_artists INNER JOIN albums ON ((albums.d1 = albums_artists.c1) AND (albums.d2 = albums_artists.c2)) INNER JOIN albums_tags ON ((albums_tags.f1 = albums.e1) AND (albums_tags.f2 = albums.e2)) WHERE (((albums_tags.g1, albums_tags.g2) IN (SELECT tags.h1, tags.h2 FROM tags WHERE ((x = 1) AND (tags.h1 IS NOT NULL) AND (tags.h2 IS NOT NULL)))) AND (albums_artists.b1 IS NOT NULL) AND (albums_artists.b2 IS NOT NULL)))) OR (artists.id IS NULL) OR (artists.yyy IS NULL))'
176
+ end
177
+
114
178
  it "should support a :conditions option" do
115
179
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>{:a=>32}
116
180
  n = @c1.load(:id => 1234)
117
- a = n.tags_dataset
118
- a.should be_a_kind_of(Sequel::Dataset)
119
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (a = 32)'
181
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (a = 32)'
120
182
  n.tags.should == [@c2.load(:id=>1)]
121
183
 
122
184
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :conditions=>['a = ?', 42]
123
185
  n = @c1.load(:id => 1234)
124
- a = n.tags_dataset
125
- a.should be_a_kind_of(Sequel::Dataset)
126
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (a = 42)'
186
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (a = 42)'
127
187
  n.tags.should == [@c2.load(:id=>1)]
128
188
  end
129
189
 
130
190
  it "should support an :order option" do
131
191
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :order=>:blah
132
192
  n = @c1.load(:id => 1234)
133
- a = n.tags_dataset
134
- a.should be_a_kind_of(Sequel::Dataset)
135
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) ORDER BY blah'
193
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) ORDER BY blah'
136
194
  n.tags.should == [@c2.load(:id=>1)]
137
195
  end
138
196
 
139
197
  it "should support an array for the :order option" do
140
198
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :order=>[:blah1, :blah2]
141
199
  n = @c1.load(:id => 1234)
142
- a = n.tags_dataset
143
- a.should be_a_kind_of(Sequel::Dataset)
144
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) ORDER BY blah1, blah2'
200
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) ORDER BY blah1, blah2'
145
201
  n.tags.should == [@c2.load(:id=>1)]
146
202
  end
147
203
 
148
204
  it "should support a select option" do
149
205
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>:blah
150
206
  n = @c1.load(:id => 1234)
151
- a = n.tags_dataset
152
- a.should be_a_kind_of(Sequel::Dataset)
153
- a.sql.should == 'SELECT blah 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) AND (albums_artists.artist_id = 1234))'
207
+ n.tags_dataset.sql.should == 'SELECT blah 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) AND (albums_artists.artist_id = 1234))'
154
208
  n.tags.should == [@c2.load(:id=>1)]
155
209
  end
156
210
 
157
211
  it "should support an array for the select option" do
158
212
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :select=>[:tags.*, :albums__name]
159
213
  n = @c1.load(:id => 1234)
160
- a = n.tags_dataset
161
- a.should be_a_kind_of(Sequel::Dataset)
162
- a.sql.should == 'SELECT tags.*, albums.name 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) AND (albums_artists.artist_id = 1234))'
214
+ n.tags_dataset.sql.should == 'SELECT tags.*, albums.name 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) AND (albums_artists.artist_id = 1234))'
163
215
  n.tags.should == [@c2.load(:id=>1)]
164
216
  end
165
217
 
@@ -167,9 +219,7 @@ describe Sequel::Model, "many_through_many" do
167
219
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]] do |ds| ds.filter(:yyy=>@yyy) end
168
220
  n = @c1.load(:id => 1234)
169
221
  n.yyy = 85
170
- a = n.tags_dataset
171
- a.should be_a_kind_of(Sequel::Dataset)
172
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (yyy = 85)'
222
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (yyy = 85)'
173
223
  n.tags.should == [@c2.load(:id=>1)]
174
224
  end
175
225
 
@@ -177,34 +227,26 @@ describe Sequel::Model, "many_through_many" do
177
227
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :order=>:blah do |ds| ds.filter(:yyy=>@yyy) end
178
228
  n = @c1.load(:id => 1234)
179
229
  n.yyy = 85
180
- a = n.tags_dataset
181
- a.should be_a_kind_of(Sequel::Dataset)
182
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (yyy = 85) ORDER BY blah'
230
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) WHERE (yyy = 85) ORDER BY blah'
183
231
  n.tags.should == [@c2.load(:id=>1)]
184
232
  end
185
233
 
186
234
  it "should support a :dataset option that is used instead of the default" do
187
235
  @c1.many_through_many :tags, [[:a, :b, :c]], :dataset=>proc{Tag.join(:albums_tags, [:tag_id]).join(:albums, [:album_id]).join(:albums_artists, [:album_id]).filter(:albums_artists__artist_id=>id)}
188
236
  n = @c1.load(:id => 1234)
189
- a = n.tags_dataset
190
- a.should be_a_kind_of(Sequel::Dataset)
191
- a.sql.should == 'SELECT tags.* FROM tags INNER JOIN albums_tags USING (tag_id) INNER JOIN albums USING (album_id) INNER JOIN albums_artists USING (album_id) WHERE (albums_artists.artist_id = 1234)'
237
+ n.tags_dataset.sql.should == 'SELECT tags.* FROM tags INNER JOIN albums_tags USING (tag_id) INNER JOIN albums USING (album_id) INNER JOIN albums_artists USING (album_id) WHERE (albums_artists.artist_id = 1234)'
192
238
  n.tags.should == [@c2.load(:id=>1)]
193
239
  end
194
240
 
195
241
  it "should support a :limit option" do
196
242
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :limit=>10
197
243
  n = @c1.load(:id => 1234)
198
- a = n.tags_dataset
199
- a.should be_a_kind_of(Sequel::Dataset)
200
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) LIMIT 10'
244
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) LIMIT 10'
201
245
  n.tags.should == [@c2.load(:id=>1)]
202
246
 
203
247
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :limit=>[10, 10]
204
248
  n = @c1.load(:id => 1234)
205
- a = n.tags_dataset
206
- a.should be_a_kind_of(Sequel::Dataset)
207
- a.sql.should == '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) AND (albums_artists.artist_id = 1234)) LIMIT 10 OFFSET 10'
249
+ n.tags_dataset.sql.should == '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) AND (albums_artists.artist_id = 1234)) LIMIT 10 OFFSET 10'
208
250
  n.tags.should == [@c2.load(:id=>1)]
209
251
  end
210
252
 
@@ -228,7 +270,7 @@ describe Sequel::Model, "many_through_many" do
228
270
  n.tags.should == [@c2.load(:id=>1)]
229
271
  MODEL_DB.sqls.should == ['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) AND (albums_artists.artist_id = 1234))']
230
272
  n.associations[:tags].should == n.tags
231
- MODEL_DB.sqls.length.should == 1
273
+ MODEL_DB.sqls.length.should == 0
232
274
  end
233
275
 
234
276
  it "should use cached instance variable if available" do
@@ -247,7 +289,7 @@ describe Sequel::Model, "many_through_many" do
247
289
  n.tags(true).should == [@c2.load(:id=>1)]
248
290
  MODEL_DB.sqls.should == ['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) AND (albums_artists.artist_id = 1234))']
249
291
  n.associations[:tags].should == n.tags
250
- MODEL_DB.sqls.length.should == 1
292
+ MODEL_DB.sqls.length.should == 0
251
293
  end
252
294
 
253
295
  it "should not add associations methods directly to class" do
@@ -264,18 +306,13 @@ describe Sequel::Model, "many_through_many" do
264
306
  h = []
265
307
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :after_load=>:al
266
308
  @c1.class_eval do
267
- class_variable_set(:@@blah, h)
309
+ self::Foo = h
268
310
  def al(v)
269
- v.each{|x| self.class.send(:class_variable_get, :@@blah) << x.pk * 20}
270
- end
271
- end
272
- @c2.class_eval do
273
- def @dataset.fetch_rows(sql)
274
- yield({:id=>20})
275
- yield({:id=>30})
311
+ v.each{|x| model::Foo << x.pk * 20}
276
312
  end
277
313
  end
278
- p = @c1.load(:id=>10, :parent_id=>20)
314
+ @c2.dataset._fetch = [{:id=>20}, {:id=>30}]
315
+ p = @c1.load(:id=>10, :parent_id=>20)
279
316
  p.tags
280
317
  h.should == [400, 600]
281
318
  p.tags.collect{|a| a.pk}.should == [20, 30]
@@ -284,14 +321,7 @@ describe Sequel::Model, "many_through_many" do
284
321
  it "should support a :uniq option that removes duplicates from the association" do
285
322
  h = []
286
323
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :uniq=>true
287
- @c2.class_eval do
288
- def @dataset.fetch_rows(sql)
289
- yield({:id=>20})
290
- yield({:id=>30})
291
- yield({:id=>20})
292
- yield({:id=>30})
293
- end
294
- end
324
+ @c2.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
295
325
  @c1.load(:id=>10).tags.should == [@c2.load(:id=>20), @c2.load(:id=>30)]
296
326
  end
297
327
  end
@@ -352,57 +382,40 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
352
382
  end
353
383
  class ::Track < Sequel::Model
354
384
  end
355
-
356
- Artist.dataset.extend(Module.new {
357
- def columns
358
- [:id]
385
+ Artist.dataset.columns(:id)._fetch = proc do |sql|
386
+ h = {:id => 1}
387
+ if sql =~ /FROM artists LEFT OUTER JOIN albums_artists/
388
+ h[:tags_id] = 2
389
+ h[:albums_0_id] = 3 if sql =~ /LEFT OUTER JOIN albums AS albums_0/
390
+ h[:tracks_id] = 4 if sql =~ /LEFT OUTER JOIN tracks/
391
+ h[:other_tags_id] = 9 if sql =~ /other_tags\.id AS other_tags_id/
392
+ h[:artists_0_id] = 10 if sql =~ /artists_0\.id AS artists_0_id/
359
393
  end
360
-
361
- def fetch_rows(sql)
362
- @db << sql
363
- h = {:id => 1}
364
- if sql =~ /FROM artists LEFT OUTER JOIN albums_artists/
365
- h[:tags_id] = 2
366
- h[:albums_0_id] = 3 if sql =~ /LEFT OUTER JOIN albums AS albums_0/
367
- h[:tracks_id] = 4 if sql =~ /LEFT OUTER JOIN tracks/
368
- h[:other_tags_id] = 9 if sql =~ /other_tags\.id AS other_tags_id/
369
- h[:artists_0_id] = 10 if sql =~ /artists_0\.id AS artists_0_id/
370
- end
371
- yield h
372
- end
373
- })
374
-
375
- Tag.dataset.extend(Module.new {
376
- def fetch_rows(sql)
377
- @db << sql
378
- h = {:id => 2}
379
- if sql =~ /albums_artists.artist_id IN \(([18])\)/
380
- h.merge!(:x_foreign_key_x=>$1.to_i)
381
- elsif sql =~ /\(\(albums_artists.b1, albums_artists.b2\) IN \(\(1, 8\)\)\)/
382
- h.merge!(:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>8)
383
- end
384
- h[:tag_id] = h.delete(:id) if sql =~ /albums_artists.artist_id IN \(8\)/
385
- yield h
386
- end
387
- })
394
+ h
395
+ end
388
396
 
389
- Album.dataset.extend(Module.new {
390
- def fetch_rows(sql)
391
- @db << sql
392
- h = {:id => 3}
393
- h.merge!(:x_foreign_key_x=>1) if sql =~ /albums_artists.artist_id IN \(1\)/
394
- yield h
397
+ Tag.dataset._fetch = proc do |sql|
398
+ h = {:id => 2}
399
+ if sql =~ /albums_artists.artist_id IN \(([18])\)/
400
+ h[:x_foreign_key_x] = $1.to_i
401
+ elsif sql =~ /\(\(albums_artists.b1, albums_artists.b2\) IN \(\(1, 8\)\)\)/
402
+ h.merge!(:x_foreign_key_0_x=>1, :x_foreign_key_1_x=>8)
395
403
  end
396
- })
404
+ h[:tag_id] = h.delete(:id) if sql =~ /albums_artists.artist_id IN \(8\)/
405
+ h
406
+ end
397
407
 
398
- Track.dataset.extend(Module.new {
399
- def fetch_rows(sql)
400
- @db << sql
401
- h = {:id => 4}
402
- h.merge!(:x_foreign_key_x=>2) if sql =~ /albums_tags.tag_id IN \(2\)/
403
- yield h
404
- end
405
- })
408
+ Album.dataset._fetch = proc do |sql|
409
+ h = {:id => 3}
410
+ h[:x_foreign_key_x] = 1 if sql =~ /albums_artists.artist_id IN \(1\)/
411
+ h
412
+ end
413
+
414
+ Track.dataset._fetch = proc do |sql|
415
+ h = {:id => 4}
416
+ h[:x_foreign_key_x] = 2 if sql =~ /albums_tags.tag_id IN \(2\)/
417
+ h
418
+ end
406
419
 
407
420
  @c1 = Artist
408
421
  MODEL_DB.reset
@@ -416,33 +429,35 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
416
429
  a.should == [@c1.load(:id=>1)]
417
430
  MODEL_DB.sqls.should == ['SELECT * FROM artists', 'SELECT 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) AND (albums_artists.artist_id IN (1)))']
418
431
  a.first.tags.should == [Tag.load(:id=>2)]
419
- MODEL_DB.sqls.length.should == 2
432
+ MODEL_DB.sqls.length.should == 0
420
433
  end
421
434
 
422
435
  it "should eagerly load multiple associations in a single call" do
423
436
  a = @c1.eager(:tags, :albums).all
424
437
  a.should == [@c1.load(:id=>1)]
425
- MODEL_DB.sqls.length.should == 3
426
- MODEL_DB.sqls[0].should == 'SELECT * FROM artists'
427
- MODEL_DB.sqls[1..-1].should(include('SELECT 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) AND (albums_artists.artist_id IN (1)))'))
428
- MODEL_DB.sqls[1..-1].should(include('SELECT albums.*, albums_artists.artist_id AS x_foreign_key_x FROM albums INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id IN (1)))'))
438
+ sqls = MODEL_DB.sqls
439
+ sqls.length.should == 3
440
+ sqls[0].should == 'SELECT * FROM artists'
441
+ sqls[1..-1].should(include('SELECT 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) AND (albums_artists.artist_id IN (1)))'))
442
+ sqls[1..-1].should(include('SELECT albums.*, albums_artists.artist_id AS x_foreign_key_x FROM albums INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id IN (1)))'))
429
443
  a = a.first
430
444
  a.tags.should == [Tag.load(:id=>2)]
431
445
  a.albums.should == [Album.load(:id=>3)]
432
- MODEL_DB.sqls.length.should == 3
446
+ MODEL_DB.sqls.length.should == 0
433
447
  end
434
448
 
435
449
  it "should eagerly load multiple associations in separate" do
436
450
  a = @c1.eager(:tags).eager(:albums).all
437
451
  a.should == [@c1.load(:id=>1)]
438
- MODEL_DB.sqls.length.should == 3
439
- MODEL_DB.sqls[0].should == 'SELECT * FROM artists'
440
- MODEL_DB.sqls[1..-1].should(include('SELECT 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) AND (albums_artists.artist_id IN (1)))'))
441
- MODEL_DB.sqls[1..-1].should(include('SELECT albums.*, albums_artists.artist_id AS x_foreign_key_x FROM albums INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id IN (1)))'))
452
+ sqls = MODEL_DB.sqls
453
+ sqls.length.should == 3
454
+ sqls[0].should == 'SELECT * FROM artists'
455
+ sqls[1..-1].should(include('SELECT 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) AND (albums_artists.artist_id IN (1)))'))
456
+ sqls[1..-1].should(include('SELECT albums.*, albums_artists.artist_id AS x_foreign_key_x FROM albums INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id IN (1)))'))
442
457
  a = a.first
443
458
  a.tags.should == [Tag.load(:id=>2)]
444
459
  a.albums.should == [Album.load(:id=>3)]
445
- MODEL_DB.sqls.length.should == 3
460
+ MODEL_DB.sqls.length.should == 0
446
461
  end
447
462
 
448
463
  it "should allow cascading of eager loading for associations of associated models" do
@@ -454,7 +469,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
454
469
  a = a.first
455
470
  a.tags.should == [Tag.load(:id=>2)]
456
471
  a.tags.first.tracks.should == [Track.load(:id=>4)]
457
- MODEL_DB.sqls.length.should == 3
472
+ MODEL_DB.sqls.length.should == 0
458
473
  end
459
474
 
460
475
  it "should cascade eagerly loading when the :eager association option is used" do
@@ -467,7 +482,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
467
482
  a = a.first
468
483
  a.tags.should == [Tag.load(:id=>2)]
469
484
  a.tags.first.tracks.should == [Track.load(:id=>4)]
470
- MODEL_DB.sqls.length.should == 3
485
+ MODEL_DB.sqls.length.should == 0
471
486
  end
472
487
 
473
488
  it "should respect :eager when lazily loading an association" do
@@ -477,39 +492,20 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
477
492
  MODEL_DB.sqls.should == ['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) AND (albums_artists.artist_id = 1))',
478
493
  'SELECT tracks.*, albums_tags.tag_id AS x_foreign_key_x FROM tracks INNER JOIN albums ON (albums.id = tracks.album_id) INNER JOIN albums_tags ON ((albums_tags.album_id = albums.id) AND (albums_tags.tag_id IN (2)))']
479
494
  a.tags.first.tracks.should == [Track.load(:id=>4)]
480
- MODEL_DB.sqls.length.should == 2
495
+ MODEL_DB.sqls.length.should == 0
481
496
  end
482
497
 
483
498
  it "should cascade eagerly loading when the :eager_graph association option is used" do
484
- Tag.dataset.extend(Module.new {
485
- def columns
486
- [:id]
487
- end
488
- def fetch_rows(sql)
489
- @db << sql
490
- yield({:id=>2, :tracks_id=>4, :x_foreign_key_x=>1})
491
- end
492
- })
493
499
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_graph=>:tracks
494
- a = @c1.eager(:tags).all
495
- a.should == [@c1.load(:id=>1)]
496
- MODEL_DB.sqls.should == ['SELECT * FROM artists',
497
- 'SELECT tags.id, tracks.id AS tracks_id, albums_artists.artist_id AS x_foreign_key_x FROM (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) AND (albums_artists.artist_id IN (1)))) AS tags LEFT OUTER JOIN albums_tags AS albums_tags_0 ON (albums_tags_0.tag_id = tags.id) LEFT OUTER JOIN albums ON (albums.id = albums_tags_0.album_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)']
498
- a = a.first
499
- a.tags.should == [Tag.load(:id=>2)]
500
- a.tags.first.tracks.should == [Track.load(:id=>4)]
501
- MODEL_DB.sqls.length.should == 2
500
+ proc{@c1.eager(:tags).all}.should raise_error(Sequel::Error)
502
501
  end
503
502
 
504
503
  it "should respect :eager_graph when lazily loading an association" do
504
+ Tag.dataset._fetch = {:id=>2, :tracks_id=>4}
505
505
  Tag.dataset.extend(Module.new {
506
506
  def columns
507
507
  [:id]
508
508
  end
509
- def fetch_rows(sql)
510
- @db << sql
511
- yield({:id=>2, :tracks_id=>4})
512
- end
513
509
  })
514
510
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :eager_graph=>:tracks
515
511
  a = @c1.load(:id=>1)
@@ -517,7 +513,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
517
513
  MODEL_DB.sqls.should == [ 'SELECT tags.id, tracks.id AS tracks_id FROM (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) AND (albums_artists.artist_id = 1))) AS tags LEFT OUTER JOIN albums_tags AS albums_tags_0 ON (albums_tags_0.tag_id = tags.id) LEFT OUTER JOIN albums ON (albums.id = albums_tags_0.album_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)']
518
514
  a.tags.should == [Tag.load(:id=>2)]
519
515
  a.tags.first.tracks.should == [Track.load(:id=>4)]
520
- MODEL_DB.sqls.length.should == 1
516
+ MODEL_DB.sqls.length.should == 0
521
517
  end
522
518
 
523
519
  it "should respect :conditions when eagerly loading" do
@@ -527,7 +523,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
527
523
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
528
524
  'SELECT 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) AND (albums_artists.artist_id IN (1))) WHERE (a = 32)']
529
525
  a.first.tags.should == [Tag.load(:id=>2)]
530
- MODEL_DB.sqls.length.should == 2
526
+ MODEL_DB.sqls.length.should == 0
531
527
  end
532
528
 
533
529
  it "should respect :order when eagerly loading" do
@@ -537,7 +533,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
537
533
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
538
534
  'SELECT 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) AND (albums_artists.artist_id IN (1))) ORDER BY blah']
539
535
  a.first.tags.should == [Tag.load(:id=>2)]
540
- MODEL_DB.sqls.length.should == 2
536
+ MODEL_DB.sqls.length.should == 0
541
537
  end
542
538
 
543
539
  it "should use the association's block when eager loading by default" do
@@ -547,7 +543,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
547
543
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
548
544
  'SELECT 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) AND (albums_artists.artist_id IN (1))) WHERE a']
549
545
  a.first.tags.should == [Tag.load(:id=>2)]
550
- MODEL_DB.sqls.length.should == 2
546
+ MODEL_DB.sqls.length.should == 0
551
547
  end
552
548
 
553
549
  it "should use the :eager_block option when eager loading if given" do
@@ -557,7 +553,87 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
557
553
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
558
554
  'SELECT 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) AND (albums_artists.artist_id IN (1))) WHERE b']
559
555
  a.first.tags.should == [Tag.load(:id=>2)]
560
- MODEL_DB.sqls.length.should == 2
556
+ MODEL_DB.sqls.length.should == 0
557
+ end
558
+
559
+ it "should respect the :limit option on a many_through_many association" do
560
+ @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
561
+ Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}, {:x_foreign_key_x=>1, :id=>7}]
562
+ a = @c1.eager(:first_two_tags).all
563
+ a.should == [@c1.load(:id=>1)]
564
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
565
+ 'SELECT 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) AND (albums_artists.artist_id IN (1)))']
566
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
567
+ MODEL_DB.sqls.length.should == 0
568
+
569
+ @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,1]
570
+ a = @c1.eager(:first_two_tags).all
571
+ a.should == [@c1.load(:id=>1)]
572
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
573
+ 'SELECT 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) AND (albums_artists.artist_id IN (1)))']
574
+ a.first.first_two_tags.should == [Tag.load(:id=>6), Tag.load(:id=>7)]
575
+ MODEL_DB.sqls.length.should == 0
576
+ end
577
+
578
+ it "should respect the :limit option on a many_through_many association using a :window_function strategy" do
579
+ Tag.dataset.meta_def(:supports_window_functions?){true}
580
+ @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=>true, :order=>:name
581
+ Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}]
582
+ a = @c1.eager(:first_two_tags).all
583
+ a.should == [@c1.load(:id=>1)]
584
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
585
+ 'SELECT * FROM (SELECT tags.*, albums_artists.artist_id AS x_foreign_key_x, row_number() OVER (PARTITION BY albums_artists.artist_id 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) AND (albums_artists.artist_id IN (1)))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
586
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
587
+ MODEL_DB.sqls.length.should == 0
588
+
589
+ @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,1], :eager_limit_strategy=>true, :order=>:name
590
+ a = @c1.eager(:first_two_tags).all
591
+ a.should == [@c1.load(:id=>1)]
592
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
593
+ 'SELECT * FROM (SELECT tags.*, albums_artists.artist_id AS x_foreign_key_x, row_number() OVER (PARTITION BY albums_artists.artist_id 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) AND (albums_artists.artist_id IN (1)))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
594
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
595
+ MODEL_DB.sqls.length.should == 0
596
+ end
597
+
598
+ 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
599
+ Tag.dataset.meta_def(:supports_window_functions?){true}
600
+ @c1.set_primary_key([:id1, :id2])
601
+ @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, :eager_limit_strategy=>true, :order=>:name
602
+ @c1.dataset._fetch = [{:id1=>1, :id2=>2}]
603
+ 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}]
604
+ a = @c1.eager(:first_two_tags).all
605
+ a.should == [@c1.load(:id1=>1, :id2=>2)]
606
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
607
+ '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) AND ((albums_artists.artist_id1, albums_artists.artist_id2) IN ((1, 2))))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
608
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
609
+ MODEL_DB.sqls.length.should == 0
610
+
611
+ @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,1], :eager_limit_strategy=>true, :order=>:name
612
+ a = @c1.eager(:first_two_tags).all
613
+ a.should == [@c1.load(:id1=>1, :id2=>2)]
614
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
615
+ '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) AND ((albums_artists.artist_id1, albums_artists.artist_id2) IN ((1, 2))))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
616
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
617
+ MODEL_DB.sqls.length.should == 0
618
+ end
619
+
620
+ it "should respect the :limit option on a many_through_many association using a :correlated_subquery strategy" do
621
+ @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=>:correlated_subquery, :order=>:name
622
+ Tag.dataset._fetch = [{:x_foreign_key_x=>1, :id=>5},{:x_foreign_key_x=>1, :id=>6}]
623
+ a = @c1.eager(:first_two_tags).all
624
+ a.should == [@c1.load(:id=>1)]
625
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
626
+ 'SELECT 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) AND (albums_artists.artist_id IN (1))) WHERE (tags.id IN (SELECT t1.id FROM tags AS t1 INNER JOIN albums_tags ON (albums_tags.tag_id = t1.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists AS t2 ON ((t2.album_id = albums.id) AND (t2.artist_id = albums_artists.artist_id)) ORDER BY name LIMIT 2)) ORDER BY name']
627
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
628
+ MODEL_DB.sqls.length.should == 0
629
+
630
+ @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,1], :eager_limit_strategy=>:correlated_subquery, :order=>:name
631
+ a = @c1.eager(:first_two_tags).all
632
+ a.should == [@c1.load(:id=>1)]
633
+ MODEL_DB.sqls.should == ['SELECT * FROM artists',
634
+ 'SELECT 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) AND (albums_artists.artist_id IN (1))) WHERE (tags.id IN (SELECT t1.id FROM tags AS t1 INNER JOIN albums_tags ON (albums_tags.tag_id = t1.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists AS t2 ON ((t2.album_id = albums.id) AND (t2.artist_id = albums_artists.artist_id)) ORDER BY name LIMIT 2 OFFSET 1)) ORDER BY name']
635
+ a.first.first_two_tags.should == [Tag.load(:id=>5), Tag.load(:id=>6)]
636
+ MODEL_DB.sqls.length.should == 0
561
637
  end
562
638
 
563
639
  it "should raise an error when attempting to eagerly load an association with the :allow_eager option set to false" do
@@ -573,47 +649,33 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
573
649
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
574
650
  'SELECT tags.name, 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) AND (albums_artists.artist_id IN (1)))']
575
651
  a.first.tags.should == [Tag.load(:id=>2)]
576
- MODEL_DB.sqls.length.should == 2
652
+ MODEL_DB.sqls.length.should == 0
577
653
  end
578
654
 
579
- it "should respect many_to_many association's :left_primary_key and :right_primary_key options" do
655
+ it "should respect many_through_many association's :left_primary_key and :right_primary_key options" do
580
656
  @c1.send(:define_method, :yyy){values[:yyy]}
581
- @c1.dataset.extend(Module.new {
582
- def columns
583
- [:id, :yyy]
584
- end
585
- def fetch_rows(sql)
586
- @db << sql
587
- yield({:id=>1, :yyy=>8})
588
- end
589
- })
657
+ @c1.dataset._fetch = {:id=>1, :yyy=>8}
658
+ @c1.dataset.meta_def(:columns){[:id, :yyy]}
590
659
  @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
591
660
  a = @c1.eager(:tags).all
592
661
  a.should == [@c1.load(:id=>1, :yyy=>8)]
593
662
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
594
663
  'SELECT tags.*, albums_artists.artist_id AS x_foreign_key_x FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.tag_id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON ((albums_artists.album_id = albums.id) AND (albums_artists.artist_id IN (8)))']
595
664
  a.first.tags.should == [Tag.load(:tag_id=>2)]
596
- MODEL_DB.sqls.length.should == 2
665
+ MODEL_DB.sqls.length.should == 0
597
666
  end
598
667
 
599
668
  it "should handle composite keys" do
600
669
  @c1.send(:define_method, :yyy){values[:yyy]}
601
- @c1.dataset.extend(Module.new {
602
- def columns
603
- [:id, :yyy]
604
- end
605
- def fetch_rows(sql)
606
- @db << sql
607
- yield({:id=>1, :yyy=>8})
608
- end
609
- })
670
+ @c1.dataset._fetch = {:id=>1, :yyy=>8}
671
+ @c1.dataset.meta_def(:columns){[:id, :yyy]}
610
672
  @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]
611
673
  a = @c1.eager(:tags).all
612
674
  a.should == [@c1.load(:id=>1, :yyy=>8)]
613
675
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
614
676
  'SELECT tags.*, albums_artists.b1 AS x_foreign_key_0_x, albums_artists.b2 AS x_foreign_key_1_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) AND ((albums_artists.b1, albums_artists.b2) IN ((1, 8))))']
615
677
  a.first.tags.should == [Tag.load(:id=>2)]
616
- MODEL_DB.sqls.length.should == 2
678
+ MODEL_DB.sqls.length.should == 0
617
679
  end
618
680
 
619
681
  it "should respect :after_load callbacks on associations when eager loading" do
@@ -623,7 +685,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
623
685
  MODEL_DB.sqls.should == ['SELECT * FROM artists',
624
686
  'SELECT 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) AND (albums_artists.artist_id IN (1)))']
625
687
  a.first.tags.should == [Tag.load(:id=>6)]
626
- MODEL_DB.sqls.length.should == 2
688
+ MODEL_DB.sqls.length.should == 0
627
689
  end
628
690
 
629
691
  it "should raise an error if called without a symbol or hash" do
@@ -635,7 +697,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
635
697
  a.should == [@c1.load(:id=>1)]
636
698
  MODEL_DB.sqls.should == ['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)']
637
699
  a.first.tags.should == [Tag.load(:id=>2)]
638
- MODEL_DB.sqls.length.should == 1
700
+ MODEL_DB.sqls.length.should == 0
639
701
  end
640
702
 
641
703
  it "should eagerly graph multiple associations in a single call" do
@@ -645,7 +707,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
645
707
  a = a.first
646
708
  a.tags.should == [Tag.load(:id=>2)]
647
709
  a.albums.should == [Album.load(:id=>3)]
648
- MODEL_DB.sqls.length.should == 1
710
+ MODEL_DB.sqls.length.should == 0
649
711
  end
650
712
 
651
713
  it "should eagerly graph multiple associations in separate calls" do
@@ -655,7 +717,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
655
717
  a = a.first
656
718
  a.tags.should == [Tag.load(:id=>2)]
657
719
  a.albums.should == [Album.load(:id=>3)]
658
- MODEL_DB.sqls.length.should == 1
720
+ MODEL_DB.sqls.length.should == 0
659
721
  end
660
722
 
661
723
  it "should allow cascading of eager graphing for associations of associated models" do
@@ -665,24 +727,18 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
665
727
  a = a.first
666
728
  a.tags.should == [Tag.load(:id=>2)]
667
729
  a.tags.first.tracks.should == [Track.load(:id=>4)]
668
- MODEL_DB.sqls.length.should == 1
730
+ MODEL_DB.sqls.length.should == 0
669
731
  end
670
732
 
671
733
  it "eager graphing should eliminate duplicates caused by cartesian products" do
672
734
  ds = @c1.eager_graph(:tags)
673
- def ds.fetch_rows(sql, &block)
674
- @db << sql
675
- # Assume artist has 2 albums each with 2 tags
676
- yield({:id=>1, :tags_id=>2})
677
- yield({:id=>1, :tags_id=>3})
678
- yield({:id=>1, :tags_id=>2})
679
- yield({:id=>1, :tags_id=>3})
680
- end
735
+ # Assume artist has 2 albums each with 2 tags
736
+ ds._fetch = [{:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}, {:id=>1, :tags_id=>2}, {:id=>1, :tags_id=>3}]
681
737
  a = ds.all
682
738
  a.should == [@c1.load(:id=>1)]
683
739
  MODEL_DB.sqls.should == ['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)']
684
740
  a.first.tags.should == [Tag.load(:id=>2), Tag.load(:id=>3)]
685
- MODEL_DB.sqls.length.should == 1
741
+ MODEL_DB.sqls.length.should == 0
686
742
  end
687
743
 
688
744
  it "should eager graph multiple associations from the same table" do
@@ -692,7 +748,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
692
748
  a = a.first
693
749
  a.tags.should == [Tag.load(:id=>2)]
694
750
  a.other_tags.should == [Tag.load(:id=>9)]
695
- MODEL_DB.sqls.length.should == 1
751
+ MODEL_DB.sqls.length.should == 0
696
752
  end
697
753
 
698
754
  it "should eager graph a self_referential association" do
@@ -702,11 +758,11 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
702
758
  a = a.first
703
759
  a.tags.should == [Tag.load(:id=>2)]
704
760
  a.artists.should == [@c1.load(:id=>10)]
705
- MODEL_DB.sqls.length.should == 1
761
+ MODEL_DB.sqls.length.should == 0
706
762
  end
707
763
 
708
- it "eager graphing should give you a graph of tables when called without .all" do
709
- @c1.eager_graph(:tags, :artists).first.should == {:artists=>@c1.load(:id=>1), :artists_0=>@c1.load(:id=>10), :tags=>Tag.load(:id=>2)}
764
+ it "eager graphing should give you a plain hash when called without .all" do
765
+ @c1.eager_graph(:tags, :artists).first.should == {:albums_0_id=>3, :artists_0_id=>10, :id=>1, :tags_id=>2}
710
766
  end
711
767
 
712
768
  it "should be able to use eager and eager_graph together" do
@@ -717,31 +773,22 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
717
773
  a = a.first
718
774
  a.tags.should == [Tag.load(:id=>2)]
719
775
  a.albums.should == [Album.load(:id=>3)]
720
- MODEL_DB.sqls.length.should == 2
776
+ MODEL_DB.sqls.length.should == 0
721
777
  end
722
778
 
723
779
  it "should handle no associated records when eagerly graphing a single many_through_many association" do
724
780
  ds = @c1.eager_graph(:tags)
725
- def ds.fetch_rows(sql)
726
- @db << sql
727
- yield({:id=>1, :tags_id=>nil})
728
- end
781
+ ds._fetch = {:id=>1, :tags_id=>nil}
729
782
  a = ds.all
730
783
  a.should == [@c1.load(:id=>1)]
731
784
  MODEL_DB.sqls.should == ['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)']
732
785
  a.first.tags.should == []
733
- MODEL_DB.sqls.length.should == 1
786
+ MODEL_DB.sqls.length.should == 0
734
787
  end
735
788
 
736
789
  it "should handle no associated records when eagerly graphing multiple many_through_many associations" do
737
790
  ds = @c1.eager_graph(:tags, :albums)
738
- def ds.fetch_rows(sql)
739
- @db << sql
740
- yield({:id=>1, :tags_id=>nil, :albums_0_id=>3})
741
- yield({:id=>1, :tags_id=>2, :albums_0_id=>nil})
742
- yield({:id=>1, :tags_id=>5, :albums_0_id=>6})
743
- yield({:id=>7, :tags_id=>nil, :albums_0_id=>nil})
744
- end
791
+ 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}]
745
792
  a = ds.all
746
793
  a.should == [@c1.load(:id=>1), @c1.load(:id=>7)]
747
794
  MODEL_DB.sqls.should == ['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)']
@@ -749,17 +796,12 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
749
796
  a.first.albums.should == [Album.load(:id=>3), Album.load(:id=>6)]
750
797
  a.last.tags.should == []
751
798
  a.last.albums.should == []
752
- MODEL_DB.sqls.length.should == 1
799
+ MODEL_DB.sqls.length.should == 0
753
800
  end
754
801
 
755
802
  it "should handle missing associated records when cascading eager graphing for associations of associated models" do
756
803
  ds = @c1.eager_graph(:tags=>:tracks)
757
- def ds.fetch_rows(sql)
758
- @db << sql
759
- yield({:id=>1, :tags_id=>2, :tracks_id=>4})
760
- yield({:id=>1, :tags_id=>3, :tracks_id=>nil})
761
- yield({:id=>2, :tags_id=>nil, :tracks_id=>nil})
762
- end
804
+ 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}]
763
805
  a = ds.all
764
806
  a.should == [@c1.load(:id=>1), @c1.load(:id=>2)]
765
807
  MODEL_DB.sqls.should == ['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)']
@@ -768,7 +810,7 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
768
810
  a.tags.should == [Tag.load(:id=>2), Tag.load(:id=>3)]
769
811
  a.tags.first.tracks.should == [Track.load(:id=>4)]
770
812
  a.tags.last.tracks.should == []
771
- MODEL_DB.sqls.length.should == 1
813
+ MODEL_DB.sqls.length.should == 0
772
814
  end
773
815
 
774
816
  it "eager graphing should respect :left_primary_key and :right_primary_key options" do
@@ -776,15 +818,12 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
776
818
  @c1.dataset.meta_def(:columns){[:id, :yyy]}
777
819
  Tag.dataset.meta_def(:columns){[:id, :tag_id]}
778
820
  ds = @c1.eager_graph(:tags)
779
- def ds.fetch_rows(sql)
780
- @db << sql
781
- yield({:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4})
782
- end
821
+ ds._fetch = {:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4}
783
822
  a = ds.all
784
823
  a.should == [@c1.load(:id=>1, :yyy=>8)]
785
824
  MODEL_DB.sqls.should == ['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)']
786
825
  a.first.tags.should == [Tag.load(:id=>2, :tag_id=>4)]
787
- MODEL_DB.sqls.length.should == 1
826
+ MODEL_DB.sqls.length.should == 0
788
827
  end
789
828
 
790
829
  it "eager graphing should respect composite keys" do
@@ -792,29 +831,23 @@ describe "Sequel::Plugins::ManyThroughMany eager loading methods" do
792
831
  @c1.dataset.meta_def(:columns){[:id, :yyy]}
793
832
  Tag.dataset.meta_def(:columns){[:id, :tag_id]}
794
833
  ds = @c1.eager_graph(:tags)
795
- def ds.fetch_rows(sql)
796
- @db << sql
797
- yield({:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4})
798
- end
834
+ ds._fetch = {:id=>1, :yyy=>8, :tags_id=>2, :tag_id=>4}
799
835
  a = ds.all
800
836
  a.should == [@c1.load(:id=>1, :yyy=>8)]
801
837
  MODEL_DB.sqls.should == ['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))']
802
838
  a.first.tags.should == [Tag.load(:id=>2, :tag_id=>4)]
803
- MODEL_DB.sqls.length.should == 1
839
+ MODEL_DB.sqls.length.should == 0
804
840
  end
805
841
 
806
842
  it "should respect the association's :graph_select option" do
807
843
  @c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]], :graph_select=>:b
808
844
  ds = @c1.eager_graph(:tags)
809
- def ds.fetch_rows(sql)
810
- @db << sql
811
- yield({:id=>1, :b=>2})
812
- end
845
+ ds._fetch = {:id=>1, :b=>2}
813
846
  a = ds.all
814
847
  a.should == [@c1.load(:id=>1)]
815
848
  MODEL_DB.sqls.should == ['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)']
816
849
  a.first.tags.should == [Tag.load(:b=>2)]
817
- MODEL_DB.sqls.length.should == 1
850
+ MODEL_DB.sqls.length.should == 0
818
851
  end
819
852
 
820
853
  it "should respect the association's :graph_join_type option" do