sequel 3.31.0 → 3.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG +54 -0
  2. data/MIT-LICENSE +1 -1
  3. data/doc/advanced_associations.rdoc +17 -0
  4. data/doc/association_basics.rdoc +74 -30
  5. data/doc/release_notes/3.32.0.txt +202 -0
  6. data/doc/schema_modification.rdoc +1 -1
  7. data/lib/sequel/adapters/jdbc/db2.rb +7 -0
  8. data/lib/sequel/adapters/jdbc/derby.rb +13 -0
  9. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  10. data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
  11. data/lib/sequel/adapters/jdbc/oracle.rb +7 -0
  12. data/lib/sequel/adapters/mock.rb +4 -0
  13. data/lib/sequel/adapters/mysql.rb +3 -0
  14. data/lib/sequel/adapters/oracle.rb +7 -3
  15. data/lib/sequel/adapters/shared/db2.rb +9 -2
  16. data/lib/sequel/adapters/shared/mssql.rb +48 -2
  17. data/lib/sequel/adapters/shared/mysql.rb +24 -4
  18. data/lib/sequel/adapters/shared/oracle.rb +7 -6
  19. data/lib/sequel/adapters/shared/progress.rb +1 -1
  20. data/lib/sequel/adapters/shared/sqlite.rb +16 -10
  21. data/lib/sequel/core.rb +22 -0
  22. data/lib/sequel/database/query.rb +13 -4
  23. data/lib/sequel/dataset/actions.rb +20 -11
  24. data/lib/sequel/dataset/mutation.rb +7 -1
  25. data/lib/sequel/dataset/prepared_statements.rb +11 -0
  26. data/lib/sequel/dataset/sql.rb +21 -24
  27. data/lib/sequel/extensions/query.rb +1 -1
  28. data/lib/sequel/model.rb +5 -2
  29. data/lib/sequel/model/associations.rb +70 -16
  30. data/lib/sequel/model/base.rb +11 -6
  31. data/lib/sequel/plugins/active_model.rb +13 -1
  32. data/lib/sequel/plugins/composition.rb +43 -10
  33. data/lib/sequel/plugins/many_through_many.rb +4 -1
  34. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  35. data/lib/sequel/plugins/serialization.rb +13 -8
  36. data/lib/sequel/plugins/serialization_modification_detection.rb +22 -10
  37. data/lib/sequel/version.rb +1 -1
  38. data/spec/adapters/mssql_spec.rb +33 -10
  39. data/spec/adapters/mysql_spec.rb +111 -91
  40. data/spec/adapters/oracle_spec.rb +18 -0
  41. data/spec/core/database_spec.rb +1 -0
  42. data/spec/core/dataset_spec.rb +110 -15
  43. data/spec/extensions/active_model_spec.rb +13 -0
  44. data/spec/extensions/many_through_many_spec.rb +14 -14
  45. data/spec/extensions/query_spec.rb +6 -0
  46. data/spec/extensions/serialization_modification_detection_spec.rb +36 -1
  47. data/spec/extensions/serialization_spec.rb +9 -0
  48. data/spec/integration/associations_test.rb +278 -154
  49. data/spec/integration/dataset_test.rb +39 -2
  50. data/spec/integration/plugin_test.rb +63 -3
  51. data/spec/integration/prepared_statement_test.rb +10 -3
  52. data/spec/integration/schema_test.rb +61 -14
  53. data/spec/integration/transaction_test.rb +10 -0
  54. data/spec/model/associations_spec.rb +170 -80
  55. data/spec/model/hooks_spec.rb +40 -0
  56. metadata +4 -2
@@ -674,6 +674,12 @@ describe Sequel::SQL::Constants do
674
674
  @ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
