sequel 3.23.0 → 3.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/CHANGELOG +64 -0
  2. data/doc/association_basics.rdoc +43 -5
  3. data/doc/model_hooks.rdoc +64 -27
  4. data/doc/prepared_statements.rdoc +8 -4
  5. data/doc/reflection.rdoc +8 -2
  6. data/doc/release_notes/3.23.0.txt +1 -1
  7. data/doc/release_notes/3.24.0.txt +420 -0
  8. data/lib/sequel/adapters/db2.rb +8 -1
  9. data/lib/sequel/adapters/firebird.rb +25 -9
  10. data/lib/sequel/adapters/informix.rb +4 -19
  11. data/lib/sequel/adapters/jdbc.rb +34 -17
  12. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  13. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  14. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  15. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  16. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  17. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  18. data/lib/sequel/adapters/postgres.rb +30 -1
  19. data/lib/sequel/adapters/shared/access.rb +10 -0
  20. data/lib/sequel/adapters/shared/informix.rb +45 -0
  21. data/lib/sequel/adapters/shared/mssql.rb +82 -8
  22. data/lib/sequel/adapters/shared/mysql.rb +25 -7
  23. data/lib/sequel/adapters/shared/postgres.rb +39 -6
  24. data/lib/sequel/adapters/shared/sqlite.rb +57 -5
  25. data/lib/sequel/adapters/sqlite.rb +8 -3
  26. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  27. data/lib/sequel/ast_transformer.rb +190 -0
  28. data/lib/sequel/core.rb +1 -1
  29. data/lib/sequel/database/misc.rb +6 -0
  30. data/lib/sequel/database/query.rb +33 -3
  31. data/lib/sequel/database/schema_methods.rb +6 -2
  32. data/lib/sequel/dataset/features.rb +6 -0
  33. data/lib/sequel/dataset/prepared_statements.rb +17 -2
  34. data/lib/sequel/dataset/query.rb +17 -0
  35. data/lib/sequel/dataset/sql.rb +2 -53
  36. data/lib/sequel/exceptions.rb +4 -0
  37. data/lib/sequel/extensions/to_dot.rb +95 -83
  38. data/lib/sequel/model.rb +5 -0
  39. data/lib/sequel/model/associations.rb +80 -14
  40. data/lib/sequel/model/base.rb +182 -55
  41. data/lib/sequel/model/exceptions.rb +3 -1
  42. data/lib/sequel/plugins/association_pks.rb +6 -4
  43. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  44. data/lib/sequel/plugins/many_through_many.rb +8 -3
  45. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  46. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  47. data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
  48. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  49. data/lib/sequel/sql.rb +8 -0
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/postgres_spec.rb +43 -18
  52. data/spec/core/connection_pool_spec.rb +56 -77
  53. data/spec/core/database_spec.rb +25 -0
  54. data/spec/core/dataset_spec.rb +127 -16
  55. data/spec/core/expression_filters_spec.rb +13 -0
  56. data/spec/core/schema_spec.rb +6 -1
  57. data/spec/extensions/association_pks_spec.rb +7 -0
  58. data/spec/extensions/defaults_setter_spec.rb +64 -0
  59. data/spec/extensions/many_through_many_spec.rb +60 -4
  60. data/spec/extensions/nested_attributes_spec.rb +1 -0
  61. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  62. data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
  63. data/spec/extensions/prepared_statements_spec.rb +72 -0
  64. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  65. data/spec/extensions/to_dot_spec.rb +3 -5
  66. data/spec/integration/associations_test.rb +155 -1
  67. data/spec/integration/dataset_test.rb +8 -1
  68. data/spec/integration/plugin_test.rb +119 -0
  69. data/spec/integration/prepared_statement_test.rb +72 -1
  70. data/spec/integration/schema_test.rb +66 -8
  71. data/spec/integration/transaction_test.rb +40 -0
  72. data/spec/model/associations_spec.rb +349 -8
  73. data/spec/model/base_spec.rb +59 -0
  74. data/spec/model/hooks_spec.rb +161 -0
  75. data/spec/model/record_spec.rb +24 -0
  76. metadata +21 -4
