sequel 3.31.0 → 3.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +54 -0
- data/MIT-LICENSE +1 -1
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +74 -30
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +7 -0
- data/lib/sequel/adapters/jdbc/derby.rb +13 -0
- data/lib/sequel/adapters/jdbc/h2.rb +10 -1
- data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +7 -0
- data/lib/sequel/adapters/mock.rb +4 -0
- data/lib/sequel/adapters/mysql.rb +3 -0
- data/lib/sequel/adapters/oracle.rb +7 -3
- data/lib/sequel/adapters/shared/db2.rb +9 -2
- data/lib/sequel/adapters/shared/mssql.rb +48 -2
- data/lib/sequel/adapters/shared/mysql.rb +24 -4
- data/lib/sequel/adapters/shared/oracle.rb +7 -6
- data/lib/sequel/adapters/shared/progress.rb +1 -1
- data/lib/sequel/adapters/shared/sqlite.rb +16 -10
- data/lib/sequel/core.rb +22 -0
- data/lib/sequel/database/query.rb +13 -4
- data/lib/sequel/dataset/actions.rb +20 -11
- data/lib/sequel/dataset/mutation.rb +7 -1
- data/lib/sequel/dataset/prepared_statements.rb +11 -0
- data/lib/sequel/dataset/sql.rb +21 -24
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/model.rb +5 -2
- data/lib/sequel/model/associations.rb +70 -16
- data/lib/sequel/model/base.rb +11 -6
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/composition.rb +43 -10
- data/lib/sequel/plugins/many_through_many.rb +4 -1
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- data/lib/sequel/plugins/serialization.rb +13 -8
- data/lib/sequel/plugins/serialization_modification_detection.rb +22 -10
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +33 -10
- data/spec/adapters/mysql_spec.rb +111 -91
- data/spec/adapters/oracle_spec.rb +18 -0
- data/spec/core/database_spec.rb +1 -0
- data/spec/core/dataset_spec.rb +110 -15
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/many_through_many_spec.rb +14 -14
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -1
- data/spec/extensions/serialization_spec.rb +9 -0
- data/spec/integration/associations_test.rb +278 -154
- data/spec/integration/dataset_test.rb +39 -2
- data/spec/integration/plugin_test.rb +63 -3
- data/spec/integration/prepared_statement_test.rb +10 -3
- data/spec/integration/schema_test.rb +61 -14
- data/spec/integration/transaction_test.rb +10 -0
- data/spec/model/associations_spec.rb +170 -80
- data/spec/model/hooks_spec.rb +40 -0
- 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 == [
|
1187
|
+
@ds.exclude(:a=>[]).all.should == []
|
1182
1188
|
@ds.filter([:a, :b]=>[]).all.should == []
|
1183
|
-
@ds.exclude([:a, :b]=>[]).all.should == [
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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 (
|
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
|
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
|
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
|
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
|
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
|