675
675
  (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
676
676
  end
677
+
678
+ cspecify "should have working CURRENT_TIMESTAMP when used as a column default", [:jdbc, :sqlite] do
679
+ @db.create_table!(:constants){DateTime :ts, :default=>Sequel::CURRENT_TIMESTAMP}
680
+ @ds.insert
681
+ (Time.now - @c[@ds.get(:ts)]).should be_within(2).of(0)
682
+ end
677
683
  end
678
684
 
679
685
  describe "Sequel::Dataset#import and #multi_insert" do
@@ -1178,11 +1184,42 @@ describe "Sequel::Dataset DSL support" do
1178
1184
  specify "should work empty arrays with nulls" do
1179
1185
  @ds.insert(nil, nil)
1180
1186
  @ds.filter(:a=>[]).all.should == []
1181
- @ds.exclude(:a=>[]).all.should == [{:a=>nil, :b=>nil}]
1187
+ @ds.exclude(:a=>[]).all.should == []
1182
1188
  @ds.filter([:a, :b]=>[]).all.should == []
1183
- @ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
1189
+ @ds.exclude([:a, :b]=>[]).all.should == []
1190
+
1191
+ unless Sequel.guarded?(:mssql, :oracle, :db2)
1192
+ # MSSQL doesn't like boolean results in the select list
1193
+ pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1194
+ pr[@ds.get({:a=>[]}.sql_expr)].should == nil
1195
+ pr[@ds.get(~({:a=>[]}).sql_expr)].should == nil
1196
+ pr[@ds.get({[:a, :b]=>[]}.sql_expr)].should == nil
1197
+ pr[@ds.get(~({[:a, :b]=>[]}).sql_expr)].should == nil
1198
+ end
1184
1199
  end
1185
1200
 
1201
+ specify "should work empty arrays with nulls and Sequel.empty_array_null_handling = true" do
1202
+ begin
1203
+ Sequel.empty_array_handle_nulls = false
1204
+ @ds.insert(nil, nil)
1205
+ @ds.filter(:a=>[]).all.should == []
1206
+ @ds.exclude(:a=>[]).all.should == [{:a=>nil, :b=>nil}]
1207
+ @ds.filter([:a, :b]=>[]).all.should == []
1208
+ @ds.exclude([:a, :b]=>[]).all.should == [{:a=>nil, :b=>nil}]
1209
+
1210
+ unless Sequel.guarded?(:mssql, :oracle, :db2)
1211
+ # MSSQL doesn't like boolean results in the select list
1212
+ pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
1213
+ pr[@ds.get({:a=>[]}.sql_expr)].should == false
1214
+ pr[@ds.get(~({:a=>[]}).sql_expr)].should == true
1215
+ pr[@ds.get({[:a, :b]=>[]}.sql_expr)].should == false
1216
+ pr[@ds.get(~({[:a, :b]=>[]}).sql_expr)].should == true
1217
+ end
1218
+ ensure
1219
+ Sequel.empty_array_handle_nulls = true
1220
+ end
1221
+ end
1222
+
1186
1223
  it "should work multiple conditions" do
1187
1224
  @ds.insert(20, 10)
1188
1225
  @ds.filter(:a=>20, :b=>10).all.should == [{:a=>20, :b=>10}]
@@ -100,8 +100,7 @@ describe "Class Table Inheritance Plugin" do
100
100
  Employee.filter(:id=>@i2).all.first.manager.id.should == @i4
101
101
  end
102
102
 
103
- # See http://www.sqlite.org/src/tktview/3338b3fa19ac4abee6c475126a2e6d9d61f26ab1
104
- cspecify "should insert rows into all tables", :sqlite do
103
+ cspecify "should insert rows into all tables", [:amalgalite], [:jdbc, :sqlite] do
105
104
  e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
106
105
  i = e.id
107
106
  @db[:employees][:id=>i].should == {:id=>i, :name=>'Ex2', :kind=>'Executive'}
@@ -140,7 +139,7 @@ describe "Class Table Inheritance Plugin" do
140
139
  Executive.limit(1).eager(:staff_members).first.staff_members.should == [Staff[@i2]]
141
140
  end
142
141
 
143
- cspecify "should handle eagerly graphing one_to_many relationships", :sqlite do
142
+ cspecify "should handle eagerly graphing one_to_many relationships", [:amalgalite], [:jdbc, :sqlite] do
144
143
  es = Executive.limit(1).eager_graph(:staff_members).all
145
144
  es.should == [Executive[@i4]]
146
145
  es.map{|x| x.staff_members}.should == [[Staff[@i2]]]
@@ -199,6 +198,10 @@ describe "Many Through Many Plugin" do
199
198
  @db.drop_table :albums_artists, :albums, :artists
200
199
  end
201
200
 
201
+ def self_join(c)
202
+ c.join(c.table_name.as(:b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
203
+ end
204
+
202
205
  specify "should handle super simple case with 1 join table" do
203
206
  Artist.many_through_many :albums, [[:albums_artists, :artist_id, :album_id]]
204
207
  Artist[@artist1.id].albums.map{|x| x.name}.sort.should == %w'A D'
@@ -240,6 +243,26 @@ describe "Many Through Many Plugin" do
240
243
 
241
244
  Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
242
245
  Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
246
+
247
+ c = self_join(Artist)
248
+ c.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
249
+ c.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
250
+ c.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
251
+ c.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
252
+
253
+ c.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
254
+ c.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
255
+ c.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
256
+ c.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
257
+
258
+ c.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
259
+ c.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
260
+
261
+ c.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
262
+ c.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
263
+
264
+ c.filter(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
265
+ c.exclude(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
243
266
  end
244
267
 
245
268
  specify "should handle typical case with 3 join tables" do
@@ -280,6 +303,23 @@ describe "Many Through Many Plugin" do
280
303
 
281
304
  Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
282
305
  Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
306
+
307
+ c = self_join(Artist)
308
+ c.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
309
+ c.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
310
+ c.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
311
+ c.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
312
+
313
+ c.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
314
+ c.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
315
+ c.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
316
+ c.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
317
+
318
+ c.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
319
+ c.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
320
+
321
+ c.filter(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
322
+ c.exclude(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
283
323
  end
284
324
 
285
325
  specify "should handle extreme case with 5 join tables" do
@@ -332,6 +372,26 @@ describe "Many Through Many Plugin" do
332
372
 
333
373
  Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
334
374
  Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
375
+
376
+ c = self_join(Artist)
377
+ c.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
378
+ c.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
379
+ c.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
380
+ c.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
381
+
382
+ c.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
383
+ c.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
384
+ c.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
385
+ c.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
386
+
387
+ c.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
388
+ c.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
389
+
390
+ c.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
391
+ c.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
392
+
393
+ c.filter(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
394
+ c.exclude(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
335
395
  end
336
396
  end
337
397
 
@@ -16,15 +16,18 @@ describe "Prepared Statements and Bound Arguments" do
16
16
  @db.drop_table(:items)
17
17
  end
18
18
 
19
- specify "should support bound variables with select, all, and first" do
19
+ specify "should support bound variables when selecting" do
20
20
  @ds.filter(:numb=>:$n).call(:select, :n=>10).should == [{:id=>1, :numb=>10}]
21
21
  @ds.filter(:numb=>:$n).call(:all, :n=>10).should == [{:id=>1, :numb=>10}]
22
22
  @ds.filter(:numb=>:$n).call(:first, :n=>10).should == {:id=>1, :numb=>10}
23
+ @ds.filter(:numb=>:$n).call([:map, :numb], :n=>10).should == [10]
24
+ @ds.filter(:numb=>:$n).call([:to_hash, :id, :numb], :n=>10).should == {1=>10}
23
25
  end
24
26
 
25
- specify "should support blocks for select and all" do
27
+ specify "should support blocks for select, all, and map " do
26
28
  @ds.filter(:numb=>:$n).call(:select, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
27
29
  @ds.filter(:numb=>:$n).call(:all, :n=>10){|r| r[:numb] *= 2}.should == [{:id=>1, :numb=>20}]
30
+ @ds.filter(:numb=>:$n).call([:map], :n=>10){|r| r[:numb] * 2}.should == [20]
28
31
  end
29
32
 
30
33
  specify "should support binding variables before the call with #bind" do
@@ -120,13 +123,17 @@ describe "Prepared Statements and Bound Arguments" do
120
123
  @ds.all.should == [{:id=>1, :numb=>30}]
121
124
  end
122
125
 
123
- specify "should support prepared statements with select, first, and all" do
126
+ specify "should support prepared statements when selecting" do
124
127
  @ds.filter(:numb=>:$n).prepare(:select, :select_n)
125
128
  @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
126
129
  @ds.filter(:numb=>:$n).prepare(:all, :select_n)
127
130
  @db.call(:select_n, :n=>10).should == [{:id=>1, :numb=>10}]
128
131
  @ds.filter(:numb=>:$n).prepare(:first, :select_n)
129
132
  @db.call(:select_n, :n=>10).should == {:id=>1, :numb=>10}
133
+ @ds.filter(:numb=>:$n).prepare([:map, :numb], :select_n)
134
+ @db.call(:select_n, :n=>10).should == [10]
135
+ @ds.filter(:numb=>:$n).prepare([:to_hash, :id, :numb], :select_n)
136
+ @db.call(:select_n, :n=>10).should == {1=>10}
130
137
  end
131
138
 
132
139
  specify "should support prepared statements being call multiple times with different arguments" do
@@ -1,6 +1,5 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
- if INTEGRATION_DB.respond_to?(:schema_parse_table, true)
4
3
  describe "Database schema parser" do
5
4
  before do
6
5
  @iom = INTEGRATION_DB.identifier_output_method
@@ -137,14 +136,17 @@ describe "Database schema parser" do
137
136
  INTEGRATION_DB.create_table!(:items){FalseClass :number}
138
137
  INTEGRATION_DB.schema(:items).first.last[:type].should == :boolean
139
138
  end
140
- end
141
- end
139
+ end if INTEGRATION_DB.respond_to?(:schema_parse_table, true)
142
140
 
143
- begin
141
+ test_indexes = begin
144
142
  INTEGRATION_DB.drop_table(:blah) rescue nil
145
143
  INTEGRATION_DB.indexes(:blah)
144
+ true
146
145
  rescue Sequel::NotImplemented
146
+ false
147
147
  rescue
148
+ true
149
+ end
148
150
  describe "Database index parsing" do
149
151
  after do
150
152
  INTEGRATION_DB.drop_table(:items)
@@ -173,8 +175,7 @@ describe "Database index parsing" do
173
175
  INTEGRATION_DB.create_table!(:items){Integer :n; Integer :a; primary_key [:n, :a]}
174
176
  INTEGRATION_DB.indexes(:items).should == {}
175
177
  end
176
- end
177
- end
178
+ end if test_indexes
178
179
 
179
180
  describe "Database schema modifiers" do
180
181
  before do
@@ -320,6 +321,21 @@ describe "Database schema modifiers" do
320
321
  proc{@ds.insert(:n=>nil)}.should raise_error(Sequel::DatabaseError)
321
322
  end
322
323
 
324
+ specify "should rename columns when the table is referenced by a foreign key" do
325
+ begin
326
+ @db.create_table!(:itemsfk){primary_key :id; Integer :a}
327
+ @db.create_table!(:items){foreign_key :id, :itemsfk}
328
+ @db[:itemsfk].insert(:a=>10)
329
+ @ds.insert(:id=>1)
330
+ @db.alter_table(:itemsfk){rename_column :a, :b}
331
+ @db[:itemsfk].insert(:b=>20)
332
+ @ds.insert(:id=>2)
333
+ @db[:itemsfk].select_order_map([:id, :b]).should == [[1, 10], [2, 20]]
334
+ ensure
335
+ @db.drop_table(:items, :itemsfk)
336
+ end
337
+ end
338
+
323
339
  cspecify "should set column NULL/NOT NULL correctly", [:jdbc, :db2], [:db2] do
324
340
  @db.create_table!(:items, :engine=>:InnoDB){Integer :id}
325
341
  @ds.insert(:id=>10)
@@ -352,6 +368,35 @@ describe "Database schema modifiers" do
352
368
  @ds.all.should == [{:id=>"10"}, {:id=>"20"}]
353
369
  end
354
370
 
371
+ cspecify "should set column types without modifying NULL/NOT NULL", [:jdbc, :db2], [:db2], :oracle, :derby do
372
+ @db.create_table!(:items){Integer :id, :null=>false, :default=>2}
373
+ proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
374
+ @db.alter_table(:items){set_column_type :id, String}
375
+ proc{@ds.insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
376
+
377
+ @db.create_table!(:items){Integer :id}
378
+ @ds.insert(:id=>nil)
379
+ @db.alter_table(:items){set_column_type :id, String}
380
+ @ds.insert(:id=>nil)
381
+ @ds.map(:id).should == [nil, nil]
382
+ end
383
+
384
+ cspecify "should set column types without modifying defaults", [:jdbc, :db2], [:db2], :oracle, :derby do
385
+ @db.create_table!(:items){Integer :id, :default=>0}
386
+ @ds.insert
387
+ @ds.map(:id).should == [0]
388
+ @db.alter_table(:items){set_column_type :id, String}
389
+ @ds.insert
390
+ @ds.map(:id).should == ['0', '0']
391
+
392
+ @db.create_table!(:items){String :id, :default=>'a'}
393
+ @ds.insert
394
+ @ds.map(:id).should == %w'a'
395
+ @db.alter_table(:items){set_column_type :id, String, :size=>1}
396
+ @ds.insert
397
+ @ds.map(:id).should == %w'a a'
398
+ end
399
+
355
400
  specify "should add unnamed unique constraints and foreign key table constraints correctly" do
356
401
  @db.create_table!(:items, :engine=>:InnoDB){Integer :id; Integer :item_id}
357
402
  @db.alter_table(:items) do
@@ -434,10 +479,12 @@ describe "Database schema modifiers" do
434
479
  end
435
480
  end
436
481
 
437
- begin
482
+ test_tables = begin
438
483
  INTEGRATION_DB.tables
484
+ true
439
485
  rescue Sequel::NotImplemented
440
- rescue
486
+ false
487
+ end
441
488
  describe "Database#tables" do
442
489
  before do
443
490
  class ::String
@@ -472,13 +519,14 @@ describe "Database#tables" do
472
519
  @db.identifier_input_method = :xxxxx
473
520
  @db.tables.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
474
521
  end
475
- end
476
- end
522
+ end if test_tables
477
523
 
478
- begin
524
+ test_views = begin
479
525
  INTEGRATION_DB.views
526
+ true
480
527
  rescue Sequel::NotImplemented
481
- rescue
528
+ false
529
+ end
482
530
  describe "Database#views" do
483
531
  before do
484
532
  class ::String
@@ -513,5 +561,4 @@ describe "Database#views" do
513
561
  @db.identifier_input_method = :xxxxx
514
562
  @db.views.each{|t| t.to_s.should =~ /\Ax{5}\d+\z/}
515
563
  end
516
- end
517
- end
564
+ end if test_views
@@ -134,6 +134,16 @@ describe "Database transactions" do
134
134
  end
135
135
 
136
136
  if INTEGRATION_DB.supports_prepared_transactions?
137
+ specify "should allow saving and destroying of model objects" do
138
+ c = Class.new(Sequel::Model(@d))
139
+ c.set_primary_key :name
140
+ c.unrestrict_primary_key
141
+ c.use_after_commit_rollback = false
142
+ @db.transaction(:prepare=>'XYZ'){c.create(:name => '1'); c.create(:name => '2').destroy}
143
+ @db.commit_prepared_transaction('XYZ')
144
+ @d.select_order_map(:name).should == ['1']
145
+ end
146
+
137
147
  specify "should commit prepared transactions using commit_prepared_transaction" do
138
148
  @db.transaction(:prepare=>'XYZ'){@d << {:name => '1'}}
139
149
  @db.commit_prepared_transaction('XYZ')
@@ -2528,42 +2528,42 @@ describe "Filtering by associations" do
2528
2528
  end
2529
2529
 
2530
2530
  it "should be able to filter on many_to_one associations" do
2531
- @Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (artist_id = 3)'
2531
+ @Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id = 3)'
2532
2532
  end
2533
2533
 
2534
2534
  it "should be able to filter on one_to_many associations" do
2535
- @Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
2535
+ @Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
2536
2536
  end
2537
2537
 
2538
2538
  it "should be able to filter on one_to_one associations" do
2539
- @Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
2539
+ @Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.id = 3)'
2540
2540
  end
2541
2541
 
2542
2542
  it "should be able to filter on many_to_many associations" do
2543
- @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))))'
2543
+ @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))))'
2544
2544
  end
2545
2545
 
2546
2546
  it "should be able to filter on many_to_one associations with composite keys" do
2547
- @Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1 = 3) AND (artist_id2 = 4))'
2547
+ @Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1 = 3) AND (albums.artist_id2 = 4))'
2548
2548
  end
