sequel 4.9.0 → 4.10.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +79 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/Rakefile +2 -12
  6. data/bin/sequel +1 -0
  7. data/doc/advanced_associations.rdoc +82 -25
  8. data/doc/association_basics.rdoc +21 -22
  9. data/doc/core_extensions.rdoc +1 -1
  10. data/doc/opening_databases.rdoc +7 -0
  11. data/doc/release_notes/4.10.0.txt +226 -0
  12. data/doc/security.rdoc +1 -0
  13. data/doc/testing.rdoc +7 -7
  14. data/doc/transactions.rdoc +8 -0
  15. data/lib/sequel/adapters/jdbc.rb +160 -168
  16. data/lib/sequel/adapters/jdbc/db2.rb +17 -18
  17. data/lib/sequel/adapters/jdbc/derby.rb +5 -28
  18. data/lib/sequel/adapters/jdbc/h2.rb +11 -22
  19. data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
  20. data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
  21. data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
  22. data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
  23. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
  24. data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
  25. data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
  26. data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
  27. data/lib/sequel/adapters/openbase.rb +1 -7
  28. data/lib/sequel/adapters/postgres.rb +1 -1
  29. data/lib/sequel/adapters/shared/access.rb +3 -6
  30. data/lib/sequel/adapters/shared/cubrid.rb +24 -9
  31. data/lib/sequel/adapters/shared/db2.rb +13 -5
  32. data/lib/sequel/adapters/shared/firebird.rb +16 -16
  33. data/lib/sequel/adapters/shared/informix.rb +2 -5
  34. data/lib/sequel/adapters/shared/mssql.rb +72 -63
  35. data/lib/sequel/adapters/shared/mysql.rb +72 -40
  36. data/lib/sequel/adapters/shared/oracle.rb +27 -15
  37. data/lib/sequel/adapters/shared/postgres.rb +24 -44
  38. data/lib/sequel/adapters/shared/progress.rb +1 -5
  39. data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
  40. data/lib/sequel/adapters/shared/sqlite.rb +21 -6
  41. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
  42. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
  43. data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
  44. data/lib/sequel/core.rb +14 -9
  45. data/lib/sequel/database/dataset_defaults.rb +1 -0
  46. data/lib/sequel/database/misc.rb +12 -0
  47. data/lib/sequel/database/query.rb +4 -1
  48. data/lib/sequel/database/schema_methods.rb +3 -2
  49. data/lib/sequel/database/transactions.rb +47 -17
  50. data/lib/sequel/dataset/features.rb +12 -2
  51. data/lib/sequel/dataset/mutation.rb +2 -0
  52. data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
  53. data/lib/sequel/dataset/prepared_statements.rb +6 -0
  54. data/lib/sequel/dataset/query.rb +1 -1
  55. data/lib/sequel/dataset/sql.rb +132 -70
  56. data/lib/sequel/extensions/columns_introspection.rb +1 -1
  57. data/lib/sequel/extensions/null_dataset.rb +8 -4
  58. data/lib/sequel/extensions/pg_array.rb +4 -4
  59. data/lib/sequel/extensions/pg_row.rb +1 -0
  60. data/lib/sequel/model/associations.rb +468 -188
  61. data/lib/sequel/model/base.rb +88 -13
  62. data/lib/sequel/plugins/association_pks.rb +23 -64
  63. data/lib/sequel/plugins/auto_validations.rb +3 -2
  64. data/lib/sequel/plugins/dataset_associations.rb +1 -3
  65. data/lib/sequel/plugins/many_through_many.rb +18 -65
  66. data/lib/sequel/plugins/pg_array_associations.rb +97 -86
  67. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  68. data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
  69. data/lib/sequel/plugins/rcte_tree.rb +12 -16
  70. data/lib/sequel/plugins/sharding.rb +21 -3
  71. data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
  72. data/lib/sequel/plugins/subclasses.rb +1 -9
  73. data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
  74. data/lib/sequel/plugins/tree.rb +2 -2
  75. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  76. data/lib/sequel/version.rb +1 -1
  77. data/spec/adapters/mssql_spec.rb +57 -15
  78. data/spec/adapters/mysql_spec.rb +11 -0
  79. data/spec/bin_spec.rb +2 -2
  80. data/spec/core/database_spec.rb +38 -4
  81. data/spec/core/dataset_spec.rb +45 -7
  82. data/spec/core/placeholder_literalizer_spec.rb +17 -0
  83. data/spec/core/schema_spec.rb +6 -1
  84. data/spec/extensions/active_model_spec.rb +18 -9
  85. data/spec/extensions/association_pks_spec.rb +20 -18
  86. data/spec/extensions/association_proxies_spec.rb +9 -9
  87. data/spec/extensions/auto_validations_spec.rb +6 -0
  88. data/spec/extensions/columns_introspection_spec.rb +1 -0
  89. data/spec/extensions/constraint_validations_spec.rb +3 -1
  90. data/spec/extensions/many_through_many_spec.rb +191 -111
  91. data/spec/extensions/pg_array_associations_spec.rb +133 -103
  92. data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
  93. data/spec/extensions/rcte_tree_spec.rb +35 -27
  94. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
  95. data/spec/extensions/sharding_spec.rb +2 -2
  96. data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
  97. data/spec/extensions/to_dot_spec.rb +1 -0
  98. data/spec/extensions/touch_spec.rb +2 -2
  99. data/spec/integration/associations_test.rb +130 -37
  100. data/spec/integration/dataset_test.rb +17 -0
  101. data/spec/integration/model_test.rb +17 -0
  102. data/spec/integration/schema_test.rb +14 -0
  103. data/spec/integration/transaction_test.rb +25 -1
  104. data/spec/model/association_reflection_spec.rb +63 -24
  105. data/spec/model/associations_spec.rb +104 -57
  106. data/spec/model/base_spec.rb +14 -1
  107. data/spec/model/class_dataset_methods_spec.rb +1 -0
  108. data/spec/model/eager_loading_spec.rb +221 -74
  109. data/spec/model/model_spec.rb +119 -1
  110. metadata +4 -2
