sequel 3.5.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/CHANGELOG +108 -0
  2. data/README.rdoc +25 -14
  3. data/Rakefile +20 -1
  4. data/doc/advanced_associations.rdoc +61 -64
  5. data/doc/cheat_sheet.rdoc +16 -7
  6. data/doc/opening_databases.rdoc +3 -3
  7. data/doc/prepared_statements.rdoc +1 -1
  8. data/doc/reflection.rdoc +2 -1
  9. data/doc/release_notes/3.6.0.txt +366 -0
  10. data/doc/schema.rdoc +19 -14
  11. data/lib/sequel/adapters/amalgalite.rb +5 -27
  12. data/lib/sequel/adapters/jdbc.rb +13 -3
  13. data/lib/sequel/adapters/jdbc/h2.rb +17 -0
  14. data/lib/sequel/adapters/jdbc/mysql.rb +20 -7
  15. data/lib/sequel/adapters/mysql.rb +4 -3
  16. data/lib/sequel/adapters/oracle.rb +1 -1
  17. data/lib/sequel/adapters/postgres.rb +87 -28
  18. data/lib/sequel/adapters/shared/mssql.rb +47 -6
  19. data/lib/sequel/adapters/shared/mysql.rb +12 -31
  20. data/lib/sequel/adapters/shared/postgres.rb +15 -12
  21. data/lib/sequel/adapters/shared/sqlite.rb +18 -0
  22. data/lib/sequel/adapters/sqlite.rb +1 -16
  23. data/lib/sequel/connection_pool.rb +1 -1
  24. data/lib/sequel/core.rb +1 -1
  25. data/lib/sequel/database.rb +1 -1
  26. data/lib/sequel/database/schema_generator.rb +2 -0
  27. data/lib/sequel/database/schema_sql.rb +1 -1
  28. data/lib/sequel/dataset.rb +5 -179
  29. data/lib/sequel/dataset/actions.rb +123 -0
  30. data/lib/sequel/dataset/convenience.rb +18 -10
  31. data/lib/sequel/dataset/features.rb +65 -0
  32. data/lib/sequel/dataset/prepared_statements.rb +29 -23
  33. data/lib/sequel/dataset/query.rb +429 -0
  34. data/lib/sequel/dataset/sql.rb +67 -435
  35. data/lib/sequel/model/associations.rb +77 -13
  36. data/lib/sequel/model/base.rb +30 -8
  37. data/lib/sequel/model/errors.rb +4 -4
  38. data/lib/sequel/plugins/caching.rb +38 -15
  39. data/lib/sequel/plugins/force_encoding.rb +18 -7
  40. data/lib/sequel/plugins/hook_class_methods.rb +4 -0
  41. data/lib/sequel/plugins/many_through_many.rb +1 -1
  42. data/lib/sequel/plugins/nested_attributes.rb +40 -11
  43. data/lib/sequel/plugins/serialization.rb +17 -3
  44. data/lib/sequel/plugins/validation_helpers.rb +65 -18
  45. data/lib/sequel/sql.rb +23 -1
  46. data/lib/sequel/version.rb +1 -1
  47. data/spec/adapters/mssql_spec.rb +96 -10
  48. data/spec/adapters/mysql_spec.rb +19 -0
  49. data/spec/adapters/postgres_spec.rb +65 -2
  50. data/spec/adapters/sqlite_spec.rb +10 -0
  51. data/spec/core/core_sql_spec.rb +9 -0
  52. data/spec/core/database_spec.rb +8 -4
  53. data/spec/core/dataset_spec.rb +122 -29
  54. data/spec/core/expression_filters_spec.rb +17 -0
  55. data/spec/extensions/caching_spec.rb +43 -3
  56. data/spec/extensions/force_encoding_spec.rb +43 -1
  57. data/spec/extensions/nested_attributes_spec.rb +55 -2
  58. data/spec/extensions/validation_helpers_spec.rb +71 -0
  59. data/spec/integration/associations_test.rb +281 -0
  60. data/spec/integration/dataset_test.rb +383 -9
  61. data/spec/integration/eager_loader_test.rb +0 -65
  62. data/spec/integration/model_test.rb +110 -0
  63. data/spec/integration/plugin_test.rb +306 -0
  64. data/spec/integration/prepared_statement_test.rb +32 -0
  65. data/spec/integration/schema_test.rb +8 -3
  66. data/spec/integration/spec_helper.rb +1 -25
  67. data/spec/model/association_reflection_spec.rb +38 -0
  68. data/spec/model/associations_spec.rb +184 -8
  69. data/spec/model/eager_loading_spec.rb +23 -0
  70. data/spec/model/model_spec.rb +8 -0
  71. data/spec/model/record_spec.rb +84 -1
  72. 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