sequel 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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"]