sequel 3.21.0 → 3.28.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 +294 -0
- data/README.rdoc +20 -6
- data/Rakefile +20 -15
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +64 -27
- data/doc/opening_databases.rdoc +37 -10
- data/doc/prepared_statements.rdoc +16 -10
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/testing.rdoc +106 -0
- data/doc/transactions.rdoc +97 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +12 -1
- data/lib/sequel/adapters/amalgalite.rb +4 -0
- data/lib/sequel/adapters/db2.rb +95 -58
- data/lib/sequel/adapters/do.rb +12 -0
- data/lib/sequel/adapters/firebird.rb +25 -203
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/h2.rb +16 -5
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/jdbc.rb +62 -29
- data/lib/sequel/adapters/mysql.rb +22 -139
- data/lib/sequel/adapters/mysql2.rb +9 -14
- data/lib/sequel/adapters/odbc/db2.rb +21 -0
- data/lib/sequel/adapters/odbc.rb +15 -3
- data/lib/sequel/adapters/oracle.rb +17 -1
- data/lib/sequel/adapters/postgres.rb +111 -16
- data/lib/sequel/adapters/shared/access.rb +21 -0
- data/lib/sequel/adapters/shared/db2.rb +290 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +85 -47
- data/lib/sequel/adapters/shared/mysql.rb +50 -7
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
- data/lib/sequel/adapters/shared/oracle.rb +0 -4
- data/lib/sequel/adapters/shared/postgres.rb +75 -43
- data/lib/sequel/adapters/shared/sqlite.rb +56 -8
- data/lib/sequel/adapters/sqlite.rb +12 -11
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/adapters/tinytds.rb +139 -7
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +6 -5
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +1 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +38 -17
- data/lib/sequel/database/query.rb +50 -19
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +52 -27
- data/lib/sequel/dataset/actions.rb +167 -48
- data/lib/sequel/dataset/features.rb +57 -8
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +39 -20
- data/lib/sequel/dataset/mutation.rb +3 -3
- data/lib/sequel/dataset/prepared_statements.rb +29 -14
- data/lib/sequel/dataset/query.rb +182 -32
- data/lib/sequel/dataset/sql.rb +31 -58
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +893 -309
- data/lib/sequel/model/base.rb +302 -105
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +13 -7
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/identity_map.rb +113 -6
- data/lib/sequel/plugins/many_through_many.rb +67 -5
- data/lib/sequel/plugins/prepared_statements.rb +140 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -20
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +12 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +36 -0
- data/spec/adapters/mysql_spec.rb +36 -19
- data/spec/adapters/postgres_spec.rb +115 -28
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/connection_pool_spec.rb +62 -77
- data/spec/core/database_spec.rb +244 -287
- data/spec/core/dataset_spec.rb +383 -34
- data/spec/core/expression_filters_spec.rb +159 -41
- data/spec/core/schema_spec.rb +326 -3
- data/spec/core/spec_helper.rb +45 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/nested_attributes_spec.rb +1 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +12 -20
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +405 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +240 -20
- data/spec/integration/plugin_test.rb +142 -5
- data/spec/integration/prepared_statement_test.rb +174 -95
- data/spec/integration/schema_test.rb +128 -16
- data/spec/integration/spec_helper.rb +15 -0
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/integration/type_test.rb +16 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +476 -5
- data/spec/model/base_spec.rb +91 -1
- data/spec/model/eager_loading_spec.rb +519 -31
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/model_spec.rb +89 -2
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/record_spec.rb +184 -12
- data/spec/model/spec_helper.rb +5 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +85 -34
|
@@ -357,6 +357,28 @@ describe Sequel::Model, "many_to_one" do
|
|
|
357
357
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
|
358
358
|
end
|
|
359
359
|
|
|
360
|
+
it "should use a callback if given one as the argument" do
|
|
361
|
+
@c2.many_to_one :parent, :class => @c2
|
|
362
|
+
|
|
363
|
+
d = @c2.create(:id => 1)
|
|
364
|
+
MODEL_DB.reset
|
|
365
|
+
d.parent_id = 234
|
|
366
|
+
d.associations[:parent] = 42
|
|
367
|
+
d.parent(proc{|ds| ds.filter{name > 'M'}}).should_not == 42
|
|
368
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it "should use a block given to the association method as a callback on ruby 1.8.7+" do
|
|
372
|
+
@c2.many_to_one :parent, :class => @c2
|
|
373
|
+
|
|
374
|
+
d = @c2.create(:id => 1)
|
|
375
|
+
MODEL_DB.reset
|
|
376
|
+
d.parent_id = 234
|
|
377
|
+
d.associations[:parent] = 42
|
|
378
|
+
d.parent{|ds| ds.filter{name > 'M'}}.should_not == 42
|
|
379
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE ((nodes.id = 234) AND (name > 'M')) LIMIT 1"]
|
|
380
|
+
end if RUBY_VERSION >= '1.8.7'
|
|
381
|
+
|
|
360
382
|
it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
|
|
361
383
|
@c2.many_to_one :parent, :class => @c2
|
|
362
384
|
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
|
@@ -538,6 +560,19 @@ describe Sequel::Model, "many_to_one" do
|
|
|
538
560
|
parent.pk.should == 20
|
|
539
561
|
end
|
|
540
562
|
|
|
563
|
+
it "should support after_load association callback that changes the cached object" do
|
|
564
|
+
h = []
|
|
565
|
+
@c2.many_to_one :parent, :class => @c2, :after_load=>:al
|
|
566
|
+
@c2.class_eval do
|
|
567
|
+
def al(v)
|
|
568
|
+
associations[:parent] = :foo
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
p = @c2.load(:id=>10, :parent_id=>20)
|
|
572
|
+
p.parent.should == :foo
|
|
573
|
+
p.associations[:parent].should == :foo
|
|
574
|
+
end
|
|
575
|
+
|
|
541
576
|
it "should raise error and not call internal add or remove method if before callback returns false, even if raise_on_save_failure is false" do
|
|
542
577
|
# The reason for this is that assignment in ruby always returns the argument instead of the result
|
|
543
578
|
# of the method, so we can't return nil to signal that the association callback prevented the modification
|
|
@@ -1149,6 +1184,16 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1149
1184
|
v.model.should == Historical::Value
|
|
1150
1185
|
end
|
|
1151
1186
|
|
|
1187
|
+
it "should use a callback if given one as the argument" do
|
|
1188
|
+
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1189
|
+
|
|
1190
|
+
d = @c2.create(:id => 1234)
|
|
1191
|
+
MODEL_DB.reset
|
|
1192
|
+
d.associations[:attributes] = []
|
|
1193
|
+
d.attributes(proc{|ds| ds.filter{name > 'M'}}).should_not == []
|
|
1194
|
+
MODEL_DB.sqls.should == ["SELECT * FROM attributes WHERE ((attributes.nodeid = 1234) AND (name > 'M'))"]
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1152
1197
|
it "should use explicit key if given" do
|
|
1153
1198
|
@c2.one_to_many :attributes, :class => @c1, :key => :nodeid
|
|
1154
1199
|
|
|
@@ -1338,7 +1383,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1338
1383
|
@c2.one_to_many :attributes, :class => @c1
|
|
1339
1384
|
n = @c2.new(:id => 1234)
|
|
1340
1385
|
a = @c1.new(:id => 2345)
|
|
1341
|
-
def a.
|
|
1386
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1342
1387
|
proc{n.add_attribute(a)}.should raise_error(Sequel::Error)
|
|
1343
1388
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
|
1344
1389
|
end
|
|
@@ -1347,7 +1392,7 @@ describe Sequel::Model, "one_to_many" do
|
|
|
1347
1392
|
@c2.one_to_many :attributes, :class => @c1, :validate=>false
|
|
1348
1393
|
n = @c2.new(:id => 1234)
|
|
1349
1394
|
a = @c1.new(:id => 2345)
|
|
1350
|
-
def a.
|
|
1395
|
+
def a.validate() errors.add(:id, 'foo') end
|
|
1351
1396
|
n.add_attribute(a).should == a
|
|
1352
1397
|
n.remove_attribute(a).should == a
|
|
1353
1398
|
end
|
|
@@ -2250,7 +2295,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2250
2295
|
@c2.many_to_many :attributes, :class => @c1
|
|
2251
2296
|
n = @c1.new
|
|
2252
2297
|
a = @c2.load(:id=>123)
|
|
2253
|
-
def n.
|
|
2298
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2254
2299
|
proc{a.add_attribute(n)}.should raise_error(Sequel::ValidationFailed)
|
|
2255
2300
|
end
|
|
2256
2301
|
|
|
@@ -2259,7 +2304,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2259
2304
|
n = @c1.new
|
|
2260
2305
|
n.raise_on_save_failure = false
|
|
2261
2306
|
a = @c2.load(:id=>123)
|
|
2262
|
-
def n.
|
|
2307
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2263
2308
|
proc{a.add_attribute(n)}.should raise_error(Sequel::Error)
|
|
2264
2309
|
end
|
|
2265
2310
|
|
|
@@ -2267,7 +2312,7 @@ describe Sequel::Model, "many_to_many" do
|
|
|
2267
2312
|
@c2.many_to_many :attributes, :class => @c1, :validate=>false
|
|
2268
2313
|
n = @c1.new
|
|
2269
2314
|
a = @c2.load(:id=>123)
|
|
2270
|
-
def n.
|
|
2315
|
+
def n.validate() errors.add(:id, 'foo') end
|
|
2271
2316
|
a.add_attribute(n)
|
|
2272
2317
|
n.new?.should == false
|
|
2273
2318
|
end
|
|
@@ -2724,3 +2769,429 @@ describe Sequel::Model, " association reflection methods" do
|
|
|
2724
2769
|
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
|
2725
2770
|
end
|
|
2726
2771
|
end
|
|
2772
|
+
|
|
2773
|
+
describe "Filtering by associations" do
|
|
2774
|
+
before do
|
|
2775
|
+
@Album = Class.new(Sequel::Model(:albums))
|
|
2776
|
+
artist = @Artist = Class.new(Sequel::Model(:artists))
|
|
2777
|
+
tag = @Tag = Class.new(Sequel::Model(:tags))
|
|
2778
|
+
track = @Track = Class.new(Sequel::Model(:tracks))
|
|
2779
|
+
album_info = @AlbumInfo = Class.new(Sequel::Model(:album_infos))
|
|
2780
|
+
@Artist.columns :id, :id1, :id2
|
|
2781
|
+
@Tag.columns :id, :tid1, :tid2
|
|
2782
|
+
@Track.columns :id, :album_id, :album_id1, :album_id2
|
|
2783
|
+
@AlbumInfo.columns :id, :album_id, :album_id1, :album_id2
|
|
2784
|
+
@Album.class_eval do
|
|
2785
|
+
columns :id, :id1, :id2, :artist_id, :artist_id1, :artist_id2
|
|
2786
|
+
many_to_one :artist, :class=>artist
|
|
2787
|
+
one_to_many :tracks, :class=>track, :key=>:album_id
|
|
2788
|
+
one_to_one :album_info, :class=>album_info, :key=>:album_id
|
|
2789
|
+
many_to_many :tags, :class=>tag, :left_key=>:album_id, :join_table=>:albums_tags
|
|
2790
|
+
|
|
2791
|
+
many_to_one :cartist, :class=>artist, :key=>[:artist_id1, :artist_id2], :primary_key=>[:id1, :id2]
|
|
2792
|
+
one_to_many :ctracks, :class=>track, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2793
|
+
one_to_one :calbum_info, :class=>album_info, :key=>[:album_id1, :album_id2], :primary_key=>[:id1, :id2]
|
|
2794
|
+
many_to_many :ctags, :class=>tag, :left_key=>[:album_id1, :album_id2], :left_primary_key=>[:id1, :id2], :right_key=>[:tag_id1, :tag_id2], :right_primary_key=>[:tid1, :tid2], :join_table=>:albums_tags
|
|
2795
|
+
end
|
|
2796
|
+
end
|
|
2797
|
+
|
|
2798
|
+
it "should be able to filter on many_to_one associations" do
|
|
2799
|
+
@Album.filter(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (artist_id = 3)'
|
|
2800
|
+
end
|
|
2801
|
+
|
|
2802
|
+
it "should be able to filter on one_to_many associations" do
|
|
2803
|
+
@Album.filter(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
|
|
2804
|
+
end
|
|
2805
|
+
|
|
2806
|
+
it "should be able to filter on one_to_one associations" do
|
|
2807
|
+
@Album.filter(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE (id = 3)'
|
|
2808
|
+
end
|
|
2809
|
+
|
|
2810
|
+
it "should be able to filter on many_to_many associations" do
|
|
2811
|
+
@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))))'
|
|
2812
|
+
end
|
|
2813
|
+
|
|
2814
|
+
it "should be able to filter on many_to_one associations with composite keys" do
|
|
2815
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3, :id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((artist_id1 = 3) AND (artist_id2 = 4))'
|
|
2816
|
+
end
|
|
2817
|
+
|
|
2818
|
+
it "should be able to filter on one_to_many associations with composite keys" do
|
|
2819
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
|
|
2820
|
+
end
|
|
2821
|
+
|
|
2822
|
+
it "should be able to filter on one_to_one associations with composite keys" do
|
|
2823
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3, :album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE ((id1 = 3) AND (id2 = 4))'
|
|
2824
|
+
end
|
|
2825
|
+
|
|
2826
|
+
it "should be able to filter on many_to_many associations with composite keys" do
|
|
2827
|
+
@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))))'
|
|
2828
|
+
end
|
|
2829
|
+
|
|
2830
|
+
it "should work inside a complex filter" do
|
|
2831
|
+
artist = @Artist.load(:id=>3)
|
|
2832
|
+
@Album.filter{foo & {:artist=>artist}}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3))'
|
|
2833
|
+
track = @Track.load(:album_id=>4)
|
|
2834
|
+
@Album.filter{foo & [[:artist, artist], [:tracks, track]]}.sql.should == 'SELECT * FROM albums WHERE (foo AND (artist_id = 3) AND (id = 4))'
|
|
2835
|
+
end
|
|
2836
|
+
|
|
2837
|
+
it "should raise for an invalid association name" do
|
|
2838
|
+
proc{@Album.filter(:foo=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2839
|
+
end
|
|
2840
|
+
|
|
2841
|
+
it "should raise for an invalid association type" do
|
|
2842
|
+
@Album.many_to_many :iatags, :clone=>:tags
|
|
2843
|
+
@Album.association_reflection(:iatags)[:type] = :foo
|
|
2844
|
+
proc{@Album.filter(:iatags=>@Tag.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2845
|
+
end
|
|
2846
|
+
|
|
2847
|
+
it "should raise for an invalid associated object class " do
|
|
2848
|
+
proc{@Album.filter(:tags=>@Artist.load(:id=>3)).sql}.should raise_error(Sequel::Error)
|
|
2849
|
+
end
|
|
2850
|
+
|
|
2851
|
+
it "should raise for an invalid associated object class when multiple objects are used" do
|
|
2852
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2853
|
+
end
|
|
2854
|
+
|
|
2855
|
+
it "should correctly handle case when a multiple value association is used" do
|
|
2856
|
+
proc{@Album.filter(:tags=>[@Tag.load(:id=>3), @Artist.load(:id=>3)]).sql}.should raise_error(Sequel::Error)
|
|
2857
|
+
end
|
|
2858
|
+
|
|
2859
|
+
it "should not affect non-association IN/NOT IN filtering with an empty array" do
|
|
2860
|
+
@Album.filter(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (tag_id != tag_id)'
|
|
2861
|
+
@Album.exclude(:tag_id=>[]).sql.should == 'SELECT * FROM albums WHERE (1 = 1)'
|
|
2862
|
+
end
|
|
2863
|
+
|
|
2864
|
+
it "should work correctly in subclasses" do
|
|
2865
|
+
c = Class.new(@Album)
|
|
2866
|
+
c.many_to_one :sartist, :class=>@Artist
|
|
2867
|
+
c.filter(:sartist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE (sartist_id = 3)'
|
|
2868
|
+
end
|
|
2869
|
+
|
|
2870
|
+
it "should be able to exclude on many_to_one associations" do
|
|
2871
|
+
@Album.exclude(:artist=>@Artist.load(:id=>3)).sql.should == 'SELECT * FROM albums WHERE ((artist_id != 3) OR (artist_id IS NULL))'
|
|
2872
|
+
end
|
|
2873
|
+
|
|
2874
|
+
it "should be able to exclude on one_to_many associations" do
|
|
2875
|
+
@Album.exclude(:tracks=>@Track.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
|
|
2876
|
+
end
|
|
2877
|
+
|
|
2878
|
+
it "should be able to exclude on one_to_one associations" do
|
|
2879
|
+
@Album.exclude(:album_info=>@AlbumInfo.load(:album_id=>3)).sql.should == 'SELECT * FROM albums WHERE ((id != 3) OR (id IS NULL))'
|
|
2880
|
+
end
|
|
2881
|
+
|
|
2882
|
+
it "should be able to exclude on many_to_many associations" do
|
|
2883
|
+
@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))'
|
|
2884
|
+
end
|
|
2885
|
+
|
|
2886
|
+
it "should be able to exclude on many_to_one associations with composite keys" do
|
|
2887
|
+
@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))'
|
|
2888
|
+
end
|
|
2889
|
+
|
|
2890
|
+
it "should be able to exclude on one_to_many associations with composite keys" do
|
|
2891
|
+
@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))'
|
|
2892
|
+
end
|
|
2893
|
+
|
|
2894
|
+
it "should be able to exclude on one_to_one associations with composite keys" do
|
|
2895
|
+
@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))'
|
|
2896
|
+
end
|
|
2897
|
+
|
|
2898
|
+
it "should be able to exclude on many_to_many associations with composite keys" do
|
|
2899
|
+
@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))'
|
|
2900
|
+
end
|
|
2901
|
+
|
|
2902
|
+
it "should be able to filter on multiple many_to_one associations" do
|
|
2903
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.load(:id=>4)]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3, 4))'
|
|
2904
|
+
end
|
|
2905
|
+
|
|
2906
|
+
it "should be able to filter on multiple one_to_many associations" do
|
|
2907
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
|
|
2908
|
+
end
|
|
2909
|
+
|
|
2910
|
+
it "should be able to filter on multiple one_to_one associations" do
|
|
2911
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.load(:album_id=>4)]).sql.should == 'SELECT * FROM albums WHERE (id IN (3, 4))'
|
|
2912
|
+
end
|
|
2913
|
+
|
|
2914
|
+
it "should be able to filter on multiple many_to_many associations" do
|
|
2915
|
+
@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))))'
|
|
2916
|
+
end
|
|
2917
|
+
|
|
2918
|
+
it "should be able to filter on multiple many_to_one associations with composite keys" do
|
|
2919
|
+
@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)))'
|
|
2920
|
+
end
|
|
2921
|
+
|
|
2922
|
+
it "should be able to filter on multiple one_to_many associations with composite keys" do
|
|
2923
|
+
@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)))'
|
|
2924
|
+
end
|
|
2925
|
+
|
|
2926
|
+
it "should be able to filter on multiple one_to_one associations with composite keys" do
|
|
2927
|
+
@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)))'
|
|
2928
|
+
end
|
|
2929
|
+
|
|
2930
|
+
it "should be able to filter on multiple many_to_many associations with composite keys" do
|
|
2931
|
+
@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))))'
|
|
2932
|
+
end
|
|
2933
|
+
|
|
2934
|
+
it "should be able to exclude on multiple many_to_one associations" do
|
|
2935
|
+
@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))'
|
|
2936
|
+
end
|
|
2937
|
+
|
|
2938
|
+
it "should be able to exclude on multiple one_to_many associations" do
|
|
2939
|
+
@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))'
|
|
2940
|
+
end
|
|
2941
|
+
|
|
2942
|
+
it "should be able to exclude on multiple one_to_one associations" do
|
|
2943
|
+
@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))'
|
|
2944
|
+
end
|
|
2945
|
+
|
|
2946
|
+
it "should be able to exclude on multiple many_to_many associations" do
|
|
2947
|
+
@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))'
|
|
2948
|
+
end
|
|
2949
|
+
|
|
2950
|
+
it "should be able to exclude on multiple many_to_one associations with composite keys" do
|
|
2951
|
+
@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))'
|
|
2952
|
+
end
|
|
2953
|
+
|
|
2954
|
+
it "should be able to exclude on multiple one_to_many associations with composite keys" do
|
|
2955
|
+
@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))'
|
|
2956
|
+
end
|
|
2957
|
+
|
|
2958
|
+
it "should be able to exclude on multiple one_to_one associations with composite keys" do
|
|
2959
|
+
@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))'
|
|
2960
|
+
end
|
|
2961
|
+
|
|
2962
|
+
it "should be able to exclude on multiple many_to_many associations with composite keys" do
|
|
2963
|
+
@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))'
|
|
2964
|
+
end
|
|
2965
|
+
|
|
2966
|
+
it "should be able to handle NULL values when filtering many_to_one associations" do
|
|
2967
|
+
@Album.filter(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2968
|
+
end
|
|
2969
|
+
|
|
2970
|
+
it "should be able to handle NULL values when filtering one_to_many associations" do
|
|
2971
|
+
@Album.filter(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2972
|
+
end
|
|
2973
|
+
|
|
2974
|
+
it "should be able to handle NULL values when filtering one_to_one associations" do
|
|
2975
|
+
@Album.filter(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2976
|
+
end
|
|
2977
|
+
|
|
2978
|
+
it "should be able to handle NULL values when filtering many_to_many associations" do
|
|
2979
|
+
@Album.filter(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2980
|
+
end
|
|
2981
|
+
|
|
2982
|
+
it "should be able to handle filteringing with NULL values for many_to_one associations with composite keys" do
|
|
2983
|
+
@Album.filter(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2984
|
+
@Album.filter(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2985
|
+
@Album.filter(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2986
|
+
end
|
|
2987
|
+
|
|
2988
|
+
it "should be able to filtering with NULL values for one_to_many associations with composite keys" do
|
|
2989
|
+
@Album.filter(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2990
|
+
@Album.filter(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2991
|
+
@Album.filter(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2992
|
+
end
|
|
2993
|
+
|
|
2994
|
+
it "should be able to filtering with NULL values for one_to_one associations with composite keys" do
|
|
2995
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2996
|
+
@Album.filter(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2997
|
+
@Album.filter(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
2998
|
+
end
|
|
2999
|
+
|
|
3000
|
+
it "should be able to filtering with NULL values for many_to_many associations with composite keys" do
|
|
3001
|
+
@Album.filter(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3002
|
+
@Album.filter(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3003
|
+
@Album.filter(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3004
|
+
end
|
|
3005
|
+
|
|
3006
|
+
it "should be able to handle NULL values when excluding many_to_one associations" do
|
|
3007
|
+
@Album.exclude(:artist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3008
|
+
end
|
|
3009
|
+
|
|
3010
|
+
it "should be able to handle NULL values when excluding one_to_many associations" do
|
|
3011
|
+
@Album.exclude(:tracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3012
|
+
end
|
|
3013
|
+
|
|
3014
|
+
it "should be able to handle NULL values when excluding one_to_one associations" do
|
|
3015
|
+
@Album.exclude(:album_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3016
|
+
end
|
|
3017
|
+
|
|
3018
|
+
it "should be able to handle NULL values when excluding many_to_many associations" do
|
|
3019
|
+
@Album.exclude(:tags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3020
|
+
end
|
|
3021
|
+
|
|
3022
|
+
it "should be able to handle excluding with NULL values for many_to_one associations with composite keys" do
|
|
3023
|
+
@Album.exclude(:cartist=>@Artist.load(:id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3024
|
+
@Album.exclude(:cartist=>@Artist.load(:id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3025
|
+
@Album.exclude(:cartist=>@Artist.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3026
|
+
end
|
|
3027
|
+
|
|
3028
|
+
it "should be able to excluding with NULL values for one_to_many associations with composite keys" do
|
|
3029
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3030
|
+
@Album.exclude(:ctracks=>@Track.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3031
|
+
@Album.exclude(:ctracks=>@Track.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3032
|
+
end
|
|
3033
|
+
|
|
3034
|
+
it "should be able to excluding with NULL values for one_to_one associations with composite keys" do
|
|
3035
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3036
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.load(:album_id1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3037
|
+
@Album.exclude(:calbum_info=>@AlbumInfo.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3038
|
+
end
|
|
3039
|
+
|
|
3040
|
+
it "should be able to excluding with NULL values for many_to_many associations with composite keys" do
|
|
3041
|
+
@Album.exclude(:ctags=>@Tag.load(:tid1=>3)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3042
|
+
@Album.exclude(:ctags=>@Tag.load(:tid2=>4)).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3043
|
+
@Album.exclude(:ctags=>@Tag.new).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3044
|
+
end
|
|
3045
|
+
|
|
3046
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations" do
|
|
3047
|
+
@Album.filter(:artist=>[@Artist.load(:id=>3), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE (artist_id IN (3))'
|
|
3048
|
+
@Album.filter(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3049
|
+
end
|
|
3050
|
+
|
|
3051
|
+
it "should be able to handle NULL values when filtering multiple one_to_many associations" do
|
|
3052
|
+
@Album.filter(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
|
|
3053
|
+
@Album.filter(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3054
|
+
end
|
|
3055
|
+
|
|
3056
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations" do
|
|
3057
|
+
@Album.filter(:album_info=>[@AlbumInfo.load(:album_id=>3), @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE (id IN (3))'
|
|
3058
|
+
@Album.filter(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3059
|
+
end
|
|
3060
|
+
|
|
3061
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations" do
|
|
3062
|
+
@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))))'
|
|
3063
|
+
@Album.filter(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'f\''
|
|
3064
|
+
end
|
|
3065
|
+
|
|
3066
|
+
it "should be able to handle NULL values when filtering multiple many_to_one associations with composite keys" do
|
|
3067
|
+
@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)))'
|
|
3068
|
+
@Album.filter(:cartist=>[@Artist.load(:id1=>3, :id2=>4), @Artist.new]).sql.should == 'SELECT * FROM albums WHERE ((artist_id1, artist_id2) IN ((3, 4)))'
|
|
3069
|
+
end
|
|
3070
|
+
|
|
3071
|
+
it "should be able handle NULL values when filtering multiple one_to_many associations with composite keys" do
|
|
3072
|
+
@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)))'
|
|
3073
|
+
@Album.filter(:ctracks=>[@Track.load(:album_id1=>3, :album_id2=>4), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id1, id2) IN ((3, 4)))'
|
|
3074
|
+
end
|
|
3075
|
+
|
|
3076
|
+
it "should be able to handle NULL values when filtering multiple one_to_one associations with composite keys" do
|
|
3077
|
+
@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)))'
|
|
3078
|
+
@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)))'
|
|
3079
|
+
end
|
|
3080
|
+
|
|
3081
|
+
it "should be able to handle NULL values when filtering multiple many_to_many associations with composite keys" do
|
|
3082
|
+
@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))))'
|
|
3083
|
+
@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))))'
|
|
3084
|
+
end
|
|
3085
|
+
|
|
3086
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations" do
|
|
3087
|
+
@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))'
|
|
3088
|
+
@Album.exclude(:artist=>[@Artist.new, @Artist.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3089
|
+
end
|
|
3090
|
+
|
|
3091
|
+
it "should be able to handle NULL values when excluding multiple one_to_many associations" do
|
|
3092
|
+
@Album.exclude(:tracks=>[@Track.load(:album_id=>3), @Track.new]).sql.should == 'SELECT * FROM albums WHERE ((id NOT IN (3)) OR (id IS NULL))'
|
|
3093
|
+
@Album.exclude(:tracks=>[@Track.new, @Track.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3094
|
+
end
|
|
3095
|
+
|
|
3096
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations" do
|
|
3097
|
+
@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))'
|
|
3098
|
+
@Album.exclude(:album_info=>[@AlbumInfo.new, @AlbumInfo.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3099
|
+
end
|
|
3100
|
+
|
|
3101
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations" do
|
|
3102
|
+
@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))'
|
|
3103
|
+
@Album.exclude(:tags=>[@Tag.new, @Tag.new]).sql.should == 'SELECT * FROM albums WHERE \'t\''
|
|
3104
|
+
end
|
|
3105
|
+
|
|
3106
|
+
it "should be able to handle NULL values when excluding multiple many_to_one associations with composite keys" do
|
|
3107
|
+
@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))'
|
|
3108
|
+
@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))'
|
|
3109
|
+
end
|
|
3110
|
+
|
|
3111
|
+
it "should be able handle NULL values when excluding multiple one_to_many associations with composite keys" do
|
|
3112
|
+
@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))'
|
|
3113
|
+
@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))'
|
|
3114
|
+
end
|
|
3115
|
+
|
|
3116
|
+
it "should be able to handle NULL values when excluding multiple one_to_one associations with composite keys" do
|
|
3117
|
+
@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))'
|
|
3118
|
+
@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))'
|
|
3119
|
+
end
|
|
3120
|
+
|
|
3121
|
+
it "should be able to handle NULL values when excluding multiple many_to_many associations with composite keys" do
|
|
3122
|
+
@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))'
|
|
3123
|
+
@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))'
|
|
3124
|
+
end
|
|
3125
|
+
|
|
3126
|
+
it "should be able to filter on many_to_one association datasets" do
|
|
3127
|
+
@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))))'
|
|
3128
|
+
end
|
|
3129
|
+
|
|
3130
|
+
it "should be able to filter on one_to_many association datasets" do
|
|
3131
|
+
@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))))'
|
|
3132
|
+
end
|
|
3133
|
+
|
|
3134
|
+
it "should be able to filter on one_to_one association datasets" do
|
|
3135
|
+
@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))))'
|
|
3136
|
+
end
|
|
3137
|
+
|
|
3138
|
+
it "should be able to filter on many_to_many association datasets" do
|
|
3139
|
+
@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))))'
|
|
3140
|
+
end
|
|
3141
|
+
|
|
3142
|
+
it "should be able to filter on many_to_one association datasets with composite keys" do
|
|
3143
|
+
@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))))'
|
|
3144
|
+
end
|
|
3145
|
+
|
|
3146
|
+
it "should be able to filter on one_to_many association datasets with composite keys" do
|
|
3147
|
+
@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))))'
|
|
3148
|
+
end
|
|
3149
|
+
|
|
3150
|
+
it "should be able to filter on one_to_one association datasets with composite keys" do
|
|
3151
|
+
@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))))'
|
|
3152
|
+
end
|
|
3153
|
+
|
|
3154
|
+
it "should be able to filter on many_to_many association datasets with composite keys" do
|
|
3155
|
+
@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))))'
|
|
3156
|
+
end
|
|
3157
|
+
|
|
3158
|
+
it "should be able to exclude on many_to_one association datasets" do
|
|
3159
|
+
@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))'
|
|
3160
|
+
end
|
|
3161
|
+
|
|
3162
|
+
it "should be able to exclude on one_to_many association datasets" do
|
|
3163
|
+
@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))'
|
|
3164
|
+
end
|
|
3165
|
+
|
|
3166
|
+
it "should be able to exclude on one_to_one association datasets" do
|
|
3167
|
+
@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))'
|
|
3168
|
+
end
|
|
3169
|
+
|
|
3170
|
+
it "should be able to exclude on many_to_many association datasets" do
|
|
3171
|
+
@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))'
|
|
3172
|
+
end
|
|
3173
|
+
|
|
3174
|
+
it "should be able to exclude on many_to_one association datasets with composite keys" do
|
|
3175
|
+
@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))'
|
|
3176
|
+
end
|
|
3177
|
+
|
|
3178
|
+
it "should be able to exclude on one_to_many association datasets with composite keys" do
|
|
3179
|
+
@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))'
|
|
3180
|
+
end
|
|
3181
|
+
|
|
3182
|
+
it "should be able to exclude on one_to_one association datasets with composite keys" do
|
|
3183
|
+
@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))'
|
|
3184
|
+
end
|
|
3185
|
+
|
|
3186
|
+
it "should be able to exclude on many_to_many association datasets with composite keys" do
|
|
3187
|
+
@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))'
|
|
3188
|
+
end
|
|
3189
|
+
|
|
3190
|
+
it "should do a regular IN query if the dataset for a different model is used" do
|
|
3191
|
+
@Album.filter(:artist=>@Album.select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
3192
|
+
end
|
|
3193
|
+
|
|
3194
|
+
it "should do a regular IN query if a non-model dataset is used" do
|
|
3195
|
+
@Album.filter(:artist=>@Album.db.from(:albums).select(:x)).sql.should == 'SELECT * FROM albums WHERE (artist IN (SELECT x FROM albums))'
|
|
3196
|
+
end
|
|
3197
|
+
end
|
data/spec/model/base_spec.rb
CHANGED
|
@@ -131,6 +131,50 @@ describe Sequel::Model, ".def_dataset_method" do
|
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
+
describe Sequel::Model, ".dataset_module" do
|
|
135
|
+
before do
|
|
136
|
+
@c = Class.new(Sequel::Model(:items))
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should extend the dataset with the module if the model has a dataset" do
|
|
140
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
141
|
+
@c.dataset.return_3.should == 3
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "should add methods defined in the module to the class" do
|
|
145
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
146
|
+
@c.return_3.should == 3
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should cache calls and readd methods if set_dataset is used" do
|
|
150
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
151
|
+
@c.set_dataset :items
|
|
152
|
+
@c.return_3.should == 3
|
|
153
|
+
@c.dataset.return_3.should == 3
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "should readd methods to subclasses, if set_dataset is used in a subclass" do
|
|
157
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
158
|
+
c = Class.new(@c)
|
|
159
|
+
c.set_dataset :items
|
|
160
|
+
c.return_3.should == 3
|
|
161
|
+
c.dataset.return_3.should == 3
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "should only have a single dataset_module per class" do
|
|
165
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
166
|
+
@c.instance_eval{dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}}
|
|
167
|
+
@c.return_3.should == 4
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should not have subclasses share the dataset_module" do
|
|
171
|
+
@c.instance_eval{dataset_module{def return_3() 3 end}}
|
|
172
|
+
c = Class.new(@c)
|
|
173
|
+
c.instance_eval{dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}}
|
|
174
|
+
c.return_3.should == 6
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
134
178
|
describe "A model class with implicit table name" do
|
|
135
179
|
before do
|
|
136
180
|
class Donkey < Sequel::Model
|
|
@@ -258,7 +302,7 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
|
|
|
258
302
|
before do
|
|
259
303
|
@c = Class.new(Sequel::Model(:blahblah)) do
|
|
260
304
|
columns :x, :y, :z
|
|
261
|
-
def
|
|
305
|
+
def _save_refresh
|
|
262
306
|
self
|
|
263
307
|
end
|
|
264
308
|
end
|
|
@@ -485,3 +529,49 @@ describe Sequel::Model, ".[] optimization" do
|
|
|
485
529
|
@c[1]
|
|
486
530
|
end
|
|
487
531
|
end
|
|
532
|
+
|
|
533
|
+
describe "Model datasets #with_pk" do
|
|
534
|
+
before do
|
|
535
|
+
@c = Class.new(Sequel::Model(:a))
|
|
536
|
+
@ds = @c.dataset
|
|
537
|
+
def @ds.fetch_rows(sql)
|
|
538
|
+
db << sql
|
|
539
|
+
yield(:id=>1)
|
|
540
|
+
end
|
|
541
|
+
@sqls = MODEL_DB.sqls
|
|
542
|
+
@sqls.clear
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
it "should return the first record where the primary key matches" do
|
|
546
|
+
@ds.with_pk(1).should == @c.load(:id=>1)
|
|
547
|
+
@sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
it "should handle existing filters" do
|
|
551
|
+
@ds.filter(:a=>2).with_pk(1)
|
|
552
|
+
@sqls.should == ["SELECT * FROM a WHERE ((a = 2) AND (a.id = 1)) LIMIT 1"]
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "should work with string values" do
|
|
556
|
+
@ds.with_pk("foo")
|
|
557
|
+
@sqls.should == ["SELECT * FROM a WHERE (a.id = 'foo') LIMIT 1"]
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
it "should handle an array for composite primary keys" do
|
|
561
|
+
@c.set_primary_key :id1, :id2
|
|
562
|
+
@ds.with_pk([1, 2])
|
|
563
|
+
["SELECT * FROM a WHERE ((a.id1 = 1) AND (a.id2 = 2)) LIMIT 1",
|
|
564
|
+
"SELECT * FROM a WHERE ((a.id2 = 2) AND (a.id1 = 1)) LIMIT 1"].should include(@sqls.first)
|
|
565
|
+
@sqls.length.should == 1
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "should have #[] consider an integer as a primary key lookup" do
|
|
569
|
+
@ds[1].should == @c.load(:id=>1)
|
|
570
|
+
@sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
it "should not have #[] consider a string as a primary key lookup" do
|
|
574
|
+
@ds['foo'].should == @c.load(:id=>1)
|
|
575
|
+
@sqls.should == ["SELECT * FROM a WHERE (foo) LIMIT 1"]
|
|
576
|
+
end
|
|
577
|
+
end
|