@@ -577,8 +577,10 @@ end
577
577
 
578
578
  describe Sequel::Model, ".[] optimization" do
579
579
  before do
580
- @db = DB.clone
580
+ @db = Sequel.mock
581
581
  @db.quote_identifiers = true
582
+ def @db.schema(*) [[:id, {:primary_key=>true}]] end
583
+ def @db.supports_schema_parsing?() true end
582
584
  @c = Class.new(Sequel::Model(@db))
583
585
  end
584
586
 
@@ -731,3 +733,14 @@ describe "Model datasets #with_pk with #with_pk!" do
731
733
  DB.sqls.should == ["SELECT * FROM a WHERE (foo) LIMIT 1"]
732
734
  end
733
735
  end
736
+
737
+ describe "Model::include" do
738
+ it "shouldn't change the signature of Module::include" do
739
+ mod1 = Module.new
740
+ mod2 = Module.new
741
+ including_class = Class.new(Sequel::Model(:items)) do
742
+ include(mod1, mod2)
743
+ end
744
+ including_class.included_modules.should include(mod1, mod2)
745
+ end
746
+ end
@@ -5,6 +5,7 @@ describe Sequel::Model, "class dataset methods" do
5
5
  @db = Sequel.mock
6
6
  @c = Class.new(Sequel::Model(@db[:items]))
7
7
  @d = @c.dataset
8
+ def @d.supports_cte?(*) true end
8
9
  @d._fetch = {:id=>1}
9
10
  @d.autoid = 1
10
11
  @d.numrows = 0
@@ -157,7 +157,7 @@ describe Sequel::Model, "#eager" do
157
157
  DB.sqls.should == ['SELECT * FROM albums']
158
158
  end
159
159
 
160
- it "should use first matching entry when eager loading one_to_one association" do
160
+ it "should eagerly load a single one_to_one association without an order" do
161
161
  EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id
162
162
  EagerTrack.dataset._fetch = [{:id => 3, :album_id=>1}, {:id => 4, :album_id=>1}]
163
163
  a = EagerAlbum.eager(:track).all
@@ -167,9 +167,18 @@ describe Sequel::Model, "#eager" do
167
167
  DB.sqls.should == []
168
168
  end
169
169
 
170
+ it "should eagerly load a single one_to_one association with an order" do
171
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:a
172
+ a = EagerAlbum.eager(:track).all
173
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
174
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY a LIMIT 1) AS t1']
175
+ a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
176
+ DB.sqls.should == []
177
+ end
178
+
170
179
  it "should eagerly load a single one_to_one association using the :distinct_on strategy" do
171
180
  def (EagerTrack.dataset).supports_distinct_on?() true end
172
- EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:a
181
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:a, :eager_limit_strategy=>:distinct_on
173
182
  a = EagerAlbum.eager(:track).all
174
183
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
175
184
  DB.sqls.should == ['SELECT * FROM albums', 'SELECT DISTINCT ON (tracks.album_id) * FROM tracks WHERE (tracks.album_id IN (1)) ORDER BY tracks.album_id, a']
@@ -179,7 +188,7 @@ describe Sequel::Model, "#eager" do
179
188
 
180
189
  it "should eagerly load a single one_to_one association using the :window_function strategy" do
181
190
  def (EagerTrack.dataset).supports_window_functions?() true end
182
- EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :eager_limit_strategy=>true
191
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :eager_limit_strategy=>:window_function
183
192
  a = EagerAlbum.eager(:track).all
184
193
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
185
194
  DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x = 1)']
@@ -187,19 +196,18 @@ describe Sequel::Model, "#eager" do
187
196
  DB.sqls.should == []
188
197
  end
189
198
 
190
- it "should not use distinct on eager limit strategy if the association has an offset" do
191
- def (EagerTrack.dataset).supports_distinct_on?() true end
192
- def (EagerTrack.dataset).supports_window_functions?() true end
193
- EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1], :order=>:name
199
+ it "should automatically use an eager limit stategy if the association has an offset" do
200
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1]
201
+ EagerTrack.dataset._fetch = [{:id => 4, :album_id=>1}]
194
202
  a = EagerAlbum.eager(:track).all
195
203
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
196
- DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x = 2)']
197
- a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
204
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1']
205
+ a.first.track.should == EagerTrack.load(:id => 4, :album_id=>1)
198
206
  DB.sqls.should == []
199
207
  end
200
208
 
201
- it "should automatically use an eager limit stategy if the association has an offset" do
202
- EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1]
209
+ it "should handle offsets when using the :ruby eager limit stategy" do
210
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1], :eager_limit_strategy=>:ruby
203
211
  EagerTrack.dataset._fetch = [{:id => 3, :album_id=>1}, {:id => 4, :album_id=>1}]
204
212
  a = EagerAlbum.eager(:track).all
205
213
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -208,6 +216,33 @@ describe Sequel::Model, "#eager" do
208
216
  DB.sqls.should == []
209
217
  end
210
218
 