2549
2549
 
2550
2550
  it "should be able to filter on one_to_many associations with composite keys" do
2551
- @Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
2551
+ @Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
2552
2552
  end
2553
2553
 
2554
2554
  it "should be able to filter on one_to_one associations with composite keys" do
2555
- @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
2555
+ @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 = 3) AND (albums.id2 = 4))'
2556
2556
  end
2557
2557
 
2558
2558
  it "should be able to filter on many_to_many associations with composite keys" do
2559
- @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))))'
2559
+ @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))))'
2560
2560
  end
2561
2561
 
2562
2562
  it "should work inside a complex filter" do
2563
2563
  artist = @Artist.load(:id=>3)
2564
- @Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3))'
2564
+ @Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3))'
2565
2565
  track = @Track.load(:album_id=>4)
2566
- @Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3) AND (id = 4))'
2566
+ @Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (albums.artist_id = 3) AND (albums.id = 4))'
2567
2567
  end
2568
2568
 
2569
2569
  it "should raise for an invalid association name" do
@@ -2590,109 +2590,109 @@ describe "Filtering by associations" do
2590
2590
 
2591
2591
  it "should not affect non-association IN/NOT IN filtering with an empty array" do
2592
2592
  @Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
2593
- @Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (1 = 1)'
2593
+ @Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id = tag_id)'
2594
2594
  end
