sequel 3.5.0 → 3.6.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 +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
|