219
+ it "should support a :subqueries_per_union option for the number of subqueries in a union" do
220
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1], :subqueries_per_union=>1
221
+ EagerAlbum.dataset._fetch = [{:id => 1, :band_id => 2}, {:id => 2, :band_id => 3}, {:id => 3, :band_id => 4}]
222
+ EagerTrack.dataset._fetch = [[{:id => 4, :album_id=>1}], [{:id=>5, :album_id=>2}], [{:id=>6, :album_id=>3}]]
223
+ a = EagerAlbum.eager(:track).all
224
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2), EagerAlbum.load(:id => 2, :band_id => 3), EagerAlbum.load(:id => 3, :band_id => 4)]
225
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1', 'SELECT * FROM (SELECT * FROM tracks WHERE (2 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1', 'SELECT * FROM (SELECT * FROM tracks WHERE (3 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1']
226
+ a.first.track.should == EagerTrack.load(:id => 4, :album_id=>1)
227
+ DB.sqls.should == []
228
+
229
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1], :subqueries_per_union=>2
230
+ EagerTrack.dataset._fetch = [[{:id => 4, :album_id=>1}, {:id=>5, :album_id=>2}], [{:id=>6, :album_id=>3}]]
231
+ a = EagerAlbum.eager(:track).all
232
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2), EagerAlbum.load(:id => 2, :band_id => 3), EagerAlbum.load(:id => 3, :band_id => 4)]
233
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1 UNION ALL SELECT * FROM (SELECT * FROM tracks WHERE (2 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1', 'SELECT * FROM (SELECT * FROM tracks WHERE (3 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1']
234
+ a.first.track.should == EagerTrack.load(:id => 4, :album_id=>1)
235
+ DB.sqls.should == []
236
+
237
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :limit=>[1,1], :subqueries_per_union=>3
238
+ EagerTrack.dataset._fetch = [[{:id => 4, :album_id=>1}, {:id=>5, :album_id=>2}, {:id=>6, :album_id=>3}]]
239
+ a = EagerAlbum.eager(:track).all
240
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2), EagerAlbum.load(:id => 2, :band_id => 3), EagerAlbum.load(:id => 3, :band_id => 4)]
241
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1 UNION ALL SELECT * FROM (SELECT * FROM tracks WHERE (2 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1 UNION ALL SELECT * FROM (SELECT * FROM tracks WHERE (3 = tracks.album_id) LIMIT 1 OFFSET 1) AS t1']
242
+ a.first.track.should == EagerTrack.load(:id => 4, :album_id=>1)
243
+ DB.sqls.should == []
244
+ end
245
+
211
246
  it "should eagerly load a single one_to_many association" do
212
247
  a = EagerAlbum.eager(:tracks).all
213
248
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -219,7 +254,7 @@ describe Sequel::Model, "#eager" do
219
254
  it "should eagerly load a single one_through_one association" do
220
255
  a = EagerAlbum.eager(:genre).all
221
256
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
222
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
257
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
223
258
  a.first.genre.should == EagerGenre.load(:id=>4)
224
259
  DB.sqls.should == []
225
260
  end
@@ -228,27 +263,36 @@ describe Sequel::Model, "#eager" do
228
263
  EagerGenre.dataset._fetch = [{:id => 3, :x_foreign_key_x=>1}, {:id => 4, :x_foreign_key_x=>1}]
229
264
  a = EagerAlbum.eager(:genre).all
230
265
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
231
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
266
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
232
267
  a.first.genre.should == EagerGenre.load(:id=>3)
233
268
  DB.sqls.should == []
234
269
  end
235
270
 
271
+ it "should eagerly load a single one_through_one association" do
272
+ EagerAlbum.one_through_one :genre, :clone=>:genre, :order=>:a
273
+ a = EagerAlbum.eager(:genre).all
274
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
275
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (1 = ag.album_id) ORDER BY a LIMIT 1) AS t1"]
276
+ a.first.genre.should == EagerGenre.load(:id=>4)
277
+ DB.sqls.should == []
278
+ end
279
+
236
280
  it "should eagerly load a single one_through_one association using the :distinct_on strategy" do
237
281
  def (EagerGenre.dataset).supports_distinct_on?() true end
238
- EagerAlbum.one_through_one :genre, :clone=>:genre, :order=>:a
282
+ EagerAlbum.one_through_one :genre, :clone=>:genre, :order=>:a, :eager_limit_strategy=>:distinct_on
239
283
  a = EagerAlbum.eager(:genre).all
240
284
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
241
- DB.sqls.should == ['SELECT * FROM albums', "SELECT DISTINCT ON (ag.album_id) genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1))) ORDER BY ag.album_id, a"]
285
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT DISTINCT ON (ag.album_id) genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1)) ORDER BY ag.album_id, a"]
242
286
  a.first.genre.should == EagerGenre.load(:id=>4)
243
287
  DB.sqls.should == []
244
288
  end
245
289
 
246
290
  it "should eagerly load a single one_through_one association using the :window_function strategy" do
247
291
  def (EagerGenre.dataset).supports_window_functions?() true end
248
- EagerAlbum.one_through_one :genre, :clone=>:genre, :eager_limit_strategy=>true
292
+ EagerAlbum.one_through_one :genre, :clone=>:genre, :eager_limit_strategy=>:window_function
249
293
  a = EagerAlbum.eager(:genre).all
250
294
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
251
- DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))) AS t1 WHERE (x_sequel_row_number_x = 1)"]
295
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x = 1)"]
252
296
  a.first.genre.should == EagerGenre.load(:id=>4)
253
297
  DB.sqls.should == []
254
298
  end
@@ -257,7 +301,7 @@ describe Sequel::Model, "#eager" do
257
301
  EagerGenre.dataset._fetch = [{:id => 3, :x_foreign_key_x=>1}, {:id => 4, :x_foreign_key_x=>1}]
258
302
  a = EagerAlbum.eager(:genre).all
259
303
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
260
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
304
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
261
305
  a.first.genre.should == EagerGenre.load(:id=>3)
262
306
  DB.sqls.should == []
263
307
  end
@@ -265,7 +309,7 @@ describe Sequel::Model, "#eager" do
265
309
  it "should eagerly load a single many_to_many association" do
