sequel 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -0
  3. data/README.rdoc +7 -7
  4. data/Rakefile +2 -2
  5. data/doc/active_record.rdoc +2 -2
  6. data/doc/association_basics.rdoc +21 -7
  7. data/doc/bin_sequel.rdoc +2 -2
  8. data/doc/cheat_sheet.rdoc +2 -1
  9. data/doc/dataset_basics.rdoc +1 -1
  10. data/doc/dataset_filtering.rdoc +1 -1
  11. data/doc/migration.rdoc +2 -2
  12. data/doc/object_model.rdoc +2 -2
  13. data/doc/opening_databases.rdoc +13 -1
  14. data/doc/querying.rdoc +9 -4
  15. data/doc/release_notes/4.4.0.txt +92 -0
  16. data/doc/schema_modification.rdoc +1 -1
  17. data/doc/security.rdoc +2 -2
  18. data/doc/sql.rdoc +3 -3
  19. data/doc/thread_safety.rdoc +1 -1
  20. data/doc/validations.rdoc +1 -1
  21. data/doc/virtual_rows.rdoc +1 -1
  22. data/lib/sequel/adapters/jdbc.rb +85 -19
  23. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  24. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  25. data/lib/sequel/adapters/jdbc/h2.rb +2 -2
  26. data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
  27. data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  29. data/lib/sequel/adapters/jdbc/postgresql.rb +34 -3
  30. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +57 -0
  31. data/lib/sequel/adapters/jdbc/sqlserver.rb +2 -2
  32. data/lib/sequel/adapters/oracle.rb +1 -1
  33. data/lib/sequel/adapters/shared/db2.rb +5 -0
  34. data/lib/sequel/adapters/shared/oracle.rb +41 -4
  35. data/lib/sequel/adapters/shared/sqlanywhere.rb +458 -0
  36. data/lib/sequel/adapters/sqlanywhere.rb +177 -0
  37. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +11 -3
  38. data/lib/sequel/core.rb +4 -4
  39. data/lib/sequel/database/connecting.rb +1 -1
  40. data/lib/sequel/database/query.rb +1 -1
  41. data/lib/sequel/database/schema_generator.rb +1 -1
  42. data/lib/sequel/database/schema_methods.rb +2 -2
  43. data/lib/sequel/dataset.rb +1 -1
  44. data/lib/sequel/dataset/actions.rb +2 -0
  45. data/lib/sequel/dataset/graph.rb +1 -1
  46. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  47. data/lib/sequel/dataset/query.rb +37 -16
  48. data/lib/sequel/extensions/constraint_validations.rb +1 -1
  49. data/lib/sequel/extensions/date_arithmetic.rb +2 -2
  50. data/lib/sequel/extensions/migration.rb +1 -1
  51. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +5 -4
  52. data/lib/sequel/extensions/pg_array.rb +2 -2
  53. data/lib/sequel/extensions/pg_array_ops.rb +2 -2
  54. data/lib/sequel/extensions/pg_hstore.rb +2 -2
  55. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  56. data/lib/sequel/extensions/pg_json.rb +2 -2
  57. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  58. data/lib/sequel/extensions/pg_range.rb +2 -2
  59. data/lib/sequel/extensions/pg_range_ops.rb +2 -2
  60. data/lib/sequel/extensions/pg_row.rb +2 -2
  61. data/lib/sequel/extensions/pg_row_ops.rb +3 -3
  62. data/lib/sequel/model.rb +1 -1
  63. data/lib/sequel/model/associations.rb +106 -17
  64. data/lib/sequel/model/base.rb +23 -19
  65. data/lib/sequel/plugins/json_serializer.rb +1 -1
  66. data/lib/sequel/plugins/many_through_many.rb +14 -6
  67. data/lib/sequel/plugins/pg_array_associations.rb +28 -0
  68. data/lib/sequel/plugins/rcte_tree.rb +1 -1
  69. data/lib/sequel/plugins/serialization.rb +11 -0
  70. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  71. data/lib/sequel/plugins/table_select.rb +41 -0
  72. data/lib/sequel/plugins/tree.rb +1 -1
  73. data/lib/sequel/sql.rb +2 -2
  74. data/lib/sequel/version.rb +1 -1
  75. data/spec/adapters/oracle_spec.rb +22 -1
  76. data/spec/adapters/postgres_spec.rb +31 -48
  77. data/spec/adapters/sqlanywhere_spec.rb +170 -0
  78. data/spec/core/dataset_spec.rb +109 -0
  79. data/spec/core/object_graph_spec.rb +7 -0
  80. data/spec/extensions/constraint_validations_spec.rb +7 -0
  81. data/spec/extensions/core_refinements_spec.rb +1 -1
  82. data/spec/extensions/many_through_many_spec.rb +65 -0
  83. data/spec/extensions/pg_array_associations_spec.rb +44 -0
  84. data/spec/extensions/rcte_tree_spec.rb +3 -3
  85. data/spec/extensions/spec_helper.rb +1 -1
  86. data/spec/extensions/table_select_spec.rb +71 -0
  87. data/spec/integration/associations_test.rb +279 -7
  88. data/spec/integration/dataset_test.rb +13 -4
  89. data/spec/integration/schema_test.rb +12 -14
  90. data/spec/model/associations_spec.rb +472 -3
  91. data/spec/model/class_dataset_methods_spec.rb +1 -0
  92. data/spec/model/model_spec.rb +10 -0
  93. metadata +10 -2
@@ -157,6 +157,15 @@ describe "Simple Dataset operations" do
157
157
  @ds.order(:id).limit(2, 0).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
158
158
  @ds.order(:id).limit(2, 1).all.should == [{:id=>2, :number=>20}]
159
159
  end
160
+
161
+ specify "should fetch correctly with a limit and offset using seperate methods" do
162
+ @ds.order(:id).limit(2).offset(0).all.should == [{:id=>1, :number=>10}]
163
+ @ds.order(:id).limit(2).offset(1).all.should == []
164
+ @ds.insert(:number=>20)
165
+ @ds.order(:id).limit(1).offset(1).all.should == [{:id=>2, :number=>20}]
166
+ @ds.order(:id).limit(2).offset(0).all.should == [{:id=>1, :number=>10}, {:id=>2, :number=>20}]
167
+ @ds.order(:id).limit(2).offset(1).all.should == [{:id=>2, :number=>20}]
168
+ end
160
169
 
161
170
  specify "should provide correct columns when using a limit and offset" do
162
171
  ds = @ds.order(:id).limit(1, 1)
@@ -251,7 +260,7 @@ describe "Simple dataset operations with nasty table names" do
251
260
  @db.quote_identifiers = @qi