@@ -174,6 +174,15 @@ describe "Database schema modifiers" do
174
174
  @db.create_table!(:items, :temp=>true){Integer :number}
175
175
  end
176
176
 
177
+ specify "should have create_table? only create the table if it doesn't already exist" do
178
+ @db.create_table!(:items){String :a}
179
+ @db.create_table?(:items){String :b}
180
+ @db[:items].columns.should == [:a]
181
+ @db.drop_table(:items) rescue nil
182
+ @db.create_table?(:items){String :b}
183
+ @db[:items].columns.should == [:b]
184
+ end
185
+
177
186
  specify "should rename tables correctly" do
178
187
  @db.drop_table(:items) rescue nil
179
188
  @db.create_table!(:items2){Integer :number}
@@ -362,25 +371,74 @@ describe "Database#tables" do
362
371
  "xxxxx#{@@xxxxx += 1}"
363
372
  end
364
373
  end
365
- @iom = INTEGRATION_DB.identifier_output_method
366
- @iim = INTEGRATION_DB.identifier_input_method
374
+ @db = INTEGRATION_DB
375
+ @db.create_table(:sequel_test_table){Integer :a}
376
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
377
+ @iom = @db.identifier_output_method
378
+ @iim = @db.identifier_input_method
367
379
  clear_sqls
368
380
  end
369
381
  after do
370
- INTEGRATION_DB.identifier_output_method = @iom
371
- INTEGRATION_DB.identifier_input_method = @iim
382
+ @db.drop_view :sequel_test_view
383
+ @db.drop_table :sequel_test_table
384
+ @db.identifier_output_method = @iom
385
+ @db.identifier_input_method = @iim
386
+ end
387
+
388
+ specify "should return an array of symbols" do
389
+ ts = @db.tables
390
+ ts.should be_a_kind_of(Array)
391
+ ts.each{|t| t.should be_a_kind_of(Symbol)}
392
+ ts.should include(:sequel_test_table)
393
+ ts.should_not include(:sequel_test_view)
394
+ end
395
+
396
+ specify "should respect the database's identifier_output_method" do
397
+ @db.identifier_output_method = :xxxxx
398
+ @db.identifier_input_method = :xxxxx
399
+ @db.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
400
+ end
401
+ end
402
+ end
403
+
404
+ begin
405
+ INTEGRATION_DB.views
406
+ rescue Sequel::NotImplemented
407
+ rescue
408
+ describe "Database#views" do
409
+ before do
410
+ class ::String
411
+ @@xxxxx = 0
412
+ def xxxxx
413
+ "xxxxx#{@@xxxxx += 1}"
414
+ end
415
+ end
416
+ @db = INTEGRATION_DB
417
+ @db.create_table(:sequel_test_table){Integer :a}
418
+ @db.create_view :sequel_test_view, @db[:sequel_test_table]
419
+ @iom = @db.identifier_output_method
420
+ @iim = @db.identifier_input_method
421
+ clear_sqls
422
+ end
423
+ after do
424
+ @db.drop_view :sequel_test_view
425
+ @db.drop_table :sequel_test_table
426
+ @db.identifier_output_method = @iom
427
+ @db.identifier_input_method = @iim
372
428
  end
373
429
 
374
430
  specify "should return an array of symbols" do
375
- ts = INTEGRATION_DB.tables
431
+ ts = @db.views
376
432
  ts.should be_a_kind_of(Array)
377
433
  ts.each{|t| t.should be_a_kind_of(Symbol)}
434
+ ts.should_not include(:sequel_test_table)
435
+ ts.should include(:sequel_test_view)
378
436
  end
379
437
 
380
438
  specify "should respect the database's identifier_output_method" do
381
- INTEGRATION_DB.identifier_output_method = :xxxxx
382
- INTEGRATION_DB.identifier_input_method = :xxxxx
383
- INTEGRATION_DB.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
439
+ @db.identifier_output_method = :xxxxx
440
+ @db.identifier_input_method = :xxxxx
441
+ @db.views.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
384
442
  end