266
310
  a = EagerAlbum.eager(:genres).all
267
311
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
268
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
312
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
269
313
  a.first.genres.should == [EagerGenre.load(:id=>4)]
270
314
  DB.sqls.should == []
271
315
  end
@@ -295,7 +339,7 @@ describe Sequel::Model, "#eager" do
295
339
  EagerGenre.dataset._fetch = {:id=>4, :x_foreign_key_x=>6}
296
340
  a = EagerAlbum.eager(:sgenres).all
297
341
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
298
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (6)))"]
342
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (6))"]
299
343
  a.first.sgenres.should == [EagerGenre.load(:id=>4)]
300
344
  DB.sqls.should == []
301
345
  end
@@ -305,7 +349,7 @@ describe Sequel::Model, "#eager" do
305
349
  EagerGenre.dataset._fetch = {:id=>4, :x_foreign_key_x=>6}
306
350
  a = EagerAlbum.eager(:sgenre).all
307
351
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
308
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (6)))"]
352
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (6))"]
309
353
  a.first.sgenre.should == EagerGenre.load(:id=>4)
310
354
  DB.sqls.should == []
311
355
  end
@@ -334,7 +378,7 @@ describe Sequel::Model, "#eager" do
334
378
  EagerAlbum.many_to_many :sgenres, :clone=>:genres, :eager_loading_predicate_key=>Sequel.*(:ag__album_id, 1)
335
379
  a = EagerAlbum.eager(:sgenres).all
336
380
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
337
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, (ag.album_id * 1) AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND ((ag.album_id * 1) IN (1)))"]
381
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, (ag.album_id * 1) AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE ((ag.album_id * 1) IN (1))"]
338
382
  a.first.sgenres.should == [EagerGenre.load(:id=>4)]
339
383
  DB.sqls.should == []
340
384
  end
@@ -343,7 +387,7 @@ describe Sequel::Model, "#eager" do
343
387
  EagerAlbum.one_through_one :sgenre, :clone=>:genre, :eager_loading_predicate_key=>Sequel.*(:ag__album_id, 1)
344
388
  a = EagerAlbum.eager(:sgenre).all
345
389
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
346
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, (ag.album_id * 1) AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND ((ag.album_id * 1) IN (1)))"]
390
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, (ag.album_id * 1) AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE ((ag.album_id * 1) IN (1))"]
347
391
  a.first.sgenre.should == EagerGenre.load(:id=>4)
348
392
  DB.sqls.should == []
349
393
  end
@@ -366,25 +410,25 @@ describe Sequel::Model, "#eager" do
366
410
  it "should correctly handle a :select=>[] option to many_to_many" do
367
411
  EagerAlbum.many_to_many :sgenres, :clone=>:genres, :select=>[]
368
412
  EagerAlbum.eager(:sgenres).all
369
- DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
413
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
370
414
  end
371
415
 
372
416
  it "should correctly handle a :select=>[] option to one_through_one" do
373
417
  EagerAlbum.one_through_one :sgenre, :clone=>:genre, :select=>[]
374
418
  EagerAlbum.eager(:sgenre).all
375
- DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
419
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
376
420
  end
377
421
 
378
422
  it "should correctly handle an aliased join table in many_to_many" do
379
423
  EagerAlbum.many_to_many :sgenres, :clone=>:genres, :join_table=>:ag___ga
380
424
  EagerAlbum.eager(:sgenres).all
381
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON ((ga.genre_id = genres.id) AND (ga.album_id IN (1)))"]
425
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON (ga.genre_id = genres.id) WHERE (ga.album_id IN (1))"]
382
426
  end
383
427
 
384
428
  it "should correctly handle an aliased join table in one_through_one" do
385
429
  EagerAlbum.one_through_one :sgenre, :clone=>:genre, :join_table=>:ag___ga
386
430
  EagerAlbum.eager(:sgenre).all
387
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON ((ga.genre_id = genres.id) AND (ga.album_id IN (1)))"]
431
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON (ga.genre_id = genres.id) WHERE (ga.album_id IN (1))"]
388
432
  end
389
433
 
390
434
  it "should eagerly load multiple associations in a single call" do
@@ -394,7 +438,7 @@ describe Sequel::Model, "#eager" do
394
438
  sqls.shift.should == 'SELECT * FROM albums'
395
439
  sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
396
440
  'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
397
- 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
441
+ 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))']
398
442
  a = a.first
399
443
  a.band.should == EagerBand.load(:id=>2)
400
444
  a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
@@ -409,7 +453,7 @@ describe Sequel::Model, "#eager" do
409
453
  sqls.shift.should == 'SELECT * FROM albums'
410
454
  sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
411
455
  'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
412
- 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
456
+ 'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))']
413
457
  a = a.first
414
458
  a.band.should == EagerBand.load(:id=>2)
415
459
  a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
@@ -423,7 +467,7 @@ describe Sequel::Model, "#eager" do
423
467
  DB.sqls.should == ['SELECT * FROM tracks',
424
468
  'SELECT * FROM albums WHERE (albums.id IN (1))',
425
469
  'SELECT * FROM bands WHERE (bands.id IN (2))',
426
- "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
470
+ "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.member_id = members.id) WHERE (bm.band_id IN (2))"]
427
471
  a = a.first
428
472
  a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
429
473
  a.album.band.should == EagerBand.load(:id => 2)
@@ -431,6 +475,32 @@ describe Sequel::Model, "#eager" do
431
475
  DB.sqls.should == []
432
476
  end
433
477
 