252
261
  end
253
262
 
254
- cspecify "should work correctly", :mssql, :oracle do
263
+ cspecify "should work correctly", :mssql, :oracle, :sqlanywhere do
255
264
  @db.create_table!(@table) do
256
265
  primary_key :id
257
266
  Integer :number
@@ -375,7 +384,7 @@ describe Sequel::Database do
375
384
  DB.get(Sequel.cast(Sequel.blob(""), File).as(:a)).should == ""
376
385
  end
377
386
 
378
- cspecify "should properly escape identifiers", :db2, :oracle do
387
+ cspecify "should properly escape identifiers", :db2, :oracle, :sqlanywhere do
379
388
  DB.create_table(:"\\'\"[]"){Integer :id}
380
389
  DB.drop_table(:"\\'\"[]")
381
390
  end
@@ -1339,7 +1348,7 @@ describe "Sequel::Dataset DSL support" do
1339
1348
  @ds.filter([:a, :b]=>[]).all.should == []
1340
1349
  @ds.exclude([:a, :b]=>[]).all.should == []
1341
1350
 
1342
- unless Sequel.guarded?(:mssql, :oracle, :db2)
1351
+ unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1343
1352
  # Some databases don't like boolean results in the select list
1344
1353
  pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1345
1354
  pr[@ds.get(Sequel.expr(:a=>[]))].should == nil
@@ -1357,7 +1366,7 @@ describe "Sequel::Dataset DSL support" do
1357
1366
  ds.filter([:a, :b]=>[]).all.should == []
1358
1367
  ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
1359
1368
 
1360
- unless Sequel.guarded?(:mssql, :oracle, :db2)
1369
+ unless Sequel.guarded?(:mssql, :oracle, :db2, :sqlanywhere)
1361
1370
  # Some databases don't like boolean results in the select list
1362
1371
  pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1363
1372
  pr[ds.get(Sequel.expr(:a=>[]))].should == false
@@ -206,7 +206,7 @@ describe "Database foreign key parsing" do
206
206
  end
207
207
 
208
208
  specify "should parse foreign key information into an array of hashes" do
209
- @db.create_table!(:a, :engine=>:InnoDB){primary_key :c; Integer :d; index :d, :unique=>true}
209
+ @db.create_table!(:a, :engine=>:InnoDB){primary_key :c; Integer :d, :null => false, :unique => true}
210
210
  @db.create_table!(:b, :engine=>:InnoDB){foreign_key :e, :a}
211
211
  @pr[:a]
212
212
  @pr[:b, [[:e], :a, [:pk, :c]]]
@@ -217,7 +217,7 @@ describe "Database foreign key parsing" do
217
217
  @db.alter_table(:b){add_foreign_key [:f], :a, :key=>[:c]}
218
218
  @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]]]
219
219
 
220
- @db.alter_table(:a){add_index [:d, :c], :unique=>true}
220
+ @db.alter_table(:a){add_unique_constraint [:d, :c]}
221
221
  @db.alter_table(:b){add_foreign_key [:f, :e], :a, :key=>[:d, :c]}
222
222
  @pr[:b, [[:e], :a, [:pk, :c]], [[:f], :a, [:c]], [[:f], :a, [:d]], [[:f, :e], :a, [:d, :c]]]
223
223
 
@@ -232,9 +232,9 @@ describe "Database foreign key parsing" do
232
232
  end
233
233
 
234
234
  specify "should handle composite foreign and primary keys" do
235
- @db.create_table!(:a, :engine=>:InnoDB){Integer :b; Integer :c; primary_key [:b, :c]; index [:c, :b], :unique=>true}
236
- @db.create_table!(:b, :engine=>:InnoDB){Integer :e; Integer :f; foreign_key [:e, :f], :a; foreign_key [:f, :e], :a, :key=>[:c, :b]}
237
- @pr[:b, [[:e, :f], :a, [:pk, :b, :c]], [[:f, :e], :a, [:c, :b]]]
235
+ @db.create_table!(:a, :engine=>:InnoDB){Integer :b, :null=>false; Integer :c, :null=>false; Integer :d, :null=>false; primary_key [:b, :c]; unique [:d, :c]}
236
+ @db.create_table!(:b, :engine=>:InnoDB){Integer :e, :null=>false; Integer :f, :null=>false; Integer :g, :null=>false; foreign_key [:e, :f], :a; foreign_key [:g, :f], :a, :key=>[:d, :c]}
237
+ @pr[:b, [[:e, :f], :a, [:pk, :b, :c]], [[:g, :f], :a, [:d, :c]]]
238
238
  end
239
239
  end if DB.supports_foreign_key_parsing?
240
240
 
@@ -400,7 +400,7 @@ describe "Database schema modifiers" do
400
400
  @ds.all.should == [{:number=>10, :name=>nil}]
401
401
  end
402
402
 
403
- cspecify "should add primary key columns to tables correctly", :h2, :derby do
403
+ cspecify "should add primary key columns to tables correctly", :derby do
404
404
  @db.create_table!(:items){Integer :number}
405
405
  @ds.insert(:number=>10)
406
406
  @db.alter_table(:items){add_primary_key :id}
@@ -418,7 +418,7 @@ describe "Database schema modifiers" do
418
418
  proc{@ds.insert(10)}.should_not raise_error
419
419
  end
420
420
 
421
- cspecify "should add foreign key columns to tables correctly", :hsqldb do
421
+ specify "should add foreign key columns to tables correctly" do
422
422
  @db.create_table!(:items){primary_key :id}
423
423
  @ds.insert
424
424
  i = @ds.get(:id)
@@ -545,7 +545,7 @@ describe "Database schema modifiers" do
545
545
  end
546
546
 
547
547
  specify "should add unnamed unique constraints and foreign key table constraints correctly" do
548
- @db.create_table!(:items, :engine=>:InnoDB){Integer :id; Integer :item_id}
548
+ @db.create_table!(:items, :engine=>:InnoDB){Integer :id, :null => false; Integer :item_id, :null => false}
549
549
  @db.alter_table(:items) do
550
550
  add_unique_constraint [:item_id, :id]
551
551
  add_foreign_key [:id, :item_id], :items, :key=>[:item_id, :id]
@@ -607,18 +607,16 @@ describe "Database schema modifiers" do
607
607
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id]
608
608
  end
609
609
 
610
- cspecify "should remove foreign key columns from tables correctly", :h2, :mssql, :hsqldb do
611
- # MySQL with InnoDB cannot drop foreign key columns unless you know the
612
- # name of the constraint, see Bug #14347
613
- @db.create_table!(:items, :engine=>:MyISAM) do
610
+ specify "should remove foreign key columns from tables correctly" do
611
+ @db.create_table!(:items, :engine=>:InnoDB) do
614
612
  primary_key :id