2595
2595
 
2596
2596
  it "should work correctly in subclasses" do
2597
2597
  c = Class.new(@Album)
2598
2598
  c.many_to_one :sartist, :class=>@Artist
2599
- c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (sartist_id = 3)'
2599
+ c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (albums.sartist_id = 3)'
2600
2600
  end
2601
2601
 
2602
2602
  it "should be able to exclude on many_to_one associations" do
2603
- @Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((artist_id != 3) OR (artist_id IS NULL))'
2603
+ @Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id != 3) OR (albums.artist_id IS NULL))'
2604
2604
  end
2605
2605
 
2606
2606
  it "should be able to exclude on one_to_many associations" do
2607
- @Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
2607
+ @Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
2608
2608
  end
2609
2609
 
2610
2610
  it "should be able to exclude on one_to_one associations" do
2611
- @Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
2611
+ @Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((albums.id != 3) OR (albums.id IS NULL))'
2612
2612
  end
2613
2613
 
2614
2614
  it "should be able to exclude on many_to_many associations" do
2615
- @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))'
2615
+ @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))'
2616
2616
  end
2617
2617
 
2618
2618
  it "should be able to exclude on many_to_one associations with composite keys" do
2619
- @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))'
2619
+ @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))'
2620
2620
  end
2621
2621
 
2622
2622
  it "should be able to exclude on one_to_many associations with composite keys" do
