sequel 4.9.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
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