478
+ it "should cascade eager loading when using a UNION strategy for eager loading limited associations" do
479
+ EagerTrack.many_to_one :album2, :clone=>:album
480
+ EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:a
481
+ a = EagerAlbum.eager(:track=>:album2).all
482
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
483
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY a LIMIT 1) AS t1', 'SELECT * FROM albums WHERE (albums.id IN (1))']
484
+ a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
485
+ a.first.track.album2.should == EagerAlbum.load(:id => 1, :band_id => 2)
486
+ DB.sqls.should == []
487
+
488
+ a = EagerAlbum.eager(:track=>[:album2]).all
489
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
490
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY a LIMIT 1) AS t1', 'SELECT * FROM albums WHERE (albums.id IN (1))']
491
+ a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
492
+ a.first.track.album2.should == EagerAlbum.load(:id => 1, :band_id => 2)
493
+ DB.sqls.should == []
494
+
495
+ a = EagerAlbum.eager(:track=>{:album2=>:track}).all
496
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
497
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY a LIMIT 1) AS t1', 'SELECT * FROM albums WHERE (albums.id IN (1))', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY a LIMIT 1) AS t1']
498
+ a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
499
+ a.first.track.album2.should == EagerAlbum.load(:id => 1, :band_id => 2)
500
+ a.first.track.album2.track.should == EagerTrack.load(:id => 3, :album_id=>1)
501
+ DB.sqls.should == []
502
+ end
503
+
434
504
  it "should cascade eagerly loading when the :eager association option is used" do
435
505
  a = EagerBand.eager(:albums).all
436
506
  a.should == [EagerBand.load(:id=>2)]
@@ -488,7 +558,7 @@ describe Sequel::Model, "#eager" do
488
558
  ds._fetch = [{:id=>5, :bands_id=>2, :p_k=>6}, {:id=>5, :bands_id=>3, :p_k=>6}]
489
559
  a = EagerBand.load(:id=>2)
490
560
  a.graph_members.should == [EagerBandMember.load(:id=>5)]
491
- DB.sqls.should == ['SELECT members.id, bands.id AS bands_id, bands.p_k FROM (SELECT members.* FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id = 2))) AS members LEFT OUTER JOIN bm AS bm_0 ON (bm_0.member_id = members.id) LEFT OUTER JOIN bands ON (bands.id = bm_0.band_id) ORDER BY bands.id']
561
+ DB.sqls.should == ['SELECT members.id, bands.id AS bands_id, bands.p_k FROM (SELECT members.* FROM members INNER JOIN bm ON (bm.member_id = members.id) WHERE (bm.band_id = 2)) AS members LEFT OUTER JOIN bm AS bm_0 ON (bm_0.member_id = members.id) LEFT OUTER JOIN bands ON (bands.id = bm_0.band_id) ORDER BY bands.id']
492
562
  a.graph_members.first.bands.should == [EagerBand.load(:id=>2, :p_k=>6), EagerBand.load(:id=>3, :p_k=>6)]
493
563
  DB.sqls.should == []
494
564
  end
@@ -497,19 +567,19 @@ describe Sequel::Model, "#eager" do
497
567
  EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>{:a=>32}
498
568
  a = EagerBandMember.eager(:good_bands).all
499
569
  a.should == [EagerBandMember.load(:id => 5)]
500
- DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (a = 32) ORDER BY id']
570
+ DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.band_id = bands.id) WHERE ((a = 32) AND (bm.member_id IN (5))) ORDER BY id']
501
571
  a.first.good_bands.should == [EagerBand.load(:id => 2)]
502
572
  DB.sqls.should == []
503
573
 
504
574
  EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>"x = 1"
505
575
  a = EagerBandMember.eager(:good_bands).all
506
- DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (x = 1) ORDER BY id']
576
+ DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.band_id = bands.id) WHERE ((x = 1) AND (bm.member_id IN (5))) ORDER BY id']
507
577
  end
508
578
 
509
579
  it "should respect :order when eagerly loading" do
510
580
  a = EagerBandMember.eager(:bands).all
511
581
  a.should == [EagerBandMember.load(:id => 5)]
512
- DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) ORDER BY id']
582
+ DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.band_id = bands.id) WHERE (bm.member_id IN (5)) ORDER BY id']
513
583
  a.first.bands.should == [EagerBand.load(:id => 2)]
514
584
  DB.sqls.should == []
515
585
  end
@@ -544,14 +614,14 @@ describe Sequel::Model, "#eager" do
544
614
 
545
615
  it "should use the association's block when eager loading by default" do
546
616
  EagerAlbum.eager(:good_tracks).all
547
- DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (name = 'Good'))"]
617
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE ((name = 'Good') AND (tracks.album_id IN (1)))"]
548
618
  end
549
619
 
550
620
  it "should use the eager_block option when eager loading if given" do
551
621
  EagerBand.eager(:good_albums).all
552
- DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
622
+ DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((name = 'good') AND (albums.band_id IN (2)))"]
553
623
  EagerBand.eager(:good_albums=>:good_tracks).all
554
- DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))", "SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (name = 'Good'))"]
624
+ DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((name = 'good') AND (albums.band_id IN (2)))", "SELECT * FROM tracks WHERE ((name = 'Good') AND (tracks.album_id IN (1)))"]
555
625
  end
556
626
 
557
627
  it "should raise an error when attempting to eagerly load an association with the :allow_eager option set to false" do
@@ -565,7 +635,7 @@ describe Sequel::Model, "#eager" do
565
635
  EagerAlbum.eager(:track_names).all
566
636
  DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM tracks WHERE (tracks.album_id IN (1))"]
567
637
  EagerAlbum.eager(:genre_names).all