2623
- @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))'
2623
+ @Album.exclude(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2624
2624
  end
2625
2625
 
2626
2626
  it "should be able to exclude on one_to_one associations with composite keys" do
2627
- @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))'
2627
+ @Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((albums.id1 != 3) OR (albums.id2 != 4) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2628
2628
  end
2629
2629
 
2630
2630
  it "should be able to exclude on many_to_many associations with composite keys" do
2631
- @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))'
2631
+ @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))'
2632
2632
  end
2633
2633
 
2634
2634
  it "should be able to filter on multiple many_to_one associations" do
2635
- @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3, 4))'
2635
+ @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3, 4))'
2636
2636
  end
2637
2637
 
2638
2638
  it "should be able to filter on multiple one_to_many associations" do
2639
- @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
2639
+ @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
2640
2640
  end
2641
2641
 
2642
2642
  it "should be able to filter on multiple one_to_one associations" do
2643
- @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
2643
+ @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3, 4))'
2644
2644
  end
2645
2645
 
2646
2646
  it "should be able to filter on multiple many_to_many associations" do
2647
- @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))))'
2647
+ @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))))'
2648
2648
  end
2649
2649
 
2650
2650
  it "should be able to filter on multiple many_to_one associations with composite keys" do
2651
- @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)))'
2651
+ @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)))'
2652
2652
  end
2653
2653
 
2654
2654
  it "should be able to filter on multiple one_to_many associations with composite keys" do
2655
- @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)))'
2655
+ @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 ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
2656
2656
  end
2657
2657
 
2658
2658
  it "should be able to filter on multiple one_to_one associations with composite keys" do
2659
- @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)))'
2659
+ @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 ((albums.id1, albums.id2) IN ((3, 4), (5, 6)))'
2660
2660
  end
2661
2661
 
2662
2662
  it "should be able to filter on multiple many_to_many associations with composite keys" do
2663
- @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))))'
2663
+ @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))))'
2664
2664
  end
2665
2665
 
2666
2666
  it "should be able to exclude on multiple many_to_one associations" do
2667
- @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))'
2667
+ @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))'
2668
2668
  end
2669
2669
 