615
613
  Integer :i
616
614
  foreign_key :item_id, :items
617
615
  end
618
616
  @ds.insert(:i=>10)
619
- @db.drop_column(:items, :item_id)
617
+ @db.alter_table(:items){drop_foreign_key :item_id}
620
618
  @db.schema(:items, :reload=>true).map{|x| x.first}.should == [:id, :i]
621
- end
619
+ end if DB.supports_foreign_key_parsing?
622
620
 
623
621
  specify "should remove multiple columns in a single alter_table block" do
624
622
  @db.create_table!(:items) do
@@ -106,6 +106,7 @@ describe Sequel::Model, "associate" do
106
106
  klass.many_to_one :par, :clone=>:par_parent, :select=>:b
107
107
  klass.one_to_many :par1s, :clone=>:par_parent1s, :order=>:b, :limit=>10, :block=>nil
108
108
  klass.many_to_many(:par2s, :clone=>:par_parent2s, :order=>:c){3}
109
+ klass.many_to_one :par3, :clone=>:par
109
110
 
110
111
  klass.association_reflection(:par).associated_class.should == ParParent
111
112
  klass.association_reflection(:par1s).associated_class.should == ParParent
@@ -114,12 +115,16 @@ describe Sequel::Model, "associate" do
114
115
  klass.association_reflection(:par)[:order].should == :a
115
116
  klass.association_reflection(:par).select.should == :b
116
117
  klass.association_reflection(:par)[:block].call.should == 1
118
+ klass.association_reflection(:par)[:eager_block].call.should == 1
117
119
  klass.association_reflection(:par1s)[:limit].should == 10
118
120
  klass.association_reflection(:par1s)[:order].should == :b
119
121
  klass.association_reflection(:par1s)[:block].should == nil
120
122
  klass.association_reflection(:par2s)[:after_load].length.should == 1
121
123
  klass.association_reflection(:par2s)[:order].should == :c
122
124
  klass.association_reflection(:par2s)[:block].call.should == 3
125
+
126
+ klass.association_reflection(:par3)[:block].call.should == 1
127
+ klass.association_reflection(:par3)[:eager_block].call.should == 1
123
128
  ensure
124
129
  Object.send(:remove_const, :ParParent)
125
130
  end
@@ -2594,7 +2599,7 @@ describe Sequel::Model, "many_to_many" do
2594
2599
  end
2595
2600
 
2596
2601
  describe "Filtering by associations" do
2597
- before do
2602
+ before(:all) do
2598
2603
  @Album = Class.new(Sequel::Model(:albums))
2599
2604
  artist = @Artist = Class.new(Sequel::Model(:artists))
2600
2605
  tag = @Tag = Class.new(Sequel::Model(:tags))
@@ -2606,15 +2611,37 @@ describe "Filtering by associations" do
2606
2611
  @AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
2607
2612
  @Album.class_eval do
2608
2613
  columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
2609
- many_to_one :artist, :class=>artist
2614
+ b = lambda{|ds| ds.where(:name=>'B')}
2615
+
2616
+ many_to_one :artist, :class=>artist, :key=>:artist_id
2610
2617
  one_to_many :tracks, :class=>track, :key=>:album_id
2611
2618
  one_to_one :album_info, :class=>album_info, :key=>:album_id
2612
- many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags
2619
+ many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags, :right_key=>:tag_id
2620
+
2621
+ many_to_one :a_artist, :clone=>:artist, :conditions=>{:name=>'A'}
2622
+ one_to_many :a_tracks, :clone=>:tracks, :conditions=>{:name=>'A'}
2623
+ one_to_one :a_album_info, :clone=>:album_info, :conditions=>{:name=>'A'}
2624
+ many_to_many :a_tags, :clone=>:tags, :conditions=>{:name=>'A'}
2625
+
2626
+ many_to_one :b_artist, :clone=>:artist, &b
2627
+ one_to_many :b_tracks, :clone=>:tracks, &b
2628
+ one_to_one :b_album_info, :clone=>:album_info, &b
2629
+ many_to_many :b_tags, :clone=>:tags, &b
2613
2630
 
2614
2631
  many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
2615
2632
  one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
2616
2633
  one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
2617
2634
  many_to_many :ctags, :class=>tag, :left_key=>[:album_id1, :album_id2], :left_primary_key=>[:id1, :id2], :right_key=>[:tag_id1, :tag_id2], :right_primary_key=>[:tid1, :tid2], :join_table=>:albums_tags
2635
+
2636
+ many_to_one :a_cartist, :clone=>:cartist, :conditions=>{:name=>'A'}
2637
+ one_to_many :a_ctracks, :clone=>:ctracks, :conditions=>{:name=>'A'}
2638
+ one_to_one :a_calbum_info, :clone=>:calbum_info, :conditions=>{:name=>'A'}
2639
+ many_to_many :a_ctags, :clone=>:ctags, :conditions=>{:name=>'A'}
2640
+
2641
+ many_to_one :b_cartist, :clone=>:cartist, &b
2642
+ one_to_many :b_ctracks, :clone=>:ctracks, &b
2643
+ one_to_one :b_calbum_info, :clone=>:calbum_info, &b
2644
+ many_to_many :b_ctags, :clone=>:ctags, &b
2618
2645
  end
2619
2646
  end
2620
2647
 
@@ -2634,6 +2661,38 @@ describe "Filtering by associations" do
2634
2661
  @Album.filter(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL))))'
2635
2662
  end
2636
2663
 
2664
+ it "should be able to filter on many_to_one associations with :conditions" do
2665
+ @Album.filter(:a_artist=>@Artist.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id = 3) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id = 3)))))"
2666
+ end
2667
+
2668
+ it "should be able to filter on one_to_many associations with :conditions" do
2669
+ @Album.filter(:a_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id = 3) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5)))))"
2670
+ end
2671
+
2672
+ it "should be able to filter on one_to_one associations with :conditions" do
2673
+ @Album.filter(:a_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id = 3) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5)))))"
2674
+ end
2675
+
2676
+ it "should be able to filter on many_to_many associations with :conditions" do
2677
+ @Album.filter(:a_tags=>@Tag.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id = 3)))))"
2678
+ end
2679
+
2680
+ it "should be able to filter on many_to_one associations with block" do
2681
+ @Album.filter(:b_artist=>@Artist.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id = 3) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id = 3)))))"
2682
+ end
2683
+
2684
+ it "should be able to filter on one_to_many associations with block" do
2685
+ @Album.filter(:b_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id = 3) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id = 5)))))"
2686
+ end
2687
+
2688
+ it "should be able to filter on one_to_one associations with block" do
2689
+ @Album.filter(:b_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id = 3) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id = 5)))))"
2690
+ end
2691
+
2692
+ it "should be able to filter on many_to_many associations with block" do
2693
+ @Album.filter(:b_tags=>@Tag.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id = 3)))))"
2694
+ end
2695
+
2637
2696
  it "should be able to filter on many_to_one associations with composite keys" do