568
- DB.sqls.should == ['SELECT * FROM albums', "SELECT id, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
638
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT id, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
569
639
  end
570
640
 
571
641
  it "should respect many_to_one association's :qualify option" do
@@ -615,7 +685,7 @@ describe Sequel::Model, "#eager" do
615
685
  EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>[:band_id, :id], :left_key=>[:l1, :l2], :right_primary_key=>[:xxx, :id], :right_key=>[:r1, :r2], :join_table=>:ag
616
686
  EagerGenre.dataset._fetch = [{:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5}, {:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>6}]
617
687
  as = EagerAlbum.eager(:special_genres).all
618
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id) AND ((ag.l1, ag.l2) IN ((2, 1))))"]
688
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id)) WHERE ((ag.l1, ag.l2) IN ((2, 1)))"]
619
689
  as.length.should == 1
620
690
  as.first.special_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
621
691
  end
@@ -624,7 +694,7 @@ describe Sequel::Model, "#eager" do
624
694
  EagerAlbum.one_through_one :special_genre, :class=>:EagerGenre, :left_primary_key=>[:band_id, :id], :left_key=>[:l1, :l2], :right_primary_key=>[:xxx, :id], :right_key=>[:r1, :r2], :join_table=>:ag
625
695
  EagerGenre.dataset._fetch = [{:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5}]
626
696
  as = EagerAlbum.eager(:special_genre).all
627
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id) AND ((ag.l1, ag.l2) IN ((2, 1))))"]
697
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id)) WHERE ((ag.l1, ag.l2) IN ((2, 1)))"]
628
698
  as.length.should == 1
629
699
  as.first.special_genre.should == EagerGenre.load(:id=>5)
630
700
  end
@@ -633,7 +703,7 @@ describe Sequel::Model, "#eager" do
633
703
  EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_primary_key=>:xxx, :right_key=>:genre_id, :join_table=>:ag
634
704
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
635
705
  as = EagerAlbum.eager(:special_genres).all
636
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.xxx) AND (ag.album_id IN (2)))"]
706
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.xxx) WHERE (ag.album_id IN (2))"]
637
707
  as.length.should == 1
638
708
  as.first.special_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
639
709
  end
@@ -642,13 +712,13 @@ describe Sequel::Model, "#eager" do
642
712
  EagerAlbum.one_through_one :special_genre, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_primary_key=>:xxx, :right_key=>:genre_id, :join_table=>:ag
643
713
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}]
644
714
  as = EagerAlbum.eager(:special_genre).all
645
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.xxx) AND (ag.album_id IN (2)))"]
715
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.xxx) WHERE (ag.album_id IN (2))"]
646
716
  as.length.should == 1
647
717
  as.first.special_genre.should == EagerGenre.load(:id=>5)
648
718
  end
649
719
 
650
- it "should respect the :limit option on a one_to_many association" do
651
- EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2
720
+ it "should respect the :limit option on a one_to_many association using the :ruby strategy" do
721
+ EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2, :eager_limit_strategy=>:ruby
652
722
  EagerTrack.dataset._fetch = [{:album_id=>1, :id=>2}, {:album_id=>1, :id=>3}, {:album_id=>1, :id=>4}]
653
723
  as = EagerAlbum.eager(:first_two_tracks).all
654
724
  DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
@@ -656,43 +726,60 @@ describe Sequel::Model, "#eager" do
656
726
  as.first.first_two_tracks.should == [EagerTrack.load(:album_id=>1, :id=>2), EagerTrack.load(:album_id=>1, :id=>3)]
657
727
 
658
728
  DB.reset
659
- EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>[1,1]
729
+ EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>[1,1], :eager_limit_strategy=>:ruby
660
730
  as = EagerAlbum.eager(:first_two_tracks).all
661
731
  DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
662
732
  as.length.should == 1
663
733
  as.first.first_two_tracks.should == [EagerTrack.load(:album_id=>1, :id=>3)]
664
734
 
665
735
  DB.reset
666
- EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>[nil,1]
736
+ EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>[nil,1], :eager_limit_strategy=>:ruby
667
737
  as = EagerAlbum.eager(:first_two_tracks).all
668
738
  DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
669
739
  as.length.should == 1
670
740
  as.first.first_two_tracks.should == [EagerTrack.load(:album_id=>1, :id=>3), EagerTrack.load(:album_id=>1, :id=>4)]
671
741
  end
672
742
 
673
- it "should respect the :limit option on a one_to_many association using the :window_function strategy" do
674
- def (EagerTrack.dataset).supports_window_functions?() true end
743
+ it "should respect the :limit option on a one_to_many association" do
675
744
  EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>2
676
745
  a = EagerAlbum.eager(:tracks).all
677
746
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
678
- DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
747
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY name LIMIT 2) AS t1']
679
748
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
680
749
  DB.sqls.should == []
681
- end
682
750
 
683
- it "should respect the :limit option with an offset on a one_to_many association using the :window_function strategy" do
684
- def (EagerTrack.dataset).supports_window_functions?() true end
685
751
  EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>[2, 1]
686
752
  a = EagerAlbum.eager(:tracks).all
687
753
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
688
- DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
754
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY name LIMIT 2 OFFSET 1) AS t1']
755
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
756
+ DB.sqls.should == []
757
+
758
+ EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>[nil, 1]
759
+ a = EagerAlbum.eager(:tracks).all
760
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
761
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT * FROM tracks WHERE (1 = tracks.album_id) ORDER BY name OFFSET 1) AS t1']
689
762
  a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
690
763
  DB.sqls.should == []
691
764
  end
692
765
 
693
- it "should respect the :limit option with just an offset on a one_to_many association using the :window_function strategy" do
766
+ it "should respect the :limit option on a one_to_many association using the :window_function strategy" do
694
767
  def (EagerTrack.dataset).supports_window_functions?() true end