2670
2670
  it "should be able to exclude on multiple one_to_many associations" do
2671
- @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))'
2671
+ @Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
2672
2672
  end
2673
2673
 
2674
2674
  it "should be able to exclude on multiple one_to_one associations" do
2675
- @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))'
2675
+ @Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3, 4)) OR (albums.id IS NULL))'
2676
2676
  end
2677
2677
 
2678
2678
  it "should be able to exclude on multiple many_to_many associations" do
2679
- @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))'
2679
+ @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))'
2680
2680
  end
2681
2681
 
2682
2682
  it "should be able to exclude on multiple many_to_one associations with composite keys" do
2683
- @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))'
2683
+ @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))'
2684
2684
  end
2685
2685
 
2686
2686
  it "should be able to exclude on multiple one_to_many associations with composite keys" do
2687
- @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))'
2687
+ @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 (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2688
2688
  end
2689
2689
 
2690
2690
  it "should be able to exclude on multiple one_to_one associations with composite keys" do
2691
- @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))'
2691
+ @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 (((albums.id1, albums.id2) NOT IN ((3, 4), (5, 6))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2692
2692
  end
2693
2693
 
2694
2694
  it "should be able to exclude on multiple many_to_many associations with composite keys" do
2695
- @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))'
2695
+ @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))'
2696
2696
  end
2697
2697
 
2698
2698
  it "should be able to handle NULL values when filtering many_to_one associations" do
@@ -2711,25 +2711,25 @@ describe "Filtering by associations" do
2711
2711
  @Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2712
2712
  end
2713
2713
 
2714
- it "should be able to handle filteringing with NULL values for many_to_one associations with composite keys" do
2714
+ it "should be able to handle filtering with NULL values for many_to_one associations with composite keys" do
2715
2715
  @Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2716
2716
  @Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2717
2717
  @Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2718
2718
  end
2719
2719
 
2720
- it "should be able to filtering with NULL values for one_to_many associations with composite keys" do
2720
+ it "should be able to filter with NULL values for one_to_many associations with composite keys" do
2721
2721
  @Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2722
2722
  @Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2723
2723
  @Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2724
2724
  end
2725
2725
 
2726
- it "should be able to filtering with NULL values for one_to_one associations with composite keys" do
2726
+ it "should be able to filter with NULL values for one_to_one associations with composite keys" do
2727
2727
  @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2728
2728
  @Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2729
2729
  @Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
2730
2730
  end
2731
2731
 
2732
- it "should be able to filtering with NULL values for many_to_many associations with composite keys" do
2732
+ it "should be able to filter with NULL values for many_to_many associations with composite keys" do
2733
2733
  @Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2734
2734
  @Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
2735
2735
  @Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
@@ -2776,147 +2776,147 @@ describe "Filtering by associations" do
2776
2776
  end
2777
2777
 
2778
2778
  it "should be able to handle NULL values when filtering multiple many_to_one associations" do
2779
- @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3))'
2779
+ @Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (albums.artist_id IN (3))'
2780
2780
  @Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
2781
2781
  end
2782
2782
 
2783
2783
  it "should be able to handle NULL values when filtering multiple one_to_many associations" do
2784
- @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
2784
+ @Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
2785
2785
  @Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
2786
2786
  end
2787
2787
 
2788
2788
  it "should be able to handle NULL values when filtering multiple one_to_one associations" do
2789
- @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
2789
+ @Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (3))'
2790
2790
  @Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
2791
2791
  end
2792
2792
 
2793
2793
  it "should be able to handle NULL values when filtering multiple many_to_many associations" do
2794
- @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))))'
2794
+ @Album.filter(:tags=>[@Tag.load(:id=>3), @Tag.new]).sql.should == 'SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM albums_tags WHERE ((albums_tags.tag_id IN (3)) AND (albums_tags.album_id IS NOT NULL))))'
2795
2795
  @Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
2796
2796
  end
2797
2797
 
2798
2798
  it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
2799
- @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)))'
2800
- @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
2799
+ @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
2800
+ @Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN ((3, 4)))'
2801
2801
  end
2802
2802
 
2803
2803
  it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
2804
- @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)))'
2805
- @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
2804
+ @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
2805
+ @Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
2806
2806
  end
2807
2807
 
2808
2808
  it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
2809
- @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)))'
2810
- @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)))'
2809
+ @Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
2810
+ @Album.filter(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id1, albums.id2) IN ((3, 4)))'
2811
2811
  end
2812
2812
 
2813
2813
  it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
2814
- @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))))'
2815
- @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))))'
2814
+ @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).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))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
2815
+ @Album.filter(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).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))) AND (albums_tags.album_id1 IS NOT NULL) AND (albums_tags.album_id2 IS NOT NULL))))'
2816
2816
  end
2817
2817
 
2818
2818
  it "should be able to handle NULL values when excluding multiple many_to_one associations" do
2819
- @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))'
2819
+ @Album.exclude(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.artist_id NOT IN (3)) OR (albums.artist_id IS NULL))'
2820
2820
  @Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
2821
2821
  end
2822
2822
 
2823
2823
  it "should be able to handle NULL values when excluding multiple one_to_many associations" do
2824
- @Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
2824
+ @Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
2825
2825
  @Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
2826
2826
  end
2827
2827
 
