sequel 4.7.0 → 4.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG +46 -0
- data/README.rdoc +25 -1
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +143 -17
- data/doc/association_basics.rdoc +80 -59
- data/doc/release_notes/4.8.0.txt +175 -0
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +4 -2
- data/lib/sequel/adapters/shared/postgres.rb +19 -3
- data/lib/sequel/adapters/shared/sqlite.rb +3 -3
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/graph.rb +23 -9
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/sql.rb +3 -3
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -1
- data/lib/sequel/extensions/pg_array_ops.rb +6 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +7 -0
- data/lib/sequel/extensions/pg_json_ops.rb +5 -0
- data/lib/sequel/extensions/query.rb +8 -2
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model/associations.rb +476 -152
- data/lib/sequel/plugins/class_table_inheritance.rb +11 -3
- data/lib/sequel/plugins/dataset_associations.rb +21 -18
- data/lib/sequel/plugins/many_through_many.rb +87 -20
- data/lib/sequel/plugins/nested_attributes.rb +12 -0
- data/lib/sequel/plugins/pg_array_associations.rb +31 -12
- data/lib/sequel/plugins/single_table_inheritance.rb +9 -1
- data/lib/sequel/sql.rb +1 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +2 -2
- data/spec/adapters/postgres_spec.rb +7 -0
- data/spec/core/object_graph_spec.rb +250 -196
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +100 -6
- data/spec/extensions/many_through_many_spec.rb +1002 -19
- data/spec/extensions/nested_attributes_spec.rb +24 -0
- data/spec/extensions/pg_array_associations_spec.rb +17 -12
- data/spec/extensions/pg_array_spec.rb +4 -2
- data/spec/extensions/spec_helper.rb +1 -1
- data/spec/integration/associations_test.rb +1003 -48
- data/spec/integration/dataset_test.rb +12 -5
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/type_test.rb +1 -1
- data/spec/model/associations_spec.rb +467 -130
- data/spec/model/eager_loading_spec.rb +332 -5
- metadata +5 -3
@@ -7,6 +7,7 @@ describe Sequel::Model, "#eager" do
|
|
7
7
|
many_to_one :band, :class=>'EagerBand', :key=>:band_id
|
8
8
|
one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id
|
9
9
|
many_to_many :genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
|
10
|
+
one_through_one :genre, :clone=>:genres
|
10
11
|
one_to_many :good_tracks, :class=>'EagerTrack', :reciprocal=>nil, :key=>:album_id do |ds|
|
11
12
|
ds.filter(:name=>'Good')
|
12
13
|
end
|
@@ -168,10 +169,10 @@ describe Sequel::Model, "#eager" do
|
|
168
169
|
|
169
170
|
it "should eagerly load a single one_to_one association using the :distinct_on strategy" do
|
170
171
|
def (EagerTrack.dataset).supports_distinct_on?() true end
|
171
|
-
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :
|
172
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :order=>:a
|
172
173
|
a = EagerAlbum.eager(:track).all
|
173
174
|
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
174
|
-
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']
|
175
|
+
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']
|
175
176
|
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
176
177
|
DB.sqls.should == []
|
177
178
|
end
|
@@ -215,6 +216,52 @@ describe Sequel::Model, "#eager" do
|
|
215
216
|
DB.sqls.should == []
|
216
217
|
end
|
217
218
|
|
219
|
+
it "should eagerly load a single one_through_one association" do
|
220
|
+
a = EagerAlbum.eager(:genre).all
|
221
|
+
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)))"]
|
223
|
+
a.first.genre.should == EagerGenre.load(:id=>4)
|
224
|
+
DB.sqls.should == []
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should use first matching entry when eager loading one_through_one association" do
|
228
|
+
EagerGenre.dataset._fetch = [{:id => 3, :x_foreign_key_x=>1}, {:id => 4, :x_foreign_key_x=>1}]
|
229
|
+
a = EagerAlbum.eager(:genre).all
|
230
|
+
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)))"]
|
232
|
+
a.first.genre.should == EagerGenre.load(:id=>3)
|
233
|
+
DB.sqls.should == []
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should eagerly load a single one_through_one association using the :distinct_on strategy" do
|
237
|
+
def (EagerGenre.dataset).supports_distinct_on?() true end
|
238
|
+
EagerAlbum.one_through_one :genre, :clone=>:genre, :order=>:a
|
239
|
+
a = EagerAlbum.eager(:genre).all
|
240
|
+
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"]
|
242
|
+
a.first.genre.should == EagerGenre.load(:id=>4)
|
243
|
+
DB.sqls.should == []
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should eagerly load a single one_through_one association using the :window_function strategy" do
|
247
|
+
def (EagerGenre.dataset).supports_window_functions?() true end
|
248
|
+
EagerAlbum.one_through_one :genre, :clone=>:genre, :eager_limit_strategy=>true
|
249
|
+
a = EagerAlbum.eager(:genre).all
|
250
|
+
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)"]
|
252
|
+
a.first.genre.should == EagerGenre.load(:id=>4)
|
253
|
+
DB.sqls.should == []
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should automatically use an eager limit stategy if the association has an offset" do
|
257
|
+
EagerGenre.dataset._fetch = [{:id => 3, :x_foreign_key_x=>1}, {:id => 4, :x_foreign_key_x=>1}]
|
258
|
+
a = EagerAlbum.eager(:genre).all
|
259
|
+
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)))"]
|
261
|
+
a.first.genre.should == EagerGenre.load(:id=>3)
|
262
|
+
DB.sqls.should == []
|
263
|
+
end
|
264
|
+
|
218
265
|
it "should eagerly load a single many_to_many association" do
|
219
266
|
a = EagerAlbum.eager(:genres).all
|
220
267
|
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
@@ -253,6 +300,16 @@ describe Sequel::Model, "#eager" do
|
|
253
300
|
DB.sqls.should == []
|
254
301
|
end
|
255
302
|
|
303
|
+
it "should support using a custom :left_primary_key option when eager loading one_through_one associations" do
|
304
|
+
EagerAlbum.one_through_one :sgenre, :clone=>:genre, :left_primary_key=>:band_id3
|
305
|
+
EagerGenre.dataset._fetch = {:id=>4, :x_foreign_key_x=>6}
|
306
|
+
a = EagerAlbum.eager(:sgenre).all
|
307
|
+
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)))"]
|
309
|
+
a.first.sgenre.should == EagerGenre.load(:id=>4)
|
310
|
+
DB.sqls.should == []
|
311
|
+
end
|
312
|
+
|
256
313
|
it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup, for many_to_one associations" do
|
257
314
|
EagerAlbum.many_to_one :sband, :clone=>:band, :eager_loading_predicate_key=>Sequel./(:bands__id, 3), :primary_key_method=>:id3
|
258
315
|
EagerBand.dataset._fetch = {:id=>6}
|
@@ -282,6 +339,15 @@ describe Sequel::Model, "#eager" do
|
|
282
339
|
DB.sqls.should == []
|
283
340
|
end
|
284
341
|
|
342
|
+
it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup, for one_through_one associations" do
|
343
|
+
EagerAlbum.one_through_one :sgenre, :clone=>:genre, :eager_loading_predicate_key=>Sequel.*(:ag__album_id, 1)
|
344
|
+
a = EagerAlbum.eager(:sgenre).all
|
345
|
+
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)))"]
|
347
|
+
a.first.sgenre.should == EagerGenre.load(:id=>4)
|
348
|
+
DB.sqls.should == []
|
349
|
+
end
|
350
|
+
|
285
351
|
it "should raise an error for an unhandled :eager_loader_key option" do
|
286
352
|
EagerAlbum.many_to_many :sgenres, :clone=>:genres, :eager_loader_key=>1
|
287
353
|
ds = EagerAlbum.eager(:sgenres)
|
@@ -303,12 +369,24 @@ describe Sequel::Model, "#eager" do
|
|
303
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)))"]
|
304
370
|
end
|
305
371
|
|
372
|
+
it "should correctly handle a :select=>[] option to one_through_one" do
|
373
|
+
EagerAlbum.one_through_one :sgenre, :clone=>:genre, :select=>[]
|
374
|
+
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)))"]
|
376
|
+
end
|
377
|
+
|
306
378
|
it "should correctly handle an aliased join table in many_to_many" do
|
307
379
|
EagerAlbum.many_to_many :sgenres, :clone=>:genres, :join_table=>:ag___ga
|
308
380
|
EagerAlbum.eager(:sgenres).all
|
309
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)))"]
|
310
382
|
end
|
311
383
|
|
384
|
+
it "should correctly handle an aliased join table in one_through_one" do
|
385
|
+
EagerAlbum.one_through_one :sgenre, :clone=>:genre, :join_table=>:ag___ga
|
386
|
+
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)))"]
|
388
|
+
end
|
389
|
+
|
312
390
|
it "should eagerly load multiple associations in a single call" do
|
313
391
|
a = EagerAlbum.eager(:genres, :tracks, :band).all
|
314
392
|
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
@@ -542,6 +620,15 @@ describe Sequel::Model, "#eager" do
|
|
542
620
|
as.first.special_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
543
621
|
end
|
544
622
|
|
623
|
+
it "should respect one_through_one association's composite keys" do
|
624
|
+
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
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5}]
|
626
|
+
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))))"]
|
628
|
+
as.length.should == 1
|
629
|
+
as.first.special_genre.should == EagerGenre.load(:id=>5)
|
630
|
+
end
|
631
|
+
|
545
632
|
it "should respect many_to_many association's :left_primary_key and :right_primary_key options" do
|
546
633
|
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
|
547
634
|
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
@@ -551,6 +638,15 @@ describe Sequel::Model, "#eager" do
|
|
551
638
|
as.first.special_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
552
639
|
end
|
553
640
|
|
641
|
+
it "should respect one_through_one association's :left_primary_key and :right_primary_key options" do
|
642
|
+
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
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}]
|
644
|
+
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)))"]
|
646
|
+
as.length.should == 1
|
647
|
+
as.first.special_genre.should == EagerGenre.load(:id=>5)
|
648
|
+
end
|
649
|
+
|
554
650
|
it "should respect the :limit option on a one_to_many association" do
|
555
651
|
EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2
|
556
652
|
EagerTrack.dataset._fetch = [{:album_id=>1, :id=>2}, {:album_id=>1, :id=>3}, {:album_id=>1, :id=>4}]
|
@@ -739,6 +835,14 @@ describe Sequel::Model, "#eager" do
|
|
739
835
|
DB.sqls.should == []
|
740
836
|
end
|
741
837
|
|
838
|
+
it "should eagerly load a one_through_one association with custom eager block" do
|
839
|
+
a = EagerAlbum.eager(:genre => proc {|ds| ds.select(:name)}).all
|
840
|
+
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)))"]
|
842
|
+
a.first.genre.should == EagerGenre.load(:id => 4)
|
843
|
+
DB.sqls.should == []
|
844
|
+
end
|
845
|
+
|
742
846
|
it "should allow cascading of eager loading within a custom eager block" do
|
743
847
|
a = EagerTrack.eager(:album => proc {|ds| ds.eager(:band => :members)}).all
|
744
848
|
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
@@ -807,7 +911,9 @@ describe Sequel::Model, "#eager_graph" do
|
|
807
911
|
columns :id, :band_id
|
808
912
|
many_to_one :band, :class=>'GraphBand', :key=>:band_id
|
809
913
|
one_to_many :tracks, :class=>'GraphTrack', :key=>:album_id
|
914
|
+
one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
810
915
|
many_to_many :genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
|
916
|
+
one_through_one :genre, :clone=>:genres
|
811
917
|
many_to_one :previous_album, :class=>'GraphAlbum'
|
812
918
|
end
|
813
919
|
|
@@ -909,6 +1015,21 @@ describe Sequel::Model, "#eager_graph" do
|
|
909
1015
|
a.album.band.members.should == [GraphBandMember.load(:id => 5)]
|
910
1016
|
end
|
911
1017
|
|
1018
|
+
it "should set up correct inner joins when using association_join" do
|
1019
|
+
GraphAlbum.association_join(:band).sql.should == 'SELECT * FROM albums INNER JOIN bands AS band ON (band.id = albums.band_id)'
|
1020
|
+
GraphAlbum.association_join(:track).sql.should == 'SELECT * FROM albums INNER JOIN tracks AS track ON (track.album_id = albums.id)'
|
1021
|
+
GraphAlbum.association_join(:tracks).sql.should == 'SELECT * FROM albums INNER JOIN tracks ON (tracks.album_id = albums.id)'
|
1022
|
+
GraphAlbum.association_join(:genres).sql.should == 'SELECT * FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres ON (genres.id = ag.genre_id)'
|
1023
|
+
GraphAlbum.association_join(:genre).sql.should == 'SELECT * FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres AS genre ON (genre.id = ag.genre_id)'
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
it "should set up correct join types when using association_*_join" do
|
1027
|
+
GraphAlbum.association_inner_join(:band).sql.should == 'SELECT * FROM albums INNER JOIN bands AS band ON (band.id = albums.band_id)'
|
1028
|
+
GraphAlbum.association_left_join(:track).sql.should == 'SELECT * FROM albums LEFT JOIN tracks AS track ON (track.album_id = albums.id)'
|
1029
|
+
GraphAlbum.association_right_join(:tracks).sql.should == 'SELECT * FROM albums RIGHT JOIN tracks ON (tracks.album_id = albums.id)'
|
1030
|
+
GraphAlbum.association_full_join(:genres).sql.should == 'SELECT * FROM albums FULL JOIN ag ON (ag.album_id = albums.id) FULL JOIN genres ON (genres.id = ag.genre_id)'
|
1031
|
+
end
|
1032
|
+
|
912
1033
|
it "should eagerly load a single many_to_one association" do
|
913
1034
|
ds = GraphAlbum.eager_graph(:band)
|
914
1035
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
@@ -929,8 +1050,16 @@ describe Sequel::Model, "#eager_graph" do
|
|
929
1050
|
a.first.band_id.should == GraphBand.load(:id => 2, :vocalist_id=>3)
|
930
1051
|
end
|
931
1052
|
|
1053
|
+
it "should support :join_type eager_graph option one_to_one association" do
|
1054
|
+
ds = GraphAlbum.eager_graph_with_options(:track, :join_type=>:inner)
|
1055
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, track.id AS track_id, track.album_id FROM albums INNER JOIN tracks AS track ON (track.album_id = albums.id)'
|
1056
|
+
ds._fetch = {:id=>1, :band_id=>2, :track_id=>3, :album_id=>1}
|
1057
|
+
a = ds.all
|
1058
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1059
|
+
a.first.track.should == GraphTrack.load(:id => 3, :album_id=>1)
|
1060
|
+
end
|
1061
|
+
|
932
1062
|
it "should eagerly load a single one_to_one association" do
|
933
|
-
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
934
1063
|
ds = GraphAlbum.eager_graph(:track)
|
935
1064
|
ds.sql.should == 'SELECT albums.id, albums.band_id, track.id AS track_id, track.album_id FROM albums LEFT OUTER JOIN tracks AS track ON (track.album_id = albums.id)'
|
936
1065
|
ds._fetch = {:id=>1, :band_id=>2, :track_id=>3, :album_id=>1}
|
@@ -939,6 +1068,32 @@ describe Sequel::Model, "#eager_graph" do
|
|
939
1068
|
a.first.track.should == GraphTrack.load(:id => 3, :album_id=>1)
|
940
1069
|
end
|
941
1070
|
|
1071
|
+
it "should eagerly graph a single one_to_one association using the :distinct_on strategy" do
|
1072
|
+
sub = Class.new(GraphTrack)
|
1073
|
+
def (sub.dataset).supports_distinct_on?() true end
|
1074
|
+
def (sub.dataset).columns() [:id, :album_id] end
|
1075
|
+
GraphAlbum.one_to_one :ltrack, :clone=>:track, :class=>sub
|
1076
|
+
ds = GraphAlbum.eager_graph_with_options(:ltrack, :limit_strategy=>true)
|
1077
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, ltrack.id AS ltrack_id, ltrack.album_id FROM albums LEFT OUTER JOIN (SELECT DISTINCT ON (tracks.album_id) * FROM tracks ORDER BY tracks.album_id) AS ltrack ON (ltrack.album_id = albums.id)'
|
1078
|
+
ds._fetch = {:id=>1, :band_id=>2, :ltrack_id=>3, :album_id=>1}
|
1079
|
+
a = ds.all
|
1080
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1081
|
+
a.first.ltrack.should == sub.load(:id => 3, :album_id=>1)
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
it "should eagerly graph a single one_to_one association using the :window_function strategy" do
|
1085
|
+
sub = Class.new(GraphTrack)
|
1086
|
+
def (sub.dataset).supports_window_functions?() true end
|
1087
|
+
def (sub.dataset).columns() [:id, :album_id] end
|
1088
|
+
GraphAlbum.one_to_one :ltrack, :clone=>:track, :class=>sub
|
1089
|
+
ds = GraphAlbum.eager_graph_with_options(:ltrack, :limit_strategy=>true)
|
1090
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, ltrack.id AS ltrack_id, ltrack.album_id FROM albums LEFT OUTER JOIN (SELECT id, album_id FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x = 1)) AS ltrack ON (ltrack.album_id = albums.id)'
|
1091
|
+
ds._fetch = {:id=>1, :band_id=>2, :ltrack_id=>3, :album_id=>1}
|
1092
|
+
a = ds.all
|
1093
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1094
|
+
a.first.ltrack.should == sub.load(:id => 3, :album_id=>1)
|
1095
|
+
end
|
1096
|
+
|
942
1097
|
it "should eagerly load a single one_to_many association" do
|
943
1098
|
ds = GraphAlbum.eager_graph(:tracks)
|
944
1099
|
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)'
|
@@ -948,6 +1103,19 @@ describe Sequel::Model, "#eager_graph" do
|
|
948
1103
|
a.first.tracks.should == [GraphTrack.load(:id => 3, :album_id=>1)]
|
949
1104
|
end
|
950
1105
|
|
1106
|
+
it "should eagerly graph a single one_to_many association using the :window_function strategy" do
|
1107
|
+
sub = Class.new(GraphTrack)
|
1108
|
+
def (sub.dataset).supports_window_functions?() true end
|
1109
|
+
def (sub.dataset).columns() [:id, :album_id] end
|
1110
|
+
GraphAlbum.one_to_many :ltracks, :clone=>:tracks, :limit=>2, :class=>sub
|
1111
|
+
ds = GraphAlbum.eager_graph_with_options(:ltracks, :limit_strategy=>true)
|
1112
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, ltracks.id AS ltracks_id, ltracks.album_id FROM albums LEFT OUTER JOIN (SELECT id, album_id FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x <= 2)) AS ltracks ON (ltracks.album_id = albums.id)'
|
1113
|
+
ds._fetch = {:id=>1, :band_id=>2, :ltracks_id=>3, :album_id=>1}
|
1114
|
+
a = ds.all
|
1115
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1116
|
+
a.first.ltracks.should == [sub.load(:id => 3, :album_id=>1)]
|
1117
|
+
end
|
1118
|
+
|
951
1119
|
it "should eagerly load a single many_to_many association" do
|
952
1120
|
ds = GraphAlbum.eager_graph(:genres)
|
953
1121
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
|
@@ -957,11 +1125,62 @@ describe Sequel::Model, "#eager_graph" do
|
|
957
1125
|
a.first.genres.should == [GraphGenre.load(:id => 4)]
|
958
1126
|
end
|
959
1127
|
|
960
|
-
it "should
|
1128
|
+
it "should eagerly graph a single many_to_many association using the :window_function strategy" do
|
1129
|
+
sub = Class.new(GraphGenre)
|
1130
|
+
def (sub.dataset).supports_window_functions?() true end
|
1131
|
+
def (sub.dataset).columns() literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
|
1132
|
+
GraphAlbum.many_to_many :lgenres, :clone=>:genres, :class=>sub, :limit=>2
|
1133
|
+
ds = GraphAlbum.eager_graph_with_options(:lgenres, :limit_strategy=>true)
|
1134
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, lgenres.id AS lgenres_id FROM albums LEFT OUTER JOIN (SELECT id, x_foreign_key_x 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)) AS t1 WHERE (x_sequel_row_number_x <= 2)) AS lgenres ON (lgenres.x_foreign_key_x = albums.id)'
|
1135
|
+
ds._fetch = {:id=>1, :band_id=>2, :lgenres_id=>4}
|
1136
|
+
a = ds.all
|
1137
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1138
|
+
a.first.lgenres.should == [sub.load(:id => 4)]
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
it "should eagerly load a single one_through_one association" do
|
1142
|
+
ds = GraphAlbum.eager_graph(:genre)
|
1143
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genre.id AS genre_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genre ON (genre.id = ag.genre_id)'
|
1144
|
+
ds._fetch = {:id=>1, :band_id=>2, :genre_id=>4}
|
1145
|
+
a = ds.all
|
1146
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1147
|
+
a.first.genre.should == GraphGenre.load(:id => 4)
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
it "should eagerly graph a single one_through_one association using the :distinct_on strategy" do
|
1151
|
+
sub = Class.new(GraphGenre)
|
1152
|
+
def (sub.dataset).supports_distinct_on?() true end
|
1153
|
+
def (sub.dataset).columns() [:id] end
|
1154
|
+
GraphAlbum.one_through_one :lgenre, :clone=>:genre, :class=>sub
|
1155
|
+
ds = GraphAlbum.eager_graph_with_options(:lgenre, :limit_strategy=>true)
|
1156
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, lgenre.id AS lgenre_id FROM albums LEFT OUTER JOIN (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) ORDER BY ag.album_id) AS lgenre ON (lgenre.x_foreign_key_x = albums.id)'
|
1157
|
+
ds._fetch = {:id=>1, :band_id=>2, :lgenre_id=>4}
|
1158
|
+
a = ds.all
|
1159
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1160
|
+
a.first.lgenre.should == sub.load(:id => 4)
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
it "should eagerly graph a single one_through_one association using the :window_function strategy" do
|
1164
|
+
sub = Class.new(GraphGenre)
|
1165
|
+
def (sub.dataset).supports_window_functions?() true end
|
1166
|
+
def (sub.dataset).columns() literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
|
1167
|
+
GraphAlbum.one_through_one :lgenre, :clone=>:genre, :class=>sub
|
1168
|
+
ds = GraphAlbum.eager_graph_with_options(:lgenre, :limit_strategy=>true)
|
1169
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, lgenre.id AS lgenre_id FROM albums LEFT OUTER JOIN (SELECT id, x_foreign_key_x 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)) AS t1 WHERE (x_sequel_row_number_x = 1)) AS lgenre ON (lgenre.x_foreign_key_x = albums.id)'
|
1170
|
+
ds._fetch = {:id=>1, :band_id=>2, :lgenre_id=>4}
|
1171
|
+
a = ds.all
|
1172
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1173
|
+
a.first.lgenre.should == sub.load(:id => 4)
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
it "should correctly handle an aliased join table in many_to_many and one_through_one" do
|
961
1177
|
c = Class.new(GraphAlbum)
|
962
1178
|
c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___ga
|
963
1179
|
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS ga ON (ga.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ga.genre_id)'
|
964
1180
|
|
1181
|
+
c.many_to_many :genre, :clone=>:genre, :join_table=>:ag___ga
|
1182
|
+
c.eager_graph(:genre).sql.should == 'SELECT albums.id, albums.band_id, genre.id AS genre_id FROM albums LEFT OUTER JOIN ag AS ga ON (ga.album_id = albums.id) LEFT OUTER JOIN genres AS genre ON (genre.id = ga.genre_id)'
|
1183
|
+
|
965
1184
|
c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___albums
|
966
1185
|
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS albums_0 ON (albums_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = albums_0.genre_id)'
|
967
1186
|
|
@@ -969,6 +1188,10 @@ describe Sequel::Model, "#eager_graph" do
|
|
969
1188
|
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS genres_0 ON (genres_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = genres_0.genre_id)'
|
970
1189
|
end
|
971
1190
|
|
1191
|
+
it "should handle multiple associations in a single call to association_join" do
|
1192
|
+
GraphAlbum.association_join(:genres, :tracks, :band).sql.should == 'SELECT * FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres ON (genres.id = ag.genre_id) INNER JOIN tracks ON (tracks.album_id = albums.id) INNER JOIN bands AS band ON (band.id = albums.band_id)'
|
1193
|
+
end
|
1194
|
+
|
972
1195
|
it "should eagerly load multiple associations in a single call" do
|
973
1196
|
ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
|
974
1197
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
@@ -981,6 +1204,28 @@ describe Sequel::Model, "#eager_graph" do
|
|
981
1204
|
a.genres.should == [GraphGenre.load(:id => 4)]
|
982
1205
|
end
|
983
1206
|
|
1207
|
+
it "should eagerly load multiple associations with different limit strategies in a single call" do
|
1208
|
+
subg = Class.new(GraphGenre)
|
1209
|
+
def (subg.dataset).supports_distinct_on?() true end
|
1210
|
+
def (subg.dataset).supports_window_functions?() true end
|
1211
|
+
def (subg.dataset).columns() literal(opts[:select]) =~ /x_foreign_key_x/ ? [:id, :x_foreign_key_x] : [:id] end
|
1212
|
+
GraphAlbum.one_through_one :lgenre, :clone=>:genre, :class=>subg
|
1213
|
+
GraphAlbum.many_to_many :lgenres, :clone=>:genres, :class=>subg, :limit=>2
|
1214
|
+
|
1215
|
+
ds = GraphAlbum.eager_graph_with_options([:lgenre, :lgenres], :limit_strategy=>{:lgenre=>:distinct_on, :lgenres=>:window_function})
|
1216
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, lgenre.id AS lgenre_id, lgenres.id AS lgenres_id FROM albums LEFT OUTER JOIN (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) ORDER BY ag.album_id) AS lgenre ON (lgenre.x_foreign_key_x = albums.id) LEFT OUTER JOIN (SELECT id, x_foreign_key_x 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)) AS t1 WHERE (x_sequel_row_number_x <= 2)) AS lgenres ON (lgenres.x_foreign_key_x = albums.id)'
|
1217
|
+
ds._fetch = {:id=>1, :band_id=>2, :lgenres_id=>4, :lgenre_id=>3}
|
1218
|
+
a = ds.all
|
1219
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1220
|
+
a = a.first
|
1221
|
+
a.lgenre.should == subg.load(:id => 3)
|
1222
|
+
a.lgenres.should == [subg.load(:id => 4)]
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
it "should handle multiple associations in separate calls to association_join" do
|
1226
|
+
GraphAlbum.association_join(:genres).association_join(:tracks).association_join(:band).sql.should == 'SELECT * FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres ON (genres.id = ag.genre_id) INNER JOIN tracks ON (tracks.album_id = albums.id) INNER JOIN bands AS band ON (band.id = albums.band_id)'
|
1227
|
+
end
|
1228
|
+
|
984
1229
|
it "should eagerly load multiple associations in separate calls" do
|
985
1230
|
ds = GraphAlbum.eager_graph(:genres).eager_graph(:tracks).eager_graph(:band)
|
986
1231
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
@@ -993,6 +1238,15 @@ describe Sequel::Model, "#eager_graph" do
|
|
993
1238
|
a.genres.should == [GraphGenre.load(:id => 4)]
|
994
1239
|
end
|
995
1240
|
|
1241
|
+
it "should handle cascading associations in a single call to association_join" do
|
1242
|
+
GraphTrack.association_join(:album=>{:band=>:members}).sql.should == 'SELECT * FROM tracks INNER JOIN albums AS album ON (album.id = tracks.album_id) INNER JOIN bands AS band ON (band.id = album.band_id) INNER JOIN bm ON (bm.band_id = band.id) INNER JOIN members ON (members.id = bm.member_id)'
|
1243
|
+
GraphBand.association_join({:albums=>:tracks}, :members).sql.should == 'SELECT * FROM bands INNER JOIN albums ON (albums.band_id = bands.id) INNER JOIN tracks ON (tracks.album_id = albums.id) INNER JOIN bm ON (bm.band_id = bands.id) INNER JOIN members ON (members.id = bm.member_id)'
|
1244
|
+
end
|
1245
|
+
|
1246
|
+
it "should handle matching association names for different models when using association_join" do
|
1247
|
+
GraphAlbum.association_join(:genres).association_join(:band=>:genres).sql.should == 'SELECT * FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres ON (genres.id = ag.genre_id) INNER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN bg ON (bg.band_id = band.id) INNER JOIN genres AS genres_0 ON (genres_0.id = bg.genre_id)'
|
1248
|
+
end
|
1249
|
+
|
996
1250
|
it "should allow cascading of eager loading for associations of associated models" do
|
997
1251
|
ds = GraphTrack.eager_graph(:album=>{:band=>:members})
|
998
1252
|
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
@@ -1125,6 +1379,15 @@ describe Sequel::Model, "#eager_graph" do
|
|
1125
1379
|
a.first.band.should == nil
|
1126
1380
|
end
|
1127
1381
|
|
1382
|
+
it "should handle no associated records for a single one_to_one association" do
|
1383
|
+
ds = GraphAlbum.eager_graph(:track)
|
1384
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, track.id AS track_id, track.album_id FROM albums LEFT OUTER JOIN tracks AS track ON (track.album_id = albums.id)'
|
1385
|
+
ds._fetch = {:id=>1, :band_id=>2, :track_id=>nil, :album_id=>nil}
|
1386
|
+
a = ds.all
|
1387
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1388
|
+
a.first.track.should == nil
|
1389
|
+
end
|
1390
|
+
|
1128
1391
|
it "should handle no associated records for a single one_to_many association" do
|
1129
1392
|
ds = GraphAlbum.eager_graph(:tracks)
|
1130
1393
|
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)'
|
@@ -1134,6 +1397,15 @@ describe Sequel::Model, "#eager_graph" do
|
|
1134
1397
|
a.first.tracks.should == []
|
1135
1398
|
end
|
1136
1399
|
|
1400
|
+
it "should handle no associated records for a single one_through_one association" do
|
1401
|
+
ds = GraphAlbum.eager_graph(:genre)
|
1402
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genre.id AS genre_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genre ON (genre.id = ag.genre_id)'
|
1403
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>nil}
|
1404
|
+
a = ds.all
|
1405
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1406
|
+
a.first.genre.should == nil
|
1407
|
+
end
|
1408
|
+
|
1137
1409
|
it "should handle no associated records for a single many_to_many association" do
|
1138
1410
|
ds = GraphAlbum.eager_graph(:genres)
|
1139
1411
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
|
@@ -1391,6 +1663,11 @@ describe Sequel::Model, "#eager_graph" do
|
|
1391
1663
|
GraphAlbum.order(:band_id).eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.id) ORDER BY band_id, right_tracks.id, right_tracks.album_id'
|
1392
1664
|
end
|
1393
1665
|
|
1666
|
+
it "should use the association's :graph_order in preference or order" do
|
1667
|
+
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :order=>[:tracks__id, :tracks__album_id], :graph_order=>[:id, :album_id]
|
1668
|
+
GraphAlbum.order(:band_id).eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.id) ORDER BY band_id, right_tracks.id, right_tracks.album_id'
|
1669
|
+
end
|
1670
|
+
|
1394
1671
|
it "should add the association's :order for cascading associations" do
|
1395
1672
|
GraphBand.one_to_many :a_albums, :class=>'GraphAlbum', :key=>:band_id, :order=>:name, :reciprocal=>nil
|
1396
1673
|
GraphAlbum.one_to_many :b_tracks, :class=>'GraphTrack', :key=>:album_id, :order=>[:id, :album_id]
|
@@ -1480,6 +1757,48 @@ describe Sequel::Model, "#eager_graph" do
|
|
1480
1757
|
a.al_genres.should == [GraphGenre.load(:id=>7), GraphGenre.load(:id=>12)]
|
1481
1758
|
end
|
1482
1759
|
|
1760
|
+
it "should handle offsets on associations with no results when eager graphing" do
|
1761
|
+
GraphAlbum.one_to_many :al_tracks, :class=>GraphTrack, :key=>:album_id, :limit=>[2, 1]
|
1762
|
+
ds = GraphAlbum.eager_graph(:al_tracks)
|
1763
|
+
ds.sql.should == "SELECT albums.id, albums.band_id, al_tracks.id AS al_tracks_id, al_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id)"
|
1764
|
+
ds._fetch = [{:id=>1, :band_id=>2, :al_tracks_id=>nil, :album_id=>nil}]
|
1765
|
+
a = ds.all.first
|
1766
|
+
a.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
1767
|
+
a.al_tracks.should == []
|
1768
|
+
end
|
1769
|
+
|
1770
|
+
it "should respect offsets on associations when eager graphing" do
|
1771
|
+
GraphAlbum.many_to_one :al_band, :class=>GraphBand, :key=>:band_id
|
1772
|
+
GraphAlbum.one_to_many :al_tracks, :class=>GraphTrack, :key=>:album_id, :limit=>[1, 1]
|
1773
|
+
GraphAlbum.many_to_many :al_genres, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[1,1]
|
1774
|
+
ds = GraphAlbum.eager_graph(:al_band, :al_tracks, :al_genres)
|
1775
|
+
ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_tracks.id AS al_tracks_id, al_tracks.album_id, al_genres.id AS al_genres_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genres ON (al_genres.id = ag.genre_id)"
|
1776
|
+
ds._fetch = [{:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7},
|
1777
|
+
{:id=>1, :band_id=>2, :al_band_id=>8, :vocalist_id=>9, :al_tracks_id=>10, :album_id=>11, :al_genres_id=>12},
|
1778
|
+
{:id=>1, :band_id=>2, :al_band_id=>13, :vocalist_id=>14, :al_tracks_id=>15, :album_id=>16, :al_genres_id=>17}]
|
1779
|
+
a = ds.all.first
|
1780
|
+
a.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
1781
|
+
a.al_band.should == GraphBand.load(:id=>3, :vocalist_id=>4)
|
1782
|
+
a.al_tracks.should == [GraphTrack.load(:id=>10, :album_id=>11)]
|
1783
|
+
a.al_genres.should == [GraphGenre.load(:id=>12)]
|
1784
|
+
end
|
1785
|
+
|
1786
|
+
it "should respect offsets on associations when eager graphing one_to_one and one_through_one associations" do
|
1787
|
+
GraphAlbum.many_to_one :al_band, :class=>GraphBand, :key=>:band_id
|
1788
|
+
GraphAlbum.one_to_one :al_track, :class=>GraphTrack, :key=>:album_id, :limit=>[nil, 1]
|
1789
|
+
GraphAlbum.one_through_one :al_genre, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[nil,1]
|
1790
|
+
ds = GraphAlbum.eager_graph(:al_band, :al_track, :al_genre)
|
1791
|
+
ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_track.id AS al_track_id, al_track.album_id, al_genre.id AS al_genre_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_track ON (al_track.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genre ON (al_genre.id = ag.genre_id)"
|
1792
|
+
ds._fetch = [{:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_track_id=>5, :album_id=>6, :al_genre_id=>7},
|
1793
|
+
{:id=>1, :band_id=>2, :al_band_id=>8, :vocalist_id=>9, :al_track_id=>10, :album_id=>11, :al_genre_id=>12},
|
1794
|
+
{:id=>1, :band_id=>2, :al_band_id=>13, :vocalist_id=>14, :al_track_id=>15, :album_id=>16, :al_genre_id=>17}]
|
1795
|
+
a = ds.all.first
|
1796
|
+
a.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
1797
|
+
a.al_band.should == GraphBand.load(:id=>3, :vocalist_id=>4)
|
1798
|
+
a.al_track.should == GraphTrack.load(:id=>10, :album_id=>11)
|
1799
|
+
a.al_genre.should == GraphGenre.load(:id=>12)
|
1800
|
+
end
|
1801
|
+
|
1483
1802
|
it "should eagerly load a many_to_one association with a custom callback" do
|
1484
1803
|
ds = GraphAlbum.eager_graph(:band => proc {|ds1| ds1.select(:id).columns(:id)})
|
1485
1804
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0 FROM albums LEFT OUTER JOIN (SELECT id FROM bands) AS band ON (band.id = albums.band_id)'
|
@@ -1490,7 +1809,6 @@ describe Sequel::Model, "#eager_graph" do
|
|
1490
1809
|
end
|
1491
1810
|
|
1492
1811
|
it "should eagerly load a one_to_one association with a custom callback" do
|
1493
|
-
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
1494
1812
|
ds = GraphAlbum.eager_graph(:track => proc {|ds1| ds1.select(:album_id).columns(:album_id)})
|
1495
1813
|
ds.sql.should == 'SELECT albums.id, albums.band_id, track.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS track ON (track.album_id = albums.id)'
|
1496
1814
|
ds._fetch = {:id=>1, :band_id=>2, :album_id=>1}
|
@@ -1508,6 +1826,15 @@ describe Sequel::Model, "#eager_graph" do
|
|
1508
1826
|
a.first.tracks.should == [GraphTrack.load(:album_id=>1)]
|
1509
1827
|
end
|
1510
1828
|
|
1829
|
+
it "should eagerly load a one_through_one association with a custom callback" do
|
1830
|
+
ds = GraphAlbum.eager_graph(:genre => proc {|ds1| ds1.select(:id).columns(:id)})
|
1831
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genre.id AS genre_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN (SELECT id FROM genres) AS genre ON (genre.id = ag.genre_id)'
|
1832
|
+
ds._fetch = {:id=>1, :band_id=>2, :genre_id=>4}
|
1833
|
+
a = ds.all
|
1834
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
1835
|
+
a.first.genre.should == GraphGenre.load(:id => 4)
|
1836
|
+
end
|
1837
|
+
|
1511
1838
|
it "should eagerly load a many_to_many association with a custom callback" do
|
1512
1839
|
ds = GraphAlbum.eager_graph(:genres => proc {|ds1| ds1.select(:id).columns(:id)})
|
1513
1840
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN (SELECT id FROM genres) AS genres ON (genres.id = ag.genre_id)'
|