695
- EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>[nil, 1]
768
+ EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>2, :eager_limit_strategy=>:window_function
769
+ a = EagerAlbum.eager(:tracks).all
770
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
771
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
772
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
773
+ DB.sqls.should == []
774
+
775
+ EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>[2, 1], :eager_limit_strategy=>:window_function
776
+ a = EagerAlbum.eager(:tracks).all
777
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
778
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
779
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
780
+ DB.sqls.should == []
781
+
782
+ EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>[nil, 1], :eager_limit_strategy=>:window_function
696
783
  a = EagerAlbum.eager(:tracks).all
697
784
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
698
785
  DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x >= 2)']
@@ -700,49 +787,96 @@ describe Sequel::Model, "#eager" do
700
787
  DB.sqls.should == []
701
788
  end
702
789
 
703
- it "should respect the limit option on a many_to_many association" do
704
- EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2
790
+ it "should use a ruby strategy for limit if :eager_graph option is used" do
791
+ EagerTrack.many_to_one :album2, :clone=>:album
792
+ EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2, :eager_graph=>:album2
793
+ EagerTrack.dataset._fetch = [{:album_id=>1, :id=>2, :album2_id=>1, :band_id=>5}, {:album_id=>1, :id=>3, :album2_id=>1, :band_id=>5}, {:album_id=>1, :id=>4, :album2_id=>1, :band_id=>5}]
794
+ as = EagerAlbum.eager(:first_two_tracks).all
795
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT tracks.id, tracks.album_id, album2.id AS album2_id, album2.band_id FROM tracks LEFT OUTER JOIN albums AS album2 ON (album2.id = tracks.album_id) WHERE (tracks.album_id IN (1))"]
796
+ as.length.should == 1
797
+ tracks = as.first.first_two_tracks
798
+ tracks.should == [EagerTrack.load(:album_id=>1, :id=>2), EagerTrack.load(:album_id=>1, :id=>3)]
799
+ tracks.first.album2.should == EagerAlbum.load(:id=>1, :band_id=>5)
800
+ tracks.last.album2.should == EagerAlbum.load(:id=>1, :band_id=>5)
801
+ end
802
+
803
+ it "should not use a union strategy for limit by default if providing a per-eager load callback" do
804
+ def (EagerTrack.dataset).supports_window_functions?() true end
805
+ EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :order=>:name, :limit=>2
806
+ a = EagerAlbum.eager(:tracks=>proc{|ds| ds.where(:id=>3)}).all
807
+ a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
808
+ DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE ((tracks.album_id IN (1)) AND (id = 3))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
809
+ a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
810
+ DB.sqls.should == []
811
+ end
812
+
813
+ it "should respect the limit option on a many_to_many association using the :ruby strategy" do
814
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2, :eager_limit_strategy=>:ruby
705
815
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
706
816
  as = EagerAlbum.eager(:first_two_genres).all
707
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
817
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))"]
708
818
  as.length.should == 1
709
819
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
710
820
 
711
821
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
712
- EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[1, 1]
822
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[1, 1], :eager_limit_strategy=>:ruby
713
823
  as = EagerAlbum.eager(:first_two_genres).all
714
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
824
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))"]
715
825
  as.length.should == 1
716
826
  as.first.first_two_genres.should == [EagerGenre.load(:id=>6)]
717
827
 
718
828
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
719
- EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[nil, 1]
829
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[nil, 1], :eager_limit_strategy=>:ruby
720
830
  as = EagerAlbum.eager(:first_two_genres).all
721
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
831
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))"]
722
832
  as.length.should == 1
723
833
  as.first.first_two_genres.should == [EagerGenre.load(:id=>6), EagerGenre.load(:id=>7)]
724
834
  end
725
835
 
726
- it "should respect the limit option on a many_to_many association using the :window_function strategy" do
836
+ it "should respect the limit option on a many_to_many association" do
727
837
  def (EagerGenre.dataset).supports_window_functions?() true end
728
838
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2, :order=>:name
729
839
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
730
840
  as = EagerAlbum.eager(:first_two_genres).all
731
- DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE (x_sequel_row_number_x <= 2)"]
841
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (2 = ag.album_id) ORDER BY name LIMIT 2) AS t1"]
732
842
  as.length.should == 1
733
843
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
734
844
 
735
845
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}]
736
846
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[1, 1], :order=>:name
737
847
  as = EagerAlbum.eager(:first_two_genres).all
738
- DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 3))"]
848
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (2 = ag.album_id) ORDER BY name LIMIT 1 OFFSET 1) AS t1"]
739
849
  as.length.should == 1
740
850
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5)]
741
851
 
742
852
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
743
853
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[nil, 1], :order=>:name
744
854
  as = EagerAlbum.eager(:first_two_genres).all
745
- DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE (x_sequel_row_number_x >= 2)"]
855
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (2 = ag.album_id) ORDER BY name OFFSET 1) AS t1"]
856
+ as.length.should == 1
857
+ as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
858
+ end
859
+
860
+ it "should respect the limit option on a many_to_many association using the :window_function strategy" do
861
+ def (EagerGenre.dataset).supports_window_functions?() true end
862
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2, :order=>:name, :eager_limit_strategy=>:window_function
863
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
864
+ as = EagerAlbum.eager(:first_two_genres).all
865
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))) AS t1 WHERE (x_sequel_row_number_x <= 2)"]
866
+ as.length.should == 1
867
+ as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
868
+
869
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}]
870
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[1, 1], :order=>:name, :eager_limit_strategy=>:window_function
871
+ as = EagerAlbum.eager(:first_two_genres).all
872
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 3))"]
873
+ as.length.should == 1
874
+ as.first.first_two_genres.should == [EagerGenre.load(:id=>5)]
875
+
876
+ EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
877
+ EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[nil, 1], :order=>:name, :eager_limit_strategy=>:window_function
878
+ as = EagerAlbum.eager(:first_two_genres).all
879
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (2))) AS t1 WHERE (x_sequel_row_number_x >= 2)"]
746
880
  as.length.should == 1