2828
2828
  it "should be able to handle NULL values when excluding multiple one_to_one associations" do
2829
- @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))'
2829
+ @Album.exclude(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE ((albums.id NOT IN (3)) OR (albums.id IS NULL))'
2830
2830
  @Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
2831
2831
  end
2832
2832
 
2833
2833
  it "should be able to handle NULL values when excluding multiple many_to_many associations" do
2834
- @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))'
2834
+ @Album.exclude(:tags=>[@Tag.load(:id=>3), @Tag.new]).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)) AND (albums_tags.album_id IS NOT NULL)))) OR (albums.id IS NULL))'
2835
2835
  @Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
2836
2836
  end
2837
2837
 
2838
2838
  it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
2839
- @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))'
2840
- @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))'
2839
+ @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.load(:id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
2840
+ @Album.exclude(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.artist_id1, albums.artist_id2) NOT IN ((3, 4))) OR (albums.artist_id1 IS NULL) OR (albums.artist_id2 IS NULL))'
2841
2841
  end
2842
2842
 
2843
2843
  it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
2844
- @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))'
2845
- @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))'
2844
+ @Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.load(:album_id1=>3)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2845
+ @Album.exclude(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2846
2846
  end
2847
2847
 
2848
2848
  it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
2849
- @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))'
2850
- @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))'
2849
+ @Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.load(:album_id1=>5)]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2850
+ @Album.exclude(:calbum_info=>[@AlbumInfo.load(:album_id1=>3, :album_id2=>4), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (((albums.id1, albums.id2) NOT IN ((3, 4))) OR (albums.id1 IS NULL) OR (albums.id2 IS NULL))'
2851
2851
  end
2852
2852
 
2853
2853
  it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
2854
- @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))'
2855
- @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))'
2854
+ @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.load(:tid1=>5)]).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))) 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))'
2855
+ @Album.exclude(:ctags=>[@Tag.load(:tid1=>3, :tid2=>4), @Tag.new]).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))) 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))'
2856
2856
  end
2857
2857
 
2858
2858
  it "should be able to filter on many_to_one association datasets" do
2859
- @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))))'
2859
+ @Album.filter(: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))))'
2860
2860
  end
2861
2861
 
2862
2862
  it "should be able to filter on one_to_many association datasets" do
2863
- @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))))'
2863
+ @Album.filter(: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))))'
2864
2864
  end
2865
2865
 
2866
2866
  it "should be able to filter on one_to_one association datasets" do
2867
- @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))))'
2867
+ @Album.filter(: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))))'
2868
2868
  end
2869
2869
 
2870
2870
  it "should be able to filter on many_to_many association datasets" do
2871
- @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))))'
2871
+ @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))))'
2872
2872
  end
2873
2873
 
2874
2874
  it "should be able to filter on many_to_one association datasets with composite keys" do
2875
- @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))))'
2875
+ @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))))'
2876
2876
  end
2877
2877
 
2878
2878
  it "should be able to filter on one_to_many association datasets with composite keys" do
2879
- @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))))'
2879
+ @Album.filter(: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))))'
2880
2880
  end
2881
2881
 
2882
2882
  it "should be able to filter on one_to_one association datasets with composite keys" do
2883
- @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))))'
2883
+ @Album.filter(: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))))'
2884
2884
  end
2885
2885
 
2886
2886
  it "should be able to filter on many_to_many association datasets with composite keys" do
2887
- @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))))'
2887
+ @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))))'
2888
2888
  end
2889
2889
 
2890
2890
  it "should be able to exclude on many_to_one association datasets" do
2891
- @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))'
2891
+ @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))'
2892
2892
  end
2893
2893
 
2894
2894
  it "should be able to exclude on one_to_many association datasets" do
2895
- @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))'
2895
+ @Album.exclude(: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 IS NULL))'
2896
2896
  end
2897
2897
 
2898
2898
  it "should be able to exclude on one_to_one association datasets" do
2899
- @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))'
2899
+ @Album.exclude(: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 IS NULL))'
2900
2900
  end
2901
2901
 
2902
2902
  it "should be able to exclude on many_to_many association datasets" do
2903
- @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))'
2903
+ @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))'
2904
2904
  end
2905
2905
 
2906
2906
  it "should be able to exclude on many_to_one association datasets with composite keys" do
2907
- @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))'
2907
+ @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))'
2908
2908
  end
2909
2909
 
2910
2910
  it "should be able to exclude on one_to_many association datasets with composite keys" do
2911
- @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))'
2911
+ @Album.exclude(: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 IS NULL) OR (albums.id2 IS NULL))'
2912
2912
  end
2913
2913
 
2914
2914
  it "should be able to exclude on one_to_one association datasets with composite keys" do
2915
- @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))'
2915
+ @Album.exclude(: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 IS NULL) OR (albums.id2 IS NULL))'
2916
2916
  end
2917
2917
 
2918
2918
  it "should be able to exclude on many_to_many association datasets with composite keys" do
2919
- @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))'
2919
+ @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))'
2920
2920
  end
2921
2921
 
2922
2922
  it "should do a regular IN query if the dataset for a different model is used" do
@@ -2927,3 +2927,93 @@ describe "Filtering by associations" do
2927
2927
  @Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