385
443
  end
386
444
  end
@@ -134,4 +134,44 @@ describe "Database transactions" do
134
134
  @d.count.should == i + 1
135
135
  end
136
136
  end
137
+
138
+ if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && ![[:do, :sqlite], [:tinytds, :mssql]].include?([INTEGRATION_DB.adapter_scheme, INTEGRATION_DB.database_type]))) and RUBY_VERSION < '1.9'
139
+ specify "should handle Thread#kill for transactions inside threads" do
140
+ q = Queue.new
141
+ q1 = Queue.new
142
+ t = Thread.new do
143
+ @db.transaction do
144
+ @d << {:name => 'abc', :value => 1}
145
+ q1.push nil
146
+ q.pop
147
+ @d << {:name => 'def', :value => 2}
148
+ end
149
+ end
150
+ q1.pop
151
+ t.kill
152
+ @d.count.should == 0
153
+ end
154
+
155
+ if INTEGRATION_DB.supports_savepoints?
156
+ specify "should handle Thread#kill for transactions with savepoints inside threads" do
157
+ q = Queue.new
158
+ q1 = Queue.new
159
+ t = Thread.new do
160
+ @db.transaction do
161
+ @d << {:name => 'abc', :value => 1}
162
+ @db.transaction(:savepoint=>true) do
163
+ @d << {:name => 'def', :value => 2}
164
+ q1.push nil
165
+ q.pop
166
+ @d << {:name => 'ghi', :value => 3}
167
+ end
168
+ @d << {:name => 'jkl', :value => 4}
169
+ end
170
+ end
171
+ q1.pop
172
+ t.kill
173
+ @d.count.should == 0
174
+ end
175
+ end
176
+ end
137
177
  end
@@ -1370,7 +1370,7 @@ describe Sequel::Model, "one_to_many" do
1370
1370
  @c2.one_to_many :attributes, :class => @c1
1371
1371
  n = @c2.new(:id => 1234)
1372
1372
  a = @c1.new(:id => 2345)
1373
- def a.valid?(opts); false; end
1373
+ def a.validate() errors.add(:id, 'foo') end
1374
1374
  proc{n.add_attribute(a)}.should raise_error(Sequel::Error)
1375
1375
  proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
1376
1376
  end
@@ -1379,7 +1379,7 @@ describe Sequel::Model, "one_to_many" do
1379
1379
  @c2.one_to_many :attributes, :class => @c1, :validate=>false
1380
1380
  n = @c2.new(:id => 1234)
1381
1381
  a = @c1.new(:id => 2345)
1382
- def a.valid?(opts); false; end
1382
+ def a.validate() errors.add(:id, 'foo') end
1383
1383
  n.add_attribute(a).should == a
1384
1384
  n.remove_attribute(a).should == a
1385
1385
  end
@@ -2282,7 +2282,7 @@ describe Sequel::Model, "many_to_many" do
2282
2282
  @c2.many_to_many :attributes, :class => @c1
2283
2283
  n = @c1.new
2284
2284
  a = @c2.load(:id=>123)
2285
- def n.valid?(opts); false; end
2285
+ def n.validate() errors.add(:id, 'foo') end
2286
2286
  proc{a.add_attribute(n)}.should raise_error(Sequel::ValidationFailed)
2287
2287
  end
2288
2288
 
@@ -2291,7 +2291,7 @@ describe Sequel::Model, "many_to_many" do
2291
2291
  n = @c1.new
2292
2292
  n.raise_on_save_failure = false
2293
2293
  a = @c2.load(:id=>123)
2294
- def n.valid?(opts); false; end
2294
+ def n.validate() errors.add(:id, 'foo') end
2295
2295
  proc{a.add_attribute(n)}.should raise_error(Sequel::Error)
2296
2296
  end
2297
2297
 