747
881
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
748
882
  end
@@ -789,7 +923,7 @@ describe Sequel::Model, "#eager" do
789
923
  EagerAlbum.many_to_many :al_genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :uniq=>true
790
924
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>1, :id=>8}, {:x_foreign_key_x=>1, :id=>8}]
791
925
  a = EagerAlbum.eager(:al_genres).all.first
792
- DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
926
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
793
927
  a.should == EagerAlbum.load(:id => 1, :band_id => 2)
794
928
  a.al_genres.should == [EagerGenre.load(:id=>8)]
795
929
  end
@@ -797,7 +931,7 @@ describe Sequel::Model, "#eager" do
797
931
  it "should respect :distinct option when eagerly loading many_to_many associations" do
798
932
  EagerAlbum.many_to_many :al_genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :distinct=>true
799
933
  a = EagerAlbum.eager(:al_genres).all.first
800
- DB.sqls.should == ['SELECT * FROM albums', "SELECT DISTINCT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
934
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT DISTINCT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
801
935
  a.should == EagerAlbum.load(:id => 1, :band_id => 2)
802
936
  a.al_genres.should == [EagerGenre.load(:id=>4)]
803
937
  end
@@ -830,7 +964,7 @@ describe Sequel::Model, "#eager" do
830
964
  it "should eagerly load a many_to_many association with custom eager block" do
831
965
  a = EagerAlbum.eager(:genres => proc {|ds| ds.select(:name)}).all
832
966
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
833
- DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
967
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
834
968
  a.first.genres.should == [EagerGenre.load(:id => 4)]
835
969
  DB.sqls.should == []
836
970
  end
@@ -838,7 +972,7 @@ describe Sequel::Model, "#eager" do
838
972
  it "should eagerly load a one_through_one association with custom eager block" do
839
973
  a = EagerAlbum.eager(:genre => proc {|ds| ds.select(:name)}).all
840
974
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
841
- DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
975
+ DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
842
976
  a.first.genre.should == EagerGenre.load(:id => 4)
843
977
  DB.sqls.should == []
844
978
  end
@@ -849,7 +983,7 @@ describe Sequel::Model, "#eager" do
849
983
  DB.sqls.should == ['SELECT * FROM tracks',
850
984
  'SELECT * FROM albums WHERE (albums.id IN (1))',
851
985
  'SELECT * FROM bands WHERE (bands.id IN (2))',
852
- "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
986
+ "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.member_id = members.id) WHERE (bm.band_id IN (2))"]
853
987
  a = a.first
854
988
  a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
855
989
  a.album.band.should == EagerBand.load(:id => 2)
@@ -863,7 +997,7 @@ describe Sequel::Model, "#eager" do
863
997
  DB.sqls.should == ['SELECT * FROM tracks',
864
998
  'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
865
999
  'SELECT * FROM bands WHERE (bands.id IN (2))',
866
- "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
1000
+ "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.member_id = members.id) WHERE (bm.band_id IN (2))"]
867
1001
  a = a.first
868
1002
  a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
869
1003
  a.album.band.should == EagerBand.load(:id => 2)
@@ -900,7 +1034,7 @@ describe Sequel::Model, "#eager" do
900
1034
 
901
1035
  it "should call both association and custom eager blocks" do
902
1036
  EagerBand.eager(:good_albums => proc {|ds| ds.select(:name)}).all
903
- DB.sqls.should == ['SELECT * FROM bands', "SELECT name FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
1037
+ DB.sqls.should == ['SELECT * FROM bands', "SELECT name FROM albums WHERE ((name = 'good') AND (albums.band_id IN (2)))"]
904
1038
  end
905
1039
  end
906
1040
 
@@ -1094,6 +1228,19 @@ describe Sequel::Model, "#eager_graph" do
1094
1228
  a.first.ltrack.should == sub.load(:id => 3, :album_id=>1)
1095
1229
  end
1096
1230
 
1231
+ it "should eagerly graph a single one_to_one association using the :correlated_subquery strategy" do
1232
+ sub = Class.new(GraphTrack)
1233
+ def (sub.dataset).supports_window_functions?() true end
1234
+ def (sub.dataset).columns() [:id, :album_id] end
1235
+ GraphAlbum.one_to_one :ltrack, :clone=>:track, :class=>sub
1236
+ ds = GraphAlbum.eager_graph_with_options(:ltrack, :limit_strategy=>:correlated_subquery)
1237
+ ds.sql.should == 'SELECT albums.id, albums.band_id, ltrack.id AS ltrack_id, ltrack.album_id FROM albums LEFT OUTER JOIN (SELECT * FROM tracks WHERE (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1))) AS ltrack ON (ltrack.album_id = albums.id)'
1238
+ ds._fetch = {:id=>1, :band_id=>2, :ltrack_id=>3, :album_id=>1}
1239
+ a = ds.all
1240
+ a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
1241
+ a.first.ltrack.should == sub.load(:id => 3, :album_id=>1)
1242
+ end
1243
+
1097
1244
  it "should eagerly load a single one_to_many association" do
1098
1245
  ds = GraphAlbum.eager_graph(:tracks)
1099
1246
  ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
@@ -1367,7 +1514,7 @@ describe Sequel::Model, "#eager_graph" do
1367
1514
  a.tracks.should == [GraphTrack.load(:id=>3, :album_id=>1)]
1368
1515
  a.genres.should == [GraphGenre.load(:id => 6)]
1369
1516
  DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)',
1370
- "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
1517
+ "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) WHERE (ag.album_id IN (1))"]
1371
1518
  end
1372
1519
 
1373
1520
  it "should handle no associated records for a single many_to_one association" do