2638
2697
  @Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4))'
2639
2698
  end
@@ -2650,6 +2709,38 @@ describe "Filtering by associations" do
2650
2709
  @Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
2651
2710
  end
2652
2711
 
2712
+ it "should be able to filter on many_to_one associations with :conditions and composite keys" do
2713
+ @Album.filter(:a_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5)))))"
2714
+ end
2715
+
2716
+ it "should be able to filter on one_to_many associations with :conditions and composite keys" do
2717
+ @Album.filter(:a_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5)))))"
2718
+ end
2719
+
2720
+ it "should be able to filter on one_to_one associations with :conditions and composite keys" do
2721
+ @Album.filter(:a_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5)))))"
2722
+ end
2723
+
2724
+ it "should be able to filter on many_to_many associations with block and composite keys" do
2725
+ @Album.filter(:a_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id = 5)))))"
2726
+ end
2727
+
2728
+ it "should be able to filter on many_to_one associations with block and composite keys" do
2729
+ @Album.filter(:b_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id = 5)))))"
2730
+ end
2731
+
2732
+ it "should be able to filter on one_to_many associations with block and composite keys" do
2733
+ @Album.filter(:b_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id = 5)))))"
2734
+ end
2735
+
2736
+ it "should be able to filter on one_to_one associations with block and composite keys" do
2737
+ @Album.filter(:b_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id = 5)))))"
2738
+ end
2739
+
2740
+ it "should be able to filter on many_to_many associations with block and composite keys" do
2741
+ @Album.filter(:b_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id = 5)))))"
2742
+ end
2743
+
2653
2744
  it "should work inside a complex filter" do
2654
2745
  artist = @Artist.load(:id=>3)
2655
2746
  @Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3))'
@@ -2706,6 +2797,38 @@ describe "Filtering by associations" do
2706
2797
  @Album.exclude(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
2707
2798
  end
2708
2799
 
2800
+ it "should be able to exclude on many_to_one associations with :conditions" do
2801
+ @Album.exclude(:a_artist=>@Artist.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id = 3)))) OR (albums.artist_id IS NULL))"
2802
+ end
2803
+
2804
+ it "should be able to exclude on one_to_many associations with :conditions" do
2805
+ @Album.exclude(:a_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id IS NULL))"
2806
+ end
2807
+
2808
+ it "should be able to exclude on one_to_one associations with :conditions" do
2809
+ @Album.exclude(:a_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id IS NULL))"
2810
+ end
2811
+
2812
+ it "should be able to exclude on many_to_many associations with :conditions" do
2813
+ @Album.exclude(:a_tags=>@Tag.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id = 3)))) OR (albums.id IS NULL))"
2814
+ end
2815
+
2816
+ it "should be able to exclude on many_to_one associations with block" do
2817
+ @Album.exclude(:b_artist=>@Artist.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id = 3)))) OR (albums.artist_id IS NULL))"
2818
+ end
2819
+
2820
+ it "should be able to exclude on one_to_many associations with block" do
2821
+ @Album.exclude(:b_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id = 5)))) OR (albums.id IS NULL))"
2822
+ end
2823
+
2824
+ it "should be able to exclude on one_to_one associations with block" do
2825
+ @Album.exclude(:b_album_info=>@AlbumInfo.load(:id=>5, :album_id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id = 5)))) OR (albums.id IS NULL))"
2826
+ end
2827
+
2828
+ it "should be able to exclude on many_to_many associations with block" do
2829
+ @Album.exclude(:b_tags=>@Tag.load(:id=>3)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id = 3) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id = 3)))) OR (albums.id IS NULL))"
2830
+ end
2831
+
2709
2832
  it "should be able to exclude on many_to_one associations with composite keys" do
2710
2833
  @Album.exclude(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 != 3) OR (albums.artist_id2 != 4) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
2711
2834
  end
@@ -2722,6 +2845,38 @@ describe "Filtering by associations" do
2722
2845
  @Album.exclude(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2723
2846
  end
2724
2847
 
2848
+ it "should be able to exclude on many_to_one associations with :conditions and composite keys" do
2849
+ @Album.exclude(:a_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1 != 3) OR (albums.artist_id2 != 4) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id = 5)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
2850
+ end
2851
+
2852
+ it "should be able to exclude on one_to_many associations with :conditions and composite keys" do
2853
+ @Album.exclude(:a_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2854
+ end
2855
+
2856
+ it "should be able to exclude on one_to_one associations with :conditions and composite keys" do
2857
+ @Album.exclude(:a_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2858
+ end
2859
+
2860
+ it "should be able to exclude on many_to_many associations with block and composite keys" do
2861
+ @Album.exclude(:a_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2862
+ end
2863
+
2864
+ it "should be able to exclude on many_to_one associations with block and composite keys" do
2865
+ @Album.exclude(:b_cartist=>@Artist.load(:id=>5, :id1=>3, :id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1 != 3) OR (albums.artist_id2 != 4) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id = 5)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
2866
+ end
2867
+
2868
+ it "should be able to exclude on one_to_many associations with block and composite keys" do
2869
+ @Album.exclude(:b_ctracks=>@Track.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2870
+ end
2871
+
2872
+ it "should be able to exclude on one_to_one associations with block and composite keys" do
2873
+ @Album.exclude(:b_calbum_info=>@AlbumInfo.load(:id=>5, :album_id1=>3, :album_id2=>4)).sql.should == "SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2874
+ end
2875
+
2876
+ it "should be able to exclude on many_to_many associations with block and composite keys" do
2877
+ @Album.exclude(:b_ctags=>@Tag.load(:id=>5, :tid1=>3, :tid2=>4)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE ((albums_tags.tag_id1 = 3) AND (albums_tags.tag_id2 = 4) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id = 5)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
2878
+ end
2879
+
2725
2880
  it "should be able to filter on multiple many_to_one associations" do
2726
2881
  @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3, 4))'
2727
2882
  end
@@ -2738,6 +2893,38 @@ describe "Filtering by associations" do
2738
2893
  @Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL))))'
2739
2894
  end
2740
2895
 