@@ -2299,7 +2299,7 @@ describe Sequel::Model, "many_to_many" do
2299
2299
  @c2.many_to_many :attributes, :class => @c1, :validate=>false
2300
2300
  n = @c1.new
2301
2301
  a = @c2.load(:id=>123)
2302
- def n.valid?(opts); false; end
2302
+ def n.validate() errors.add(:id, 'foo') end
2303
2303
  a.add_attribute(n)
2304
2304
  n.new?.should == false
2305
2305
  end
@@ -2795,7 +2795,7 @@ describe "Filtering by associations" do
2795
2795
  end
2796
2796
 
2797
2797
  it "should be able to filter on many_to_many associations" do
2798
- @Album.filter(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE (tag_id = 3)))'
2798
+ @Album.filter(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id = 3) AND (album_id IS NOT NULL))))'
2799
2799
  end
2800
2800
 
2801
2801
  it "should be able to filter on many_to_one associations with composite keys" do
@@ -2811,7 +2811,7 @@ describe "Filtering by associations" do
2811
2811
  end
2812
2812
 
2813
2813
  it "should be able to filter on many_to_many associations with composite keys" do
2814
- @Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE ((tag_id1 = 3) AND (tag_id2 = 4))))'
2814
+ @Album.filter(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE ((tag_id1 = 3) AND (tag_id2 = 4) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
2815
2815
  end
2816
2816
 
2817
2817
  it "should work inside a complex filter" do
@@ -2828,16 +2828,357 @@ describe "Filtering by associations" do
2828
2828
  it "should raise for an invalid association type" do
2829
2829
  @Album.many_to_many :iatags, :clone=>:tags
2830
2830
  @Album.association_reflection(:iatags)[:type] = :foo
2831
- proc{@Album.filter(:mtmtags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
2831
+ proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
2832
2832
  end
2833
2833
 
2834
2834
  it "should raise for an invalid associated object class " do
2835
2835
  proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
2836
2836
  end
2837
2837
 
2838
+ it "should raise for an invalid associated object class when multiple objects are used" do
2839
+ proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
2840
+ end
2841
+
2842
+ it "should correctly handle case when a multiple value association is used" do
2843
+ proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
2844
+ end
2845
+
2846
+ it "should not affect non-association IN/NOT IN filtering with an empty array" do
2847
+ @Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
2848
+ @Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (1 = 1)'
2849
+ end
2850
+
2838
2851
  it "should work correctly in subclasses" do
2839
2852
  c = Class.new(@Album)
2840
2853
  c.many_to_one :sartist, :class=>@Artist
2841
2854
  c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (sartist_id = 3)'
2842
2855
  end
2856
+
2857
+ it "should be able to exclude on many_to_one associations" do
2858
+ @Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((artist_id != 3) OR (artist_id IS NULL))'
2859
+ end
2860
+
2861
+ it "should be able to exclude on one_to_many associations" do
2862
+ @Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
2863
+ end
2864
+
2865
+ it "should be able to exclude on one_to_one associations" do
2866
+ @Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
2867
+ end
2868
+
2869
+ it "should be able to exclude on many_to_many associations" do
2870
+ @Album.exclude(:tags=>@Tag.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id = 3) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
2871
+ end
2872
+
2873
+ it "should be able to exclude on many_to_one associations with composite keys" do
2874
+ @Album.exclude(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1 != 3) OR (artist_id2 != 4) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
2875
+ end
2876
+
2877
+ it "should be able to exclude on one_to_many associations with composite keys" do
2878
+ @Album.exclude(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 != 3) OR (id2 != 4) OR (id1 IS NULL) OR (id2 IS NULL))'
2879
+ end
2880
+
2881
+ it "should be able to exclude on one_to_one associations with composite keys" do
2882
+ @Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 != 3) OR (id2 != 4) OR (id1 IS NULL) OR (id2 IS NULL))'
2883
+ end
2884
+
2885
+ it "should be able to exclude on many_to_many associations with composite keys" do
2886
+ @Album.exclude(:ctags=>@Tag.load(:tid1=>3, :tid2=>4)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE ((tag_id1 = 3) AND (tag_id2 = 4) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
2887
+ end
2888
+
2889
+ it "should be able to filter on multiple many_to_one associations" do
2890
+ @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3, 4))'
2891
+ end
2892
+
2893
+ it "should be able to filter on multiple one_to_many associations" do
2894
+ @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
2895
+ end
2896
+
2897
+ it "should be able to filter on multiple one_to_one associations" do
2898
+ @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
2899
+ end
2900
+
2901
+ it "should be able to filter on multiple many_to_many associations" do
2902
+ @Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3, 4)) AND (album_id IS NOT NULL))))'
2903
+ end
2904
+
2905
+ it "should be able to filter on multiple many_to_one associations with composite keys" do
2906
+ @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4), (5, 6)))'
2907
+ end
2908
+
2909
+ it "should be able to filter on multiple one_to_many associations with composite keys" do
2910
+ @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4), (5, 6)))'
2911
+ end
2912
+
2913
+ it "should be able to filter on multiple one_to_one associations with composite keys" do
2914
+ @Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4), (5, 6)))'
2915
+ end
2916
+
2917
+ it "should be able to filter on multiple many_to_many associations with composite keys" do
2918
+ @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4), (5, 6))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
2919
+ end
2920
+
2921
+ it "should be able to exclude on multiple many_to_one associations" do
2922
+ @Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (3, 4)) OR (artist_id IS NULL))'
2923
+ end
2924
+
2925
+ it "should be able to exclude on multiple one_to_many associations" do
2926
+ @Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3, 4)) OR (id IS NULL))'
2927
+ end
2928
+
2929
+ it "should be able to exclude on multiple one_to_one associations" do
2930
+ @Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3, 4)) OR (id IS NULL))'
2931
+ end
2932
+
2933
+ it "should be able to exclude on multiple many_to_many associations" do
2934
+ @Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3, 4)) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
2935
+ end
2936
+
2937
+ it "should be able to exclude on multiple many_to_one associations with composite keys" do
2938
+ @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>5, :id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4), (5, 6))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
2939
+ end
2940
+
2941
+ it "should be able to exclude on multiple one_to_many associations with composite keys" do
2942
+ @Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4), (5, 6))) OR (id1 IS NULL) OR (id2 IS NULL))'
2943
+ end
2944
+
2945
+ it "should be able to exclude on multiple one_to_one associations with composite keys" do
2946
+ @Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5, :album_id2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4), (5, 6))) OR (id1 IS NULL) OR (id2 IS NULL))'
2947
+ end
2948
+
2949
+ it "should be able to exclude on multiple many_to_many associations with composite keys" do
2950
+ @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5, :tid2=>6)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4), (5, 6))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
2951
+ end
2952
+
2953
+ it "should be able to handle NULL values when filtering many_to_one associations" do
2954
+ @Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2955
+ end
2956
+
2957
+ it "should be able to handle NULL values when filtering one_to_many associations" do
2958
+ @Album.filter(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2959
+ end
2960
+
2961
+ it "should be able to handle NULL values when filtering one_to_one associations" do
2962
+ @Album.filter(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2963
+ end
2964
+
2965
+ it "should be able to handle NULL values when filtering many_to_many associations" do
2966
+ @Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2967
+ end
2968
+
2969
+ it "should be able to handle filteringing with NULL values for many_to_one associations with composite keys" do
2970
+ @Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2971
+ @Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2972
+ @Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2973
+ end
2974
+
2975
+ it "should be able to filtering with NULL values for one_to_many associations with composite keys" do
2976
+ @Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2977
+ @Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2978
+ @Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2979
+ end
2980
+
2981
+ it "should be able to filtering with NULL values for one_to_one associations with composite keys" do
2982
+ @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2983
+ @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2984
+ @Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2985
+ end
2986
+
2987
+ it "should be able to filtering with NULL values for many_to_many associations with composite keys" do
2988
+ @Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2989
+ @Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2990
+ @Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2991
+ end
2992
+
2993
+ it "should be able to handle NULL values when excluding many_to_one associations" do
2994
+ @Album.exclude(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
2995
+ end
2996
+
2997
+ it "should be able to handle NULL values when excluding one_to_many associations" do
2998
+ @Album.exclude(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
2999
+ end
3000
+
3001
+ it "should be able to handle NULL values when excluding one_to_one associations" do
3002
+ @Album.exclude(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3003
+ end
3004
+
3005
+ it "should be able to handle NULL values when excluding many_to_many associations" do
3006
+ @Album.exclude(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3007
+ end
3008
+
3009
+ it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
3010
+ @Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3011
+ @Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3012
+ @Album.exclude(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3013
+ end
3014
+
3015
+ it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
3016
+ @Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3017
+ @Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3018
+ @Album.exclude(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3019
+ end
3020
+
3021
+ it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
3022
+ @Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3023
+ @Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3024
+ @Album.exclude(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3025
+ end
3026
+
3027
+ it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
3028
+ @Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3029
+ @Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
3030
+ @Album.exclude(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
3031
+ end
3032
+
3033
+ it "should be able to handle NULL values when filtering multiple many_to_one associations" do
3034
+ @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3))'
3035
+ @Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
3036
+ end
3037
+
3038
+ it "should be able to handle NULL values when filtering multiple one_to_many associations" do
3039
+ @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
3040
+ @Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
3041
+ end
3042
+
3043
+ it "should be able to handle NULL values when filtering multiple one_to_one associations" do
3044
+ @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
3045
+ @Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
3046
+ end
3047
+
3048
+ it "should be able to handle NULL values when filtering multiple many_to_many associations" do
3049
+ @Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3)) AND (album_id IS NOT NULL))))'
3050
+ @Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
3051
+ end
3052
+
3053
+ it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
3054
+ @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
3055
+ @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
3056
+ end
3057
+
3058
+ it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
3059
+ @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
3060
+ @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
3061
+ end
3062
+
3063
+ it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
3064
+ @Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
3065
+ @Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
3066
+ end
3067
+
3068
+ it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
3069
+ @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
3070
+ @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
3071
+ end
3072
+
3073
+ it "should be able to handle NULL values when excluding multiple many_to_one associations" do
3074
+ @Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (3)) OR (artist_id IS NULL))'
3075
+ @Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
3076
+ end
3077
+
3078
+ it "should be able to handle NULL values when excluding multiple one_to_many associations" do
3079
+ @Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
3080
+ @Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
3081
+ end
3082
+
3083
+ it "should be able to handle NULL values when excluding multiple one_to_one associations" do
3084
+ @Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
3085
+ @Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
3086
+ end
3087
+
3088
+ it "should be able to handle NULL values when excluding multiple many_to_many associations" do
3089
+ @Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (3)) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
3090
+ @Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
3091
+ end
3092
+
3093
+ it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
3094
+ @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
3095
+ @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN ((3, 4))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
3096
+ end
3097
+
3098
+ it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
3099
+ @Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
3100
+ @Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
3101
+ end
3102
+
3103
+ it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
3104
+ @Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
3105
+ @Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN ((3, 4))) OR (id1 IS NULL) OR (id2 IS NULL))'
3106
+ end
3107
+
3108
+ it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
3109
+ @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
3110
+ @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN ((3, 4))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
3111
+ end
3112
+
3113
+ it "should be able to filter on many_to_one association datasets" do
3114
+ @Album.filter(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (SELECT id FROM artists WHERE ((x = 1) AND (id IS NOT NULL))))'
3115
+ end
3116
+
3117
+ it "should be able to filter on one_to_many association datasets" do
3118
+ @Album.filter(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM tracks WHERE ((x = 1) AND (album_id IS NOT NULL))))'
3119
+ end
3120
+
3121
+ it "should be able to filter on one_to_one association datasets" do
3122
+ @Album.filter(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM album_infos WHERE ((x = 1) AND (album_id IS NOT NULL))))'
3123
+ end
3124
+
3125
+ it "should be able to filter on many_to_many association datasets" do
3126
+ @Album.filter(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (id IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (SELECT id FROM tags WHERE ((x = 1) AND (id IS NOT NULL)))) AND (album_id IS NOT NULL))))'
3127
+ end
3128
+
3129
+ it "should be able to filter on many_to_one association datasets with composite keys" do
3130
+ @Album.filter(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN (SELECT id1, id2 FROM artists WHERE ((x = 1) AND (id1 IS NOT NULL) AND (id2 IS NOT NULL))))'
3131
+ end
3132
+
3133
+ it "should be able to filter on one_to_many association datasets with composite keys" do
3134
+ @Album.filter(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM tracks WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
3135
+ end
3136
+
3137
+ it "should be able to filter on one_to_one association datasets with composite keys" do
3138
+ @Album.filter(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM album_infos WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
3139
+ end
3140
+
3141
+ it "should be able to filter on many_to_many association datasets with composite keys" do
3142
+ @Album.filter(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN (SELECT tid1, tid2 FROM tags WHERE ((x = 1) AND (tid1 IS NOT NULL) AND (tid2 IS NOT NULL)))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL))))'
3143
+ end
3144
+
3145
+ it "should be able to exclude on many_to_one association datasets" do
3146
+ @Album.exclude(:artist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((artist_id NOT IN (SELECT id FROM artists WHERE ((x = 1) AND (id IS NOT NULL)))) OR (artist_id IS NULL))'
3147
+ end
3148
+
3149
+ it "should be able to exclude on one_to_many association datasets" do
3150
+ @Album.exclude(:tracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM tracks WHERE ((x = 1) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
3151
+ end
3152
+
3153
+ it "should be able to exclude on one_to_one association datasets" do
3154
+ @Album.exclude(:album_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM album_infos WHERE ((x = 1) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
3155
+ end
3156
+
3157
+ it "should be able to exclude on many_to_many association datasets" do
3158
+ @Album.exclude(:tags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (SELECT album_id FROM albums_tags WHERE ((tag_id IN (SELECT id FROM tags WHERE ((x = 1) AND (id IS NOT NULL)))) AND (album_id IS NOT NULL)))) OR (id IS NULL))'
3159
+ end
3160
+
3161
+ it "should be able to exclude on many_to_one association datasets with composite keys" do
3162
+ @Album.exclude(:cartist=>@Artist.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((artist_id1, artist_id2) NOT IN (SELECT id1, id2 FROM artists WHERE ((x = 1) AND (id1 IS NOT NULL) AND (id2 IS NOT NULL)))) OR (artist_id1 IS NULL) OR (artist_id2 IS NULL))'
3163
+ end
3164
+
3165
+ it "should be able to exclude on one_to_many association datasets with composite keys" do
3166
+ @Album.exclude(:ctracks=>@Track.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM tracks WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
3167
+ end
3168
+
3169
+ it "should be able to exclude on one_to_one association datasets with composite keys" do
3170
+ @Album.exclude(:calbum_info=>@AlbumInfo.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM album_infos WHERE ((x = 1) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
3171
+ end
3172
+
3173
+ it "should be able to exclude on many_to_many association datasets with composite keys" do
3174
+ @Album.exclude(:ctags=>@Tag.filter(:x=>1)).sql.should == 'SELECT * FROM albums WHERE (((id1, id2) NOT IN (SELECT album_id1, album_id2 FROM albums_tags WHERE (((tag_id1, tag_id2) IN (SELECT tid1, tid2 FROM tags WHERE ((x = 1) AND (tid1 IS NOT NULL) AND (tid2 IS NOT NULL)))) AND (album_id1 IS NOT NULL) AND (album_id2 IS NOT NULL)))) OR (id1 IS NULL) OR (id2 IS NULL))'
3175
+ end
3176
+
3177
+ it "should do a regular IN query if the dataset for a different model is used" do
3178
+ @Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
3179
+ end
3180
+
3181
+ it "should do a regular IN query if a non-model dataset is used" do
3182
+ @Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
3183
+ end
2843
3184
  end