sequel 4.7.0 → 4.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)'
|