2896
+ it "should be able to filter on multiple many_to_one associations with :conditions" do
2897
+ @Album.filter(:a_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (3, 4)) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4))))))"
2898
+ end
2899
+
2900
+ it "should be able to filter on multiple one_to_many associations with :conditions" do
2901
+ @Album.filter(:a_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (3, 4)) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6))))))"
2902
+ end
2903
+
2904
+ it "should be able to filter on multiple one_to_one associations with :conditions" do
2905
+ @Album.filter(:a_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (3, 4)) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6))))))"
2906
+ end
2907
+
2908
+ it "should be able to filter on multiple many_to_many associations with :conditions" do
2909
+ @Album.filter(:a_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id IN (3, 4))))))"
2910
+ end
2911
+
2912
+ it "should be able to filter on multiple many_to_one associations with block" do
2913
+ @Album.filter(:b_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (3, 4)) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id IN (3, 4))))))"
2914
+ end
2915
+
2916
+ it "should be able to filter on multiple one_to_many associations with block" do
2917
+ @Album.filter(:b_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (3, 4)) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id IN (5, 6))))))"
2918
+ end
2919
+
2920
+ it "should be able to filter on multiple one_to_one associations with block" do
2921
+ @Album.filter(:b_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (3, 4)) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (5, 6))))))"
2922
+ end
2923
+
2924
+ it "should be able to filter on multiple many_to_many associations with block" do
2925
+ @Album.filter(:b_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id IN (3, 4))))))"
2926
+ end
2927
+
2741
2928
  it "should be able to filter on multiple many_to_one associations with composite keys" do
2742
2929
  @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4), (5, 6)))'
2743
2930
  end
@@ -2754,6 +2941,38 @@ describe "Filtering by associations" do
2754
2941
  @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
2755
2942
  end
2756
2943
 
2944
+ it "should be able to filter on multiple many_to_one associations with :conditions and composite keys" do
2945
+ @Album.filter(:a_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) IN ((3, 4), (5, 6))) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8))))))"
2946
+ end
2947
+
2948
+ it "should be able to filter on multiple one_to_many associations with :conditions and composite keys" do
2949
+ @Album.filter(:a_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN ((3, 4), (5, 6))) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8))))))"
2950
+ end
2951
+
2952
+ it "should be able to filter on multiple one_to_one associations with :conditions and composite keys" do
2953
+ @Album.filter(:a_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN ((3, 4), (5, 6))) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8))))))"
2954
+ end
2955
+
2956
+ it "should be able to filter on multiple many_to_many associations with block and composite keys" do
2957
+ @Album.filter(:a_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id IN (7, 8))))))"
2958
+ end
2959
+
2960
+ it "should be able to filter on multiple many_to_one associations with block and composite keys" do
2961
+ @Album.filter(:b_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) IN ((3, 4), (5, 6))) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id IN (7, 8))))))"
2962
+ end
2963
+
2964
+ it "should be able to filter on multiple one_to_many associations with block and composite keys" do
2965
+ @Album.filter(:b_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN ((3, 4), (5, 6))) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id IN (7, 8))))))"
2966
+ end
2967
+
2968
+ it "should be able to filter on multiple one_to_one associations with block and composite keys" do
2969
+ @Album.filter(:b_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN ((3, 4), (5, 6))) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (7, 8))))))"
2970
+ end
2971
+
2972
+ it "should be able to filter on multiple many_to_many associations with block and composite keys" do
2973
+ @Album.filter(:b_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id IN (7, 8))))))"
2974
+ end
2975
+
2757
2976
  it "should be able to exclude on multiple many_to_one associations" do
2758
2977
  @Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3, 4)) OR (albums.artist_id IS NULL))'
2759
2978
  end
@@ -2770,6 +2989,38 @@ describe "Filtering by associations" do
2770
2989
  @Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
2771
2990
  end
2772
2991
 
2992
+ it "should be able to exclude on multiple many_to_one associations with :conditions" do
2993
+ @Album.exclude(:a_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3, 4)) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (3, 4))))) OR (albums.artist_id IS NULL))"
2994
+ end
2995
+
2996
+ it "should be able to exclude on multiple one_to_many associations with :conditions" do
2997
+ @Album.exclude(:a_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (5, 6))))) OR (albums.id IS NULL))"
2998
+ end
2999
+
3000
+ it "should be able to exclude on multiple one_to_one associations with :conditions" do
3001
+ @Album.exclude(:a_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (5, 6))))) OR (albums.id IS NULL))"
3002
+ end
3003
+
3004
+ it "should be able to exclude on multiple many_to_many associations with :conditions" do
3005
+ @Album.exclude(:a_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id IN (3, 4))))) OR (albums.id IS NULL))"
3006
+ end
3007
+
3008
+ it "should be able to exclude on multiple many_to_one associations with block" do
3009
+ @Album.exclude(:b_artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3, 4)) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id IN (3, 4))))) OR (albums.artist_id IS NULL))"
3010
+ end
3011
+
3012
+ it "should be able to exclude on multiple one_to_many associations with block" do
3013
+ @Album.exclude(:b_tracks=>[@Track.load(:id=>5, :album_id=>3), @Track.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id IN (5, 6))))) OR (albums.id IS NULL))"
3014
+ end
3015
+
3016
+ it "should be able to exclude on multiple one_to_one associations with block" do
3017
+ @Album.exclude(:b_album_info=>[@AlbumInfo.load(:id=>5, :album_id=>3), @AlbumInfo.load(:id=>6, :album_id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (5, 6))))) OR (albums.id IS NULL))"
3018
+ end
3019
+
3020
+ it "should be able to exclude on multiple many_to_many associations with block" do
3021
+ @Album.exclude(:b_tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3, 4)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id IN (3, 4))))) OR (albums.id IS NULL))"
3022
+ end
3023
+
2773
3024
  it "should be able to exclude on multiple many_to_one associations with composite keys" do
2774
3025
  @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4), (5, 6))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
2775
3026
  end
@@ -2786,6 +3037,38 @@ describe "Filtering by associations" do
2786
3037
  @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2787
3038
  end
2788
3039
 
