sequel 3.5.0 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +108 -0
- data/README.rdoc +25 -14
- data/Rakefile +20 -1
- data/doc/advanced_associations.rdoc +61 -64
- data/doc/cheat_sheet.rdoc +16 -7
- data/doc/opening_databases.rdoc +3 -3
- data/doc/prepared_statements.rdoc +1 -1
- data/doc/reflection.rdoc +2 -1
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/schema.rdoc +19 -14
- data/lib/sequel/adapters/amalgalite.rb +5 -27
- data/lib/sequel/adapters/jdbc.rb +13 -3
- data/lib/sequel/adapters/jdbc/h2.rb +17 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +20 -7
- data/lib/sequel/adapters/mysql.rb +4 -3
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +87 -28
- data/lib/sequel/adapters/shared/mssql.rb +47 -6
- data/lib/sequel/adapters/shared/mysql.rb +12 -31
- data/lib/sequel/adapters/shared/postgres.rb +15 -12
- data/lib/sequel/adapters/shared/sqlite.rb +18 -0
- data/lib/sequel/adapters/sqlite.rb +1 -16
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +2 -0
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +5 -179
- data/lib/sequel/dataset/actions.rb +123 -0
- data/lib/sequel/dataset/convenience.rb +18 -10
- data/lib/sequel/dataset/features.rb +65 -0
- data/lib/sequel/dataset/prepared_statements.rb +29 -23
- data/lib/sequel/dataset/query.rb +429 -0
- data/lib/sequel/dataset/sql.rb +67 -435
- data/lib/sequel/model/associations.rb +77 -13
- data/lib/sequel/model/base.rb +30 -8
- data/lib/sequel/model/errors.rb +4 -4
- data/lib/sequel/plugins/caching.rb +38 -15
- data/lib/sequel/plugins/force_encoding.rb +18 -7
- data/lib/sequel/plugins/hook_class_methods.rb +4 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +40 -11
- data/lib/sequel/plugins/serialization.rb +17 -3
- data/lib/sequel/plugins/validation_helpers.rb +65 -18
- data/lib/sequel/sql.rb +23 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +96 -10
- data/spec/adapters/mysql_spec.rb +19 -0
- data/spec/adapters/postgres_spec.rb +65 -2
- data/spec/adapters/sqlite_spec.rb +10 -0
- data/spec/core/core_sql_spec.rb +9 -0
- data/spec/core/database_spec.rb +8 -4
- data/spec/core/dataset_spec.rb +122 -29
- data/spec/core/expression_filters_spec.rb +17 -0
- data/spec/extensions/caching_spec.rb +43 -3
- data/spec/extensions/force_encoding_spec.rb +43 -1
- data/spec/extensions/nested_attributes_spec.rb +55 -2
- data/spec/extensions/validation_helpers_spec.rb +71 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/dataset_test.rb +383 -9
- data/spec/integration/eager_loader_test.rb +0 -65
- data/spec/integration/model_test.rb +110 -0
- data/spec/integration/plugin_test.rb +306 -0
- data/spec/integration/prepared_statement_test.rb +32 -0
- data/spec/integration/schema_test.rb +8 -3
- data/spec/integration/spec_helper.rb +1 -25
- data/spec/model/association_reflection_spec.rb +38 -0
- data/spec/model/associations_spec.rb +184 -8
- data/spec/model/eager_loading_spec.rb +23 -0
- data/spec/model/model_spec.rb +8 -0
- data/spec/model/record_spec.rb +84 -1
- metadata +9 -2
@@ -25,37 +25,31 @@ describe "Simple Dataset operations" do
|
|
25
25
|
|
26
26
|
cspecify "should insert with a primary key specified", :mssql do
|
27
27
|
@ds.insert(:id=>100, :number=>20)
|
28
|
-
sqls_should_be(/INSERT INTO items \((number, id|id, number)\) VALUES \((100, 20|20, 100)\)/)
|
29
28
|
@ds.count.should == 2
|
30
29
|
@ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
|
31
30
|
end
|
32
31
|
|
33
32
|
specify "should have insert return primary key value" do
|
34
33
|
@ds.insert(:number=>20).should == 2
|
35
|
-
sqls_should_be('INSERT INTO items (number) VALUES (20)')
|
36
34
|
@ds.filter(:id=>2).first[:number].should == 20
|
37
35
|
end
|
38
36
|
|
39
37
|
specify "should delete correctly" do
|
40
38
|
@ds.filter(1=>1).delete.should == 1
|
41
|
-
sqls_should_be('DELETE FROM items WHERE (1 = 1)')
|
42
39
|
@ds.count.should == 0
|
43
40
|
end
|
44
41
|
|
45
42
|
specify "should update correctly" do
|
46
43
|
@ds.update(:number=>:number+1).should == 1
|
47
|
-
sqls_should_be('UPDATE items SET number = (number + 1)')
|
48
44
|
@ds.all.should == [{:id=>1, :number=>11}]
|
49
45
|
end
|
50
46
|
|
51
47
|
specify "should fetch all results correctly" do
|
52
48
|
@ds.all.should == [{:id=>1, :number=>10}]
|
53
|
-
sqls_should_be('SELECT * FROM items')
|
54
49
|
end
|
55
50
|
|
56
51
|
specify "should fetch a single row correctly" do
|
57
52
|
@ds.first.should == {:id=>1, :number=>10}
|
58
|
-
sqls_should_be('SELECT * FROM items LIMIT 1')
|
59
53
|
end
|
60
54
|
|
61
55
|
specify "should fetch correctly with a limit" do
|
@@ -80,7 +74,6 @@ describe "Simple Dataset operations" do
|
|
80
74
|
|
81
75
|
specify "should alias columns correctly" do
|
82
76
|
@ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
|
83
|
-
sqls_should_be("SELECT id AS 'x', number AS 'n' FROM items LIMIT 1")
|
84
77
|
end
|
85
78
|
end
|
86
79
|
|
@@ -105,6 +98,20 @@ describe Sequel::Dataset do
|
|
105
98
|
@d.count.should == 3
|
106
99
|
end
|
107
100
|
|
101
|
+
specify "should handle aggregate methods on limited datasets correctly" do
|
102
|
+
@d << {:name => 'abc', :value => 6}
|
103
|
+
@d << {:name => 'bcd', :value => 12}
|
104
|
+
@d << {:name => 'def', :value => 18}
|
105
|
+
@d = @d.order(:name).limit(2)
|
106
|
+
@d.count.should == 2
|
107
|
+
@d.avg(:value).to_i.should == 9
|
108
|
+
@d.min(:value).to_i.should == 6
|
109
|
+
@d.reverse.min(:value).to_i.should == 12
|
110
|
+
@d.max(:value).to_i.should == 12
|
111
|
+
@d.sum(:value).to_i.should == 18
|
112
|
+
@d.interval(:value).to_i.should == 6
|
113
|
+
end
|
114
|
+
|
108
115
|
specify "should return the correct records" do
|
109
116
|
@d.to_a.should == []
|
110
117
|
@d << {:name => 'abc', :value => 123}
|
@@ -247,7 +254,6 @@ describe "Simple Dataset operations in transactions" do
|
|
247
254
|
cspecify "should insert correctly with a primary key specified inside a transaction", :mssql do
|
248
255
|
INTEGRATION_DB.transaction do
|
249
256
|
@ds.insert(:id=>100, :number=>20)
|
250
|
-
sqls_should_be('BEGIN', /INSERT INTO items_insert_in_transaction \((number, id|id, number)\) VALUES \((100, 20|20, 100)\)/)
|
251
257
|
@ds.count.should == 1
|
252
258
|
@ds.order(:id).all.should == [{:id=>100, :number=>20}]
|
253
259
|
end
|
@@ -256,7 +262,6 @@ describe "Simple Dataset operations in transactions" do
|
|
256
262
|
specify "should have insert return primary key value inside a transaction" do
|
257
263
|
INTEGRATION_DB.transaction do
|
258
264
|
@ds.insert(:number=>20).should == 1
|
259
|
-
sqls_should_be('BEGIN', /INSERT INTO items_insert_in_transaction \(number\) VALUES \(20\)/)
|
260
265
|
@ds.count.should == 1
|
261
266
|
@ds.order(:id).all.should == [{:id=>1, :number=>20}]
|
262
267
|
end
|
@@ -495,4 +500,373 @@ describe "Sequel::Dataset#import and #multi_insert" do
|
|
495
500
|
@ids.import([:i], @eds)
|
496
501
|
@ids.all.should == [{:i=>10}, {:i=>20}]
|
497
502
|
end
|
503
|
+
|
504
|
+
it "should have import work with the :slice_size option" do
|
505
|
+
@ids.import([:i], [[10], [20], [30]], :slice_size=>1)
|
506
|
+
@ids.all.should == [{:i=>10}, {:i=>20}, {:i=>30}]
|
507
|
+
@ids.delete
|
508
|
+
@ids.import([:i], [[10], [20], [30]], :slice_size=>2)
|
509
|
+
@ids.all.should == [{:i=>10}, {:i=>20}, {:i=>30}]
|
510
|
+
@ids.delete
|
511
|
+
@ids.import([:i], [[10], [20], [30]], :slice_size=>3)
|
512
|
+
@ids.all.should == [{:i=>10}, {:i=>20}, {:i=>30}]
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
describe "Sequel::Dataset convenience methods" do
|
517
|
+
before do
|
518
|
+
@db = INTEGRATION_DB
|
519
|
+
@db.create_table!(:a){Integer :a; Integer :b}
|
520
|
+
@ds = @db[:a].order(:a)
|
521
|
+
end
|
522
|
+
after do
|
523
|
+
@db.drop_table(:a)
|
524
|
+
end
|
525
|
+
|
526
|
+
it "#[]= should update matching rows" do
|
527
|
+
@ds.insert(20, 10)
|
528
|
+
@ds[:a=>20] = {:b=>30}
|
529
|
+
@ds.all.should == [{:a=>20, :b=>30}]
|
530
|
+
end
|
531
|
+
|
532
|
+
it "#empty? should return whether the dataset returns no rows" do
|
533
|
+
@ds.empty?.should == true
|
534
|
+
@ds.insert(20, 10)
|
535
|
+
@ds.empty?.should == false
|
536
|
+
end
|
537
|
+
|
538
|
+
it "#group_and_count should return a grouping by count" do
|
539
|
+
@ds.group_and_count(:a).all.should == []
|
540
|
+
@ds.insert(20, 10)
|
541
|
+
@ds.group_and_count(:a).all.each{|h| h[:count] = h[:count].to_i}.should == [{:a=>20, :count=>1}]
|
542
|
+
@ds.insert(20, 30)
|
543
|
+
@ds.group_and_count(:a).all.each{|h| h[:count] = h[:count].to_i}.should == [{:a=>20, :count=>2}]
|
544
|
+
@ds.insert(30, 30)
|
545
|
+
@ds.group_and_count(:a).all.each{|h| h[:count] = h[:count].to_i}.should == [{:a=>30, :count=>1}, {:a=>20, :count=>2}]
|
546
|
+
end
|
547
|
+
|
548
|
+
it "#group_and_count should support column aliases" do
|
549
|
+
@ds.group_and_count(:a___c).all.should == []
|
550
|
+
@ds.insert(20, 10)
|
551
|
+
@ds.group_and_count(:a___c).all.each{|h| h[:count] = h[:count].to_i}.should == [{:c=>20, :count=>1}]
|
552
|
+
@ds.insert(20, 30)
|
553
|
+
@ds.group_and_count(:a___c).all.each{|h| h[:count] = h[:count].to_i}.should == [{:c=>20, :count=>2}]
|
554
|
+
@ds.insert(30, 30)
|
555
|
+
@ds.group_and_count(:a___c).all.each{|h| h[:count] = h[:count].to_i}.should == [{:c=>30, :count=>1}, {:c=>20, :count=>2}]
|
556
|
+
end
|
557
|
+
|
558
|
+
cspecify "#range should return the range between the maximum and minimum values", :sqlite do
|
559
|
+
@ds = @ds.unordered
|
560
|
+
@ds.insert(20, 10)
|
561
|
+
@ds.insert(30, 10)
|
562
|
+
@ds.range(:a).should == (20..30)
|
563
|
+
@ds.range(:b).should == (10..10)
|
564
|
+
end
|
565
|
+
|
566
|
+
it "#interval should return the different between the maximum and minimum values" do
|
567
|
+
@ds = @ds.unordered
|
568
|
+
@ds.insert(20, 10)
|
569
|
+
@ds.insert(30, 10)
|
570
|
+
@ds.interval(:a).to_i.should == 10
|
571
|
+
@ds.interval(:b).to_i.should == 0
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
describe "Sequel::Dataset main SQL methods" do
|
576
|
+
before do
|
577
|
+
@db = INTEGRATION_DB
|
578
|
+
@db.create_table!(:a){Integer :a; Integer :b}
|
579
|
+
@ds = @db[:a].order(:a)
|
580
|
+
end
|
581
|
+
after do
|
582
|
+
@db.drop_table(:a)
|
583
|
+
end
|
584
|
+
|
585
|
+
it "#exists should return a usable exists clause" do
|
586
|
+
@ds.filter(@db[:a___c].filter(:c__a=>:a__b).exists).all.should == []
|
587
|
+
@ds.insert(20, 30)
|
588
|
+
@ds.insert(10, 20)
|
589
|
+
@ds.filter(@db[:a___c].filter(:c__a=>:a__b).exists).all.should == [{:a=>10, :b=>20}]
|
590
|
+
end
|
591
|
+
|
592
|
+
it "#filter and #exclude should work with placeholder strings" do
|
593
|
+
@ds.insert(20, 30)
|
594
|
+
@ds.filter("a > ?", 15).all.should == [{:a=>20, :b=>30}]
|
595
|
+
@ds.exclude("b < ?", 15).all.should == [{:a=>20, :b=>30}]
|
596
|
+
@ds.filter("b < ?", 15).invert.all.should == [{:a=>20, :b=>30}]
|
597
|
+
end
|
598
|
+
|
599
|
+
it "#and and #or should work with placeholder strings" do
|
600
|
+
@ds.insert(20, 30)
|
601
|
+
@ds.filter(:a=>20).and(:b=>30).all.should == [{:a=>20, :b=>30}]
|
602
|
+
@ds.filter(:a=>20).and(:b=>15).all.should == []
|
603
|
+
@ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
|
604
|
+
@ds.filter(:a=>10).or(:b=>15).all.should == []
|
605
|
+
end
|
606
|
+
|
607
|
+
it "#having should work correctly" do
|
608
|
+
@ds.unordered!
|
609
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.should == []
|
610
|
+
@ds.insert(20, 30)
|
611
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.should == []
|
612
|
+
@ds.insert(40, 20)
|
613
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.should == [{:b=>20, :c=>40}]
|
614
|
+
end
|
615
|
+
|
616
|
+
cspecify "#having should work without a previous group", :sqlite do
|
617
|
+
@ds.unordered!
|
618
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.should == []
|
619
|
+
@ds.insert(20, 30)
|
620
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.should == []
|
621
|
+
@ds.insert(40, 20)
|
622
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.should == [{:c=>40}]
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
describe "Sequel::Dataset DSL support" do
|
627
|
+
before do
|
628
|
+
@db = INTEGRATION_DB
|
629
|
+
@db.create_table!(:a){Integer :a; Integer :b}
|
630
|
+
@ds = @db[:a].order(:a)
|
631
|
+
end
|
632
|
+
after do
|
633
|
+
@db.drop_table(:a)
|
634
|
+
end
|
635
|
+
|
636
|
+
it "should work with standard mathematical operators" do
|
637
|
+
@ds.insert(20, 10)
|
638
|
+
@ds.get{a + b}.to_i.should == 30
|
639
|
+
@ds.get{a - b}.to_i.should == 10
|
640
|
+
@ds.get{a * b}.to_i.should == 200
|
641
|
+
@ds.get{a / b}.to_i.should == 2
|
642
|
+
end
|
643
|
+
|
644
|
+
cspecify "should work with standard bitwise mathematical operators", :mssql, :h2 do
|
645
|
+
@ds.insert(24, 2)
|
646
|
+
@ds.get{a.sql_number << b}.to_i.should == 96
|
647
|
+
@ds.get{a.sql_number >> b}.to_i.should == 6
|
648
|
+
@ds.delete
|
649
|
+
@ds.insert(3, 5)
|
650
|
+
@ds.get{a.sql_number | b}.to_i.should == 7
|
651
|
+
@ds.get{a.sql_number & b}.to_i.should == 1
|
652
|
+
end
|
653
|
+
|
654
|
+
cspecify "should work with the bitwise compliment operator", :mysql, :h2 do
|
655
|
+
@ds.insert(3, 5)
|
656
|
+
@ds.get{~a.sql_number}.to_i.should == -4
|
657
|
+
end
|
658
|
+
|
659
|
+
cspecify "should work with inequality operators", :mssql do
|
660
|
+
@ds.insert(20, 20)
|
661
|
+
['0', 0, false].should include(@ds.get{a > b})
|
662
|
+
['0', 0, false].should include(@ds.get{a < b})
|
663
|
+
['1', 1, true].should include(@ds.get{a <= b})
|
664
|
+
['1', 1, true].should include(@ds.get{a >= b})
|
665
|
+
end
|
666
|
+
|
667
|
+
cspecify "should work with casting and string concatentation", :mssql do
|
668
|
+
@ds.insert(20, 20)
|
669
|
+
@ds.get{a.cast_string + b}.should == '2020'
|
670
|
+
end
|
671
|
+
|
672
|
+
it "should work with ordering" do
|
673
|
+
@ds.insert(10, 20)
|
674
|
+
@ds.insert(20, 10)
|
675
|
+
@ds.order(:a, :b).all.should == [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
|
676
|
+
@ds.order(:a.asc, :b.asc).all.should == [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
|
677
|
+
@ds.order(:a.desc, :b.desc).all.should == [{:a=>20, :b=>10}, {:a=>10, :b=>20}]
|
678
|
+
end
|
679
|
+
|
680
|
+
it "should work with qualifying" do
|
681
|
+
@ds.insert(10, 20)
|
682
|
+
@ds.get(:a__b).should == 20
|
683
|
+
@ds.get{a__b}.should == 20
|
684
|
+
@ds.get(:b.qualify(:a)).should == 20
|
685
|
+
end
|
686
|
+
|
687
|
+
it "should work with aliasing" do
|
688
|
+
@ds.insert(10, 20)
|
689
|
+
@ds.get(:a__b___c).should == 20
|
690
|
+
@ds.get{a__b.as(c)}.should == 20
|
691
|
+
@ds.get(:b.qualify(:a).as(:c)).should == 20
|
692
|
+
@ds.get(:b.as(:c)).should == 20
|
693
|
+
end
|
694
|
+
|
695
|
+
it "should work with selecting all columns of a table" do
|
696
|
+
@ds.insert(20, 10)
|
697
|
+
@ds.select(:a.*).all.should == [{:a=>20, :b=>10}]
|
698
|
+
end
|
699
|
+
|
700
|
+
it "should work with ranges as hash values" do
|
701
|
+
@ds.insert(20, 10)
|
702
|
+
@ds.filter(:a=>(10..30)).all.should == [{:a=>20, :b=>10}]
|
703
|
+
@ds.filter(:a=>(25..30)).all.should == []
|
704
|
+
@ds.filter(:a=>(10..15)).all.should == []
|
705
|
+
@ds.exclude(:a=>(10..30)).all.should == []
|
706
|
+
@ds.exclude(:a=>(25..30)).all.should == [{:a=>20, :b=>10}]
|
707
|
+
@ds.exclude(:a=>(10..15)).all.should == [{:a=>20, :b=>10}]
|
708
|
+
end
|
709
|
+
|
710
|
+
it "should work with nil as hash value" do
|
711
|
+
@ds.insert(20, nil)
|
712
|
+
@ds.filter(:a=>nil).all.should == []
|
713
|
+
@ds.filter(:b=>nil).all.should == [{:a=>20, :b=>nil}]
|
714
|
+
@ds.exclude(:b=>nil).all.should == []
|
715
|
+
@ds.exclude(:a=>nil).all.should == [{:a=>20, :b=>nil}]
|
716
|
+
end
|
717
|
+
|
718
|
+
it "should work with ranges as hash values" do
|
719
|
+
@ds.insert(20, 10)
|
720
|
+
@ds.filter(:a=>(10..30)).all.should == [{:a=>20, :b=>10}]
|
721
|
+
@ds.filter(:a=>(25..30)).all.should == []
|
722
|
+
@ds.filter(:a=>(10..15)).all.should == []
|
723
|
+
@ds.exclude(:a=>(10..30)).all.should == []
|
724
|
+
@ds.exclude(:a=>(25..30)).all.should == [{:a=>20, :b=>10}]
|
725
|
+
@ds.exclude(:a=>(10..15)).all.should == [{:a=>20, :b=>10}]
|
726
|
+
end
|
727
|
+
|
728
|
+
it "should work with CASE statements" do
|
729
|
+
@ds.insert(20, 10)
|
730
|
+
@ds.filter({{:a=>20}=>20}.case(0) > 0).all.should == [{:a=>20, :b=>10}]
|
731
|
+
@ds.filter({{:a=>15}=>20}.case(0) > 0).all.should == []
|
732
|
+
@ds.filter({20=>20}.case(0, :a) > 0).all.should == [{:a=>20, :b=>10}]
|
733
|
+
@ds.filter({15=>20}.case(0, :a) > 0).all.should == []
|
734
|
+
end
|
735
|
+
|
736
|
+
it "should work multiple value arrays" do
|
737
|
+
@ds.insert(20, 10)
|
738
|
+
@ds.quote_identifiers = false
|
739
|
+
@ds.filter([:a, :b]=>[[20, 10]].sql_array).all.should == [{:a=>20, :b=>10}]
|
740
|
+
@ds.filter([:a, :b]=>[[10, 20]].sql_array).all.should == []
|
741
|
+
@ds.filter([:a, :b]=>[[20, 10], [1, 2]].sql_array).all.should == [{:a=>20, :b=>10}]
|
742
|
+
@ds.filter([:a, :b]=>[[10, 10], [20, 20]].sql_array).all.should == []
|
743
|
+
|
744
|
+
@ds.exclude([:a, :b]=>[[20, 10]].sql_array).all.should == []
|
745
|
+
@ds.exclude([:a, :b]=>[[10, 20]].sql_array).all.should == [{:a=>20, :b=>10}]
|
746
|
+
@ds.exclude([:a, :b]=>[[20, 10], [1, 2]].sql_array).all.should == []
|
747
|
+
@ds.exclude([:a, :b]=>[[10, 10], [20, 20]].sql_array).all.should == [{:a=>20, :b=>10}]
|
748
|
+
end
|
749
|
+
|
750
|
+
it "should work multiple conditions" do
|
751
|
+
@ds.insert(20, 10)
|
752
|
+
@ds.filter(:a=>20, :b=>10).all.should == [{:a=>20, :b=>10}]
|
753
|
+
@ds.filter([[:a, 20], [:b, 10]]).all.should == [{:a=>20, :b=>10}]
|
754
|
+
@ds.filter({:a=>20} & {:b=>10}).all.should == [{:a=>20, :b=>10}]
|
755
|
+
@ds.filter({:a=>20} | {:b=>5}).all.should == [{:a=>20, :b=>10}]
|
756
|
+
@ds.filter(~{:a=>10}).all.should == [{:a=>20, :b=>10}]
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
describe "SQL Extract Function" do
|
761
|
+
before do
|
762
|
+
@db = INTEGRATION_DB
|
763
|
+
@db.create_table!(:a){DateTime :a}
|
764
|
+
@ds = @db[:a].order(:a)
|
765
|
+
end
|
766
|
+
after do
|
767
|
+
@db.drop_table(:a)
|
768
|
+
end
|
769
|
+
|
770
|
+
cspecify "should return the part of the datetime asked for", :sqlite, :mssql do
|
771
|
+
t = Time.now
|
772
|
+
@ds.insert(t)
|
773
|
+
@ds.get{a.extract(:year)}.should == t.year
|
774
|
+
@ds.get{a.extract(:month)}.should == t.month
|
775
|
+
@ds.get{a.extract(:day)}.should == t.day
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
describe "Dataset string methods" do
|
780
|
+
before do
|
781
|
+
@db = INTEGRATION_DB
|
782
|
+
@db.create_table!(:a){String :a; String :b}
|
783
|
+
@ds = @db[:a].order(:a)
|
784
|
+
end
|
785
|
+
after do
|
786
|
+
@db.drop_table(:a)
|
787
|
+
end
|
788
|
+
|
789
|
+
it "#grep should return matching rows" do
|
790
|
+
@ds.insert('foo', 'bar')
|
791
|
+
@ds.grep(:a, 'foo').all.should == [{:a=>'foo', :b=>'bar'}]
|
792
|
+
@ds.grep(:b, 'foo').all.should == []
|
793
|
+
@ds.grep(:b, 'bar').all.should == [{:a=>'foo', :b=>'bar'}]
|
794
|
+
@ds.grep(:a, 'bar').all.should == []
|
795
|
+
@ds.grep([:a, :b], %w'foo bar').all.should == [{:a=>'foo', :b=>'bar'}]
|
796
|
+
@ds.grep([:a, :b], %w'boo far').all.should == []
|
797
|
+
end
|
798
|
+
|
799
|
+
it "#like should return matching rows" do
|
800
|
+
@ds.insert('foo', 'bar')
|
801
|
+
@ds.filter(:a.like('foo')).all.should == [{:a=>'foo', :b=>'bar'}]
|
802
|
+
@ds.filter(:a.like('bar')).all.should == []
|
803
|
+
@ds.filter(:a.like('foo', 'bar')).all.should == [{:a=>'foo', :b=>'bar'}]
|
804
|
+
end
|
805
|
+
|
806
|
+
it "#ilike should return matching rows, in a case insensitive manner" do
|
807
|
+
@ds.insert('foo', 'bar')
|
808
|
+
@ds.filter(:a.ilike('Foo')).all.should == [{:a=>'foo', :b=>'bar'}]
|
809
|
+
@ds.filter(:a.ilike('baR')).all.should == []
|
810
|
+
@ds.filter(:a.ilike('FOO', 'BAR')).all.should == [{:a=>'foo', :b=>'bar'}]
|
811
|
+
end
|
812
|
+
|
813
|
+
it "should work with strings created with sql_string_join" do
|
814
|
+
@ds.insert('foo', 'bar')
|
815
|
+
@ds.get([:a, :b].sql_string_join).should == 'foobar'
|
816
|
+
@ds.get([:a, :b].sql_string_join(' ')).should == 'foo bar'
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
describe "Dataset identifier methods" do
|
821
|
+
before do
|
822
|
+
class ::String
|
823
|
+
def uprev
|
824
|
+
upcase.reverse
|
825
|
+
end
|
826
|
+
end
|
827
|
+
@db = INTEGRATION_DB
|
828
|
+
@db.create_table!(:a){Integer :ab}
|
829
|
+
@ds = @db[:a].order(:ab)
|
830
|
+
@ds.insert(1)
|
831
|
+
end
|
832
|
+
after do
|
833
|
+
@db.drop_table(:a)
|
834
|
+
end
|
835
|
+
|
836
|
+
it "#identifier_output_method should change how identifiers are output" do
|
837
|
+
@ds.identifier_output_method = :upcase
|
838
|
+
@ds.first.should == {:AB=>1}
|
839
|
+
@ds.identifier_output_method = :uprev
|
840
|
+
@ds.first.should == {:BA=>1}
|
841
|
+
end
|
842
|
+
|
843
|
+
it "should work when not quoting identifiers" do
|
844
|
+
@ds.quote_identifiers = false
|
845
|
+
@ds.first.should == {:ab=>1}
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
849
|
+
describe "Dataset defaults and overrides" do
|
850
|
+
before do
|
851
|
+
@db = INTEGRATION_DB
|
852
|
+
@db.create_table!(:a){Integer :a}
|
853
|
+
@ds = @db[:a].order(:a)
|
854
|
+
end
|
855
|
+
after do
|
856
|
+
@db.drop_table(:a)
|
857
|
+
end
|
858
|
+
|
859
|
+
it "#set_defaults should set defaults that can be overridden" do
|
860
|
+
@ds = @ds.set_defaults(:a=>10)
|
861
|
+
@ds.insert
|
862
|
+
@ds.insert(:a=>20)
|
863
|
+
@ds.all.should == [{:a=>10}, {:a=>20}]
|
864
|
+
end
|
865
|
+
|
866
|
+
it "#set_overrides should set defaults that cannot be overridden" do
|
867
|
+
@ds = @ds.set_overrides(:a=>10)
|
868
|
+
@ds.insert
|
869
|
+
@ds.insert(:a=>20)
|
870
|
+
@ds.all.should == [{:a=>10}, {:a=>10}]
|
871
|
+
end
|
498
872
|
end
|