2928
2928
  end
2929
2929
  end
2930
+
2931
+ describe "Sequel::Model Associations with clashing column names" do
2932
+ before do
2933
+ @db = Sequel.mock(:fetch=>{:id=>1, :object_id=>2})
2934
+ @Foo = Class.new(Sequel::Model(@db[:foos]))
2935
+ @Bar = Class.new(Sequel::Model(@db[:bars]))
2936
+ @Foo.columns :id, :object_id
2937
+ @Bar.columns :id, :object_id
2938
+ @Foo.def_column_alias(:obj_id, :object_id)
2939
+ @Bar.def_column_alias(:obj_id, :object_id)
2940
+ @Foo.one_to_many :bars, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
2941
+ @Foo.one_to_one :bar, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
2942
+ @Bar.many_to_one :foo, :key=>:obj_id, :key_column=>:object_id, :primary_key=>:object_id, :primary_key_method=>:obj_id, :class=>@Foo
2943
+ @Foo.many_to_many :mtmbars, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:foo_id, :right_key=>:object_id, :eager_loader_key=>:object_id, :class=>@Bar
2944
+ @Bar.many_to_many :mtmfoos, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:object_id, :right_key=>:foo_id, :eager_loader_key=>:object_id, :class=>@Foo
2945
+ @foo = @Foo.load(:id=>1, :object_id=>2)
2946
+ @bar = @Bar.load(:id=>1, :object_id=>2)
2947
+ @db.sqls
2948
+ end
2949
+
2950
+ it "should have working regular association methods" do
2951
+ @Bar.first.foo.should == @foo
2952
+ @Foo.first.bars.should == [@bar]
2953
+ @Foo.first.bar.should == @bar
2954
+ @Foo.first.mtmbars.should == [@bar]
2955
+ @Bar.first.mtmfoos.should == [@foo]
2956
+ end
2957
+
2958
+ it "should have working eager loading methods" do
2959
+ @Bar.eager(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
2960
+ @Foo.eager(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
2961
+ @Foo.eager(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
2962
+ @db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
2963
+ @Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
2964
+ @db.fetch = [[{:id=>1, :object_id=>2}], [{:id=>1, :object_id=>2, :x_foreign_key_x=>2}]]
2965
+ @Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
2966
+ end
2967
+
2968
+ it "should have working eager graphing methods" do
2969
+ @db.fetch = {:id=>1, :object_id=>2, :foo_id=>1, :foo_object_id=>2}
2970
+ @Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
2971
+ @db.fetch = {:id=>1, :object_id=>2, :bars_id=>1, :bars_object_id=>2}
2972
+ @Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
2973
+ @db.fetch = {:id=>1, :object_id=>2, :bar_id=>1, :bar_object_id=>2}
2974
+ @Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
2975
+ @db.fetch = {:id=>1, :object_id=>2, :mtmfoos_id=>1, :mtmfoos_object_id=>2}
2976
+ @Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
2977
+ @db.fetch = {:id=>1, :object_id=>2, :mtmbars_id=>1, :mtmbars_object_id=>2}
2978
+ @Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
2979
+ end
2980
+
2981
+ it "should have working modification methods" do
2982
+ b = @Bar.load(:id=>2, :object_id=>3)
2983
+ f = @Foo.load(:id=>2, :object_id=>3)
2984
+ @db.numrows = 1
2985
+
2986
+ @bar.foo = f
2987
+ @bar.obj_id.should == 3
2988
+ @foo.bar = @bar
2989
+ @bar.obj_id.should == 2
2990
+
2991
+ @foo.add_bar(b)
2992
+ @db.fetch = [[{:id=>1, :object_id=>2}, {:id=>2, :object_id=>2}], [{:id=>1, :object_id=>2}]]
2993
+ @foo.bars.should == [@bar, b]
2994
+ @foo.remove_bar(b)
2995
+ @foo.bars.should == [@bar]
2996
+ @foo.remove_all_bars
2997
+ @foo.bars.should == []
2998
+
2999
+ @db.fetch = [[{:id=>1, :object_id=>2}], [], [{:id=>2, :object_id=>2}]]
3000
+ @bar = @Bar.load(:id=>1, :object_id=>2)
3001
+ @foo.mtmbars.should == [@bar]
3002
+ @foo.remove_all_mtmbars
3003
+ @foo.mtmbars.should == []
3004
+ @foo.add_mtmbar(b)
3005
+ @foo.mtmbars.should == [b]
3006
+ @foo.remove_mtmbar(b)
3007
+ @foo.mtmbars.should == []
3008
+
3009
+ @db.fetch = [[{:id=>2, :object_id=>3}], [], [{:id=>2, :object_id=>3}]]
3010
+ @bar.add_mtmfoo(f)
3011
+ @bar.mtmfoos.should == [f]
3012
+ @bar.remove_all_mtmfoos
3013
+ @bar.mtmfoos.should == []
3014
+ @bar.add_mtmfoo(f)
3015
+ @bar.mtmfoos.should == [f]
3016
+ @bar.remove_mtmfoo(f)
3017
+ @bar.mtmfoos.should == []
3018
+ end
3019
+ end