3040
+ it "should be able to exclude on multiple many_to_one associations with :conditions and composite keys" do
3041
+ @Album.exclude(:a_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4), (5, 6))) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (7, 8))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
3042
+ end
3043
+
3044
+ it "should be able to exclude on multiple one_to_many associations with :conditions and composite keys" do
3045
+ @Album.exclude(:a_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3046
+ end
3047
+
3048
+ it "should be able to exclude on multiple one_to_one associations with :conditions and composite keys" do
3049
+ @Album.exclude(:a_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3050
+ end
3051
+
3052
+ it "should be able to exclude on multiple many_to_many associations with block and composite keys" do
3053
+ @Album.exclude(:a_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3054
+ end
3055
+
3056
+ it "should be able to exclude on multiple many_to_one associations with block and composite keys" do
3057
+ @Album.exclude(:b_cartist=>[@Artist.load(:id=>7, :id1=>3, :id2=>4), @Artist.load(:id=>8, :id1=>5, :id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4), (5, 6))) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id IN (7, 8))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
3058
+ end
3059
+
3060
+ it "should be able to exclude on multiple one_to_many associations with block and composite keys" do
3061
+ @Album.exclude(:b_ctracks=>[@Track.load(:id=>7, :album_id1=>3, :album_id2=>4), @Track.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3062
+ end
3063
+
3064
+ it "should be able to exclude on multiple one_to_one associations with block and composite keys" do
3065
+ @Album.exclude(:b_calbum_info=>[@AlbumInfo.load(:id=>7, :album_id1=>3, :album_id2=>4), @AlbumInfo.load(:id=>8, :album_id1=>5, :album_id2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3066
+ end
3067
+
3068
+ it "should be able to exclude on multiple many_to_many associations with block and composite keys" do
3069
+ @Album.exclude(:b_ctags=>[@Tag.load(:id=>7, :tid1=>3, :tid2=>4), @Tag.load(:id=>8, :tid1=>5, :tid2=>6)]).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN ((3, 4), (5, 6))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id IN (7, 8))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3070
+ end
3071
+
2789
3072
  it "should be able to handle NULL values when filtering many_to_one associations" do
2790
3073
  @Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2791
3074
  end
@@ -2962,6 +3245,38 @@ describe "Filtering by associations" do
2962
3245
  @Album.filter(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL))))'
2963
3246
  end
2964
3247
 
3248
+ it "should be able to filter on many_to_one association datasets with :conditions" do
3249
+ @Album.filter(:a_artist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))))"
3250
+ end
3251
+
3252
+ it "should be able to filter on one_to_many association datasets with :conditions" do
3253
+ @Album.filter(:a_tracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL)))) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))))"
3254
+ end
3255
+
3256
+ it "should be able to filter on one_to_one association datasets with :conditions" do
3257
+ @Album.filter(:a_album_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL)))) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))))"
3258
+ end
3259
+
3260
+ it "should be able to filter on many_to_many association datasets with :conditions" do
3261
+ @Album.filter(:a_tags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
3262
+ end
3263
+
3264
+ it "should be able to filter on many_to_one association datasets with block" do
3265
+ @Album.filter(:b_artist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) AND (albums.artist_id IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))))"
3266
+ end
3267
+
3268
+ it "should be able to filter on one_to_many association datasets with block" do
3269
+ @Album.filter(:b_tracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL)))) AND (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))))"
3270
+ end
3271
+
3272
+ it "should be able to filter on one_to_one association datasets with block" do
3273
+ @Album.filter(:b_album_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL)))) AND (albums.id IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))))"
3274
+ end
3275
+
3276
+ it "should be able to filter on many_to_many association datasets with block" do
3277
+ @Album.filter(:b_tags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) AND (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
3278
+ end
3279
+
2965
3280
  it "should be able to filter on many_to_one association datasets with composite keys" do
2966
3281
  @Album.filter(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL))))'
2967
3282
  end
@@ -2978,6 +3293,38 @@ describe "Filtering by associations" do
2978
3293
  @Album.filter(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
2979
3294
  end
2980
3295
 
3296
+ it "should be able to filter on many_to_one association datasets with :conditions and composite keys" do
3297
+ @Album.filter(:a_cartist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))))"
3298
+ end
3299
+
3300
+ it "should be able to filter on one_to_many association datasets with :conditions and composite keys" do
3301
+ @Album.filter(:a_ctracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))))"
3302
+ end
3303
+
3304
+ it "should be able to filter on one_to_one association datasets with :conditions and composite keys" do
3305
+ @Album.filter(:a_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))))"
3306
+ end
3307
+
3308
+ it "should be able to filter on many_to_many association datasets with :conditions and composite keys" do
3309
+ @Album.filter(:a_ctags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
3310
+ end
3311
+
3312
+ it "should be able to filter on many_to_one association datasets with block and composite keys" do
3313
+ @Album.filter(:b_cartist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) AND ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))))"
3314
+ end
3315
+
3316
+ it "should be able to filter on one_to_many association datasets with block and composite keys" do
3317
+ @Album.filter(:b_ctracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))))"
3318
+ end
3319
+
3320
+ it "should be able to filter on one_to_one association datasets with block and composite keys" do
3321
+ @Album.filter(:b_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))))"
3322
+ end
3323
+
3324
+ it "should be able to filter on many_to_many association datasets with block and composite keys" do
3325
+ @Album.filter(:b_ctags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) AND ((albums.id1, albums.id2) IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))))"
3326
+ end
3327
+
2981
3328
  it "should be able to exclude on many_to_one association datasets" do
2982
3329
  @Album.exclude(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) OR (albums.artist_id IS NULL))'
2983
3330
  end
@@ -2994,6 +3341,38 @@ describe "Filtering by associations" do
2994
3341
  @Album.exclude(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
2995
3342
  end
2996
3343
 
3344
+ it "should be able to exclude on many_to_one association datasets with :conditions" do
3345
+ @Album.exclude(:a_artist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((name = 'A') AND (artists.id IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id IS NULL))"
3346
+ end
3347
+
3348
+ it "should be able to exclude on one_to_many association datasets with :conditions" do
3349
+ @Album.exclude(:a_tracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((name = 'A') AND (tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id IS NULL))"
3350
+ end
3351
+
3352
+ it "should be able to exclude on one_to_one association datasets with :conditions" do
3353
+ @Album.exclude(:a_album_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id IS NULL))"
3354
+ end
3355
+
3356
+ it "should be able to exclude on many_to_many association datasets with :conditions" do
3357
+ @Album.exclude(:a_tags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id IS NULL))"
3358
+ end
3359
+
3360
+ it "should be able to exclude on many_to_one association datasets with block" do
3361
+ @Album.exclude(:b_artist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((x = 1) AND (artists.id IS NOT NULL)))) OR (albums.artist_id NOT IN (SELECT artists.id FROM artists WHERE ((artists.id IS NOT NULL) AND (name = 'B') AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id IS NULL))"
3362
+ end
3363
+
3364
+ it "should be able to exclude on one_to_many association datasets with block" do
3365
+ @Album.exclude(:b_tracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((x = 1) AND (tracks.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (name = 'B') AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id IS NULL))"
3366
+ end
3367
+
3368
+ it "should be able to exclude on one_to_one association datasets with block" do
3369
+ @Album.exclude(:b_album_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((x = 1) AND (album_infos.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT album_infos.album_id FROM album_infos WHERE ((album_infos.album_id IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id IS NULL))"
3370
+ end
3371
+
3372
+ it "should be able to exclude on many_to_many association datasets with block" do
3373
+ @Album.exclude(:b_tags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE ((albums.id NOT IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (SELECT tags.id FROM tags WHERE ((x = 1) AND (tags.id IS NOT NULL)))) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id NOT IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id IS NULL))"
3374
+ end
3375
+
2997
3376
  it "should be able to exclude on many_to_one association datasets with composite keys" do
2998
3377
  @Album.exclude(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
2999
3378
  end
@@ -3010,6 +3389,38 @@ describe "Filtering by associations" do
3010
3389
  @Album.exclude(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
3011
3390
  end
3012
3391
 
3392
+ it "should be able to exclude on many_to_one association datasets with :conditions and composite keys" do
3393
+ @Album.exclude(:a_cartist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((name = 'A') AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
3394
+ end
3395
+
3396
+ it "should be able to exclude on one_to_many association datasets with :conditions and composite keys" do
3397
+ @Album.exclude(:a_ctracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((name = 'A') AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3398
+ end
3399
+
3400
+ it "should be able to exclude on one_to_one association datasets with :conditions and composite keys" do
3401
+ @Album.exclude(:a_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((name = 'A') AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3402
+ end
3403
+
3404
+ it "should be able to exclude on many_to_many association datasets with :conditions and composite keys" do
3405
+ @Album.exclude(:a_ctags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'A') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3406
+ end
3407
+
3408
+ it "should be able to exclude on many_to_one association datasets with block and composite keys" do
3409
+ @Album.exclude(:b_cartist=>@Artist.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((x = 1) AND (artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL)))) OR ((albums.artist_id1, albums.artist_id2) NOT IN (SELECT artists.id1, artists.id2 FROM artists WHERE ((artists.id1 IS NOT NULL) AND (artists.id2 IS NOT NULL) AND (name = 'B') AND (artists.id IN (SELECT artists.id FROM artists WHERE (x = 1)))))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))"
3410
+ end
3411
+
3412
+ it "should be able to exclude on one_to_many association datasets with block and composite keys" do
3413
+ @Album.exclude(:b_ctracks=>@Track.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((x = 1) AND (tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT tracks.album_id1, tracks.album_id2 FROM tracks WHERE ((tracks.album_id1 IS NOT NULL) AND (tracks.album_id2 IS NOT NULL) AND (name = 'B') AND (tracks.id IN (SELECT tracks.id FROM tracks WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3414
+ end
3415
+
3416
+ it "should be able to exclude on one_to_one association datasets with block and composite keys" do
3417
+ @Album.exclude(:b_calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((x = 1) AND (album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT album_infos.album_id1, album_infos.album_id2 FROM album_infos WHERE ((album_infos.album_id1 IS NOT NULL) AND (album_infos.album_id2 IS NOT NULL) AND (name = 'B') AND (album_infos.id IN (SELECT album_infos.id FROM album_infos WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3418
+ end
3419
+
3420
+ it "should be able to exclude on many_to_many association datasets with block and composite keys" do
3421
+ @Album.exclude(:b_ctags=>@Tag.filter(:x=>1)).sql.should == "SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM albums_tags WHERE (((albums_tags.tag_id1, albums_tags.tag_id2) IN (SELECT tags.tid1, tags.tid2 FROM tags WHERE ((x = 1) AND (tags.tid1 IS NOT NULL) AND (tags.tid2 IS NOT NULL)))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL)))) OR ((albums.id1, albums.id2) NOT IN (SELECT albums_tags.album_id1, albums_tags.album_id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id1 = tags.tid1) AND (albums_tags.tag_id2 = tags.tid2)) WHERE ((name = 'B') AND (tags.id IN (SELECT tags.id FROM tags WHERE (x = 1)))))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))"
3422
+ end
3423
+
3013
3424
  it "should do a regular IN query if the dataset for a different model is used" do
3014
3425
  @Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
3015
3426
  end
@@ -3097,6 +3508,35 @@ describe "Sequel::Model Associations with clashing column names" do
3097
3508
  @db.sqls.should == ["SELECT * FROM bars WHERE (bars.object_id IN (SELECT bars_foos.object_id FROM bars_foos WHERE ((bars_foos.foo_id = 2) AND (bars_foos.object_id IS NOT NULL)))) LIMIT 1"]
3098
3509
  end
3099
3510
 
3511
+ it "should have working filter by associations for associations with :conditions with model instances" do
3512
+ @Bar.many_to_one :foo, :clone=>:foo, :conditions=>{:name=>'A'}
3513
+ @Foo.one_to_many :bars, :clone=>:bars, :conditions=>{:name=>'A'}
3514
+ @Foo.one_to_one :bar, :clone=>:bars
3515
+ @Foo.many_to_many :mtmbars, :clone=>:mtmbars, :conditions=>{:name=>'A'}
3516
+ @Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, :conditions=>{:name=>'A'}
3517
+
3518
+ @Bar.where(:foo=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_id = 2) AND (bars.object_id IN (SELECT foos.object_id FROM foos WHERE ((name = 'A') AND (foos.object_id IS NOT NULL) AND (foos.id = 1)))))"
3519
+ @Foo.where(:bars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id = 2) AND (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1)))))"
3520
+ @Foo.where(:bar=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id = 2) AND (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((name = 'A') AND (bars.object_id IS NOT NULL) AND (bars.id = 1)))))"
3521
+ @Foo.where(:mtmbars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id IN (SELECT bars_foos.foo_id FROM bars_foos WHERE ((bars_foos.object_id = 2) AND (bars_foos.foo_id IS NOT NULL)))) AND (foos.object_id IN (SELECT bars_foos.foo_id FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE ((name = 'A') AND (bars.id = 1)))))"
3522
+ @Bar.where(:mtmfoos=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_id IN (SELECT bars_foos.object_id FROM bars_foos WHERE ((bars_foos.foo_id = 2) AND (bars_foos.object_id IS NOT NULL)))) AND (bars.object_id IN (SELECT bars_foos.object_id FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE ((name = 'A') AND (foos.id = 1)))))"
3523
+ end
3524
+
3525
+ it "should have working filter by associations for associations with block with model instances" do
3526
+ b = lambda{|ds| ds.where(:name=>'A')}
3527
+ @Bar.many_to_one :foo, :clone=>:foo, &b
3528
+ @Foo.one_to_many :bars, :clone=>:bars, &b
3529
+ @Foo.one_to_one :bar, :clone=>:bars
3530
+ @Foo.many_to_many :mtmbars, :clone=>:mtmbars, &b
3531
+ @Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, &b
3532
+
3533
+ @Bar.where(:foo=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_id = 2) AND (bars.object_id IN (SELECT foos.object_id FROM foos WHERE ((foos.object_id IS NOT NULL) AND (name = 'A') AND (foos.id = 1)))))"
3534
+ @Foo.where(:bars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id = 2) AND (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((bars.object_id IS NOT NULL) AND (name = 'A') AND (bars.id = 1)))))"
3535
+ @Foo.where(:bar=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id = 2) AND (foos.object_id IN (SELECT bars.object_id FROM bars WHERE ((bars.object_id IS NOT NULL) AND (name = 'A') AND (bars.id = 1)))))"
3536
+ @Foo.where(:mtmbars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_id IN (SELECT bars_foos.foo_id FROM bars_foos WHERE ((bars_foos.object_id = 2) AND (bars_foos.foo_id IS NOT NULL)))) AND (foos.object_id IN (SELECT bars_foos.foo_id FROM bars INNER JOIN bars_foos ON (bars_foos.object_id = bars.object_id) WHERE ((name = 'A') AND (bars.id = 1)))))"
3537
+ @Bar.where(:mtmfoos=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_id IN (SELECT bars_foos.object_id FROM bars_foos WHERE ((bars_foos.foo_id = 2) AND (bars_foos.object_id IS NOT NULL)))) AND (bars.object_id IN (SELECT bars_foos.object_id FROM foos INNER JOIN bars_foos ON (bars_foos.foo_id = foos.object_id) WHERE ((name = 'A') AND (foos.id = 1)))))"
3538
+ end
3539
+
3100
3540
  it "should have working modification methods" do
3101
3541
  b = @Bar.load(:id=>2, :object_id=>3)
3102
3542
  f = @Foo.load(:id=>2, :object_id=>3)
@@ -3217,6 +3657,35 @@ describe "Sequel::Model Associations with non-column expression keys" do
3217
3657
  @db.sqls.should == ["SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM bars_foos WHERE ((bars_foos.foo_ids[0] = 2) AND (bars_foos.bar_ids[0] IS NOT NULL)))) LIMIT 1"]
3218
3658
  end
3219
3659
 
3660
+ it "should have working filter by associations for associations with :conditions with model instances" do
3661
+ @Bar.many_to_one :foo, :clone=>:foo, :conditions=>{:name=>'A'}
3662
+ @Foo.one_to_many :bars, :clone=>:bars, :conditions=>{:name=>'A'}
3663
+ @Foo.one_to_one :bar, :clone=>:bars
3664
+ @Foo.many_to_many :mtmbars, :clone=>:mtmbars, :conditions=>{:name=>'A'}
3665
+ @Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, :conditions=>{:name=>'A'}
3666
+
3667
+ @Bar.where(:foo=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_ids[0] = 2) AND (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((name = 'A') AND (foos.object_ids[0] IS NOT NULL) AND (foos.id = 1)))))"
3668
+ @Foo.where(:bars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] = 2) AND (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1)))))"
3669
+ @Foo.where(:bar=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] = 2) AND (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((name = 'A') AND (bars.object_ids[0] IS NOT NULL) AND (bars.id = 1)))))"
3670
+ @Foo.where(:mtmbars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars_foos WHERE ((bars_foos.bar_ids[0] = 2) AND (bars_foos.foo_ids[0] IS NOT NULL)))) AND (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE ((name = 'A') AND (bars.id = 1)))))"
3671
+ @Bar.where(:mtmfoos=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM bars_foos WHERE ((bars_foos.foo_ids[0] = 2) AND (bars_foos.bar_ids[0] IS NOT NULL)))) AND (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE ((name = 'A') AND (foos.id = 1)))))"
3672
+ end
3673
+
3674
+ it "should have working filter by associations for associations with block with model instances" do
3675
+ b = lambda{|ds| ds.where(:name=>'A')}
3676
+ @Bar.many_to_one :foo, :clone=>:foo, &b
3677
+ @Foo.one_to_many :bars, :clone=>:bars, &b
3678
+ @Foo.one_to_one :bar, :clone=>:bars
3679
+ @Foo.many_to_many :mtmbars, :clone=>:mtmbars, &b
3680
+ @Bar.many_to_many :mtmfoos, :clone=>:mtmfoos, &b
3681
+
3682
+ @Bar.where(:foo=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_ids[0] = 2) AND (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((foos.object_ids[0] IS NOT NULL) AND (name = 'A') AND (foos.id = 1)))))"
3683
+ @Foo.where(:bars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] = 2) AND (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((bars.object_ids[0] IS NOT NULL) AND (name = 'A') AND (bars.id = 1)))))"
3684
+ @Foo.where(:bar=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] = 2) AND (foos.object_ids[0] IN (SELECT bars.object_ids[0] FROM bars WHERE ((bars.object_ids[0] IS NOT NULL) AND (name = 'A') AND (bars.id = 1)))))"
3685
+ @Foo.where(:mtmbars=>@bar).sql.should == "SELECT * FROM foos WHERE ((foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars_foos WHERE ((bars_foos.bar_ids[0] = 2) AND (bars_foos.foo_ids[0] IS NOT NULL)))) AND (foos.object_ids[0] IN (SELECT bars_foos.foo_ids[0] FROM bars INNER JOIN bars_foos ON (bars_foos.bar_ids[0] = bars.object_ids[0]) WHERE ((name = 'A') AND (bars.id = 1)))))"
3686
+ @Bar.where(:mtmfoos=>@foo).sql.should == "SELECT * FROM bars WHERE ((bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM bars_foos WHERE ((bars_foos.foo_ids[0] = 2) AND (bars_foos.bar_ids[0] IS NOT NULL)))) AND (bars.object_ids[0] IN (SELECT bars_foos.bar_ids[0] FROM foos INNER JOIN bars_foos ON (bars_foos.foo_ids[0] = foos.object_ids[0]) WHERE ((name = 'A') AND (foos.id = 1)))))"
3687
+ end
3688
+
3220
3689
  it "should have working filter by associations with model datasets" do
3221
3690
  @Bar.first(:foo=>@Foo.where(:id=>@foo.id)).should == @bar
3222
3691
  @db.sqls.should == ["SELECT * FROM bars WHERE (bars.object_ids[0] IN (SELECT foos.object_ids[0] FROM foos WHERE ((id = 1) AND (foos.object_ids[0] IS NOT NULL)))) LIMIT 1"]