sequel 3.24.1 → 3.25.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -759,6 +759,11 @@ describe "Dataset#exclude" do
759
759
  "SELECT * FROM test WHERE (region != 'Asia')"
760
760
  end
761
761
 
762
+ specify "should affect the having clause if having clause is already used" do
763
+ @dataset.group_and_count(:name).having{count > 2}.exclude{count > 5}.sql.should ==
764
+ "SELECT name, count(*) AS count FROM test GROUP BY name HAVING ((count > 2) AND (count <= 5))"
765
+ end
766
+
762
767
  specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
763
768
  @dataset.exclude(:region => 'Asia', :name => 'Japan').select_sql.
764
769
  should match(Regexp.union(/WHERE \(\(region != 'Asia'\) OR \(name != 'Japan'\)\)/,
@@ -793,6 +798,28 @@ describe "Dataset#exclude" do
793
798
  end
794
799
  end
795
800
 
801
+ describe "Dataset#exclude_where" do
802
+ before do
803
+ @dataset = Sequel::Dataset.new(nil).from(:test)
804
+ end
805
+
806
+ specify "should correctly negate the expression and add it to the where clause" do
807
+ @dataset.exclude_where(:region=>'Asia').sql.should == "SELECT * FROM test WHERE (region != 'Asia')"
808
+ @dataset.exclude_where(:region=>'Asia').exclude_where(:region=>'NA').sql.should == "SELECT * FROM test WHERE ((region != 'Asia') AND (region != 'NA'))"
809
+ end
810
+
811
+ specify "should affect the where clause even if having clause is already used" do
812
+ @dataset.group_and_count(:name).having{count > 2}.exclude_where(:region=>'Asia').sql.should ==
813
+ "SELECT name, count(*) AS count FROM test WHERE (region != 'Asia') GROUP BY name HAVING (count > 2)"
814
+ end
815
+ end
816
+
817
+ describe "Dataset#exclude_having" do
818
+ specify "should correctly negate the expression and add it to the having clause" do
819
+ Sequel::Dataset.new(nil).from(:test).exclude_having{count > 2}.exclude_having{count < 0}.sql.should == "SELECT * FROM test HAVING ((count <= 2) AND (count >= 0))"
820
+ end
821
+ end
822
+
796
823
  describe "Dataset#invert" do
797
824
  before do
798
825
  @d = Sequel::Dataset.new(nil).from(:test)
@@ -897,7 +924,7 @@ describe "Dataset#group_by" do
897
924
  "SELECT * FROM test GROUP BY (type_id IS NULL)"
898
925
  end
899
926
 
900
- specify "should ungroup when passed nil, empty, or no arguments" do
927
+ specify "should ungroup when passed nil or no arguments" do
901
928
  @dataset.group_by.select_sql.should ==
902
929
  "SELECT * FROM test"
903
930
  @dataset.group_by(nil).select_sql.should ==
@@ -915,6 +942,13 @@ describe "Dataset#group_by" do
915
942
  @dataset.group(:type_id=>nil).select_sql.should ==
916
943
  "SELECT * FROM test GROUP BY (type_id IS NULL)"
917
944
  end
945
+
946
+ specify "should take a virtual row block" do
947
+ @dataset.group{type_id > 1}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1)"
948
+ @dataset.group_by{type_id > 1}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1)"
949
+ @dataset.group{[type_id > 1, type_id < 2]}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1), (type_id < 2)"
950
+ @dataset.group(:foo){type_id > 1}.sql.should == "SELECT * FROM test GROUP BY foo, (type_id > 1)"
951
+ end
918
952
  end
919
953
 
920
954
  describe "Dataset#as" do
@@ -1219,6 +1253,27 @@ describe "Dataset#select" do
1219
1253
  end
1220
1254
  end
1221
1255
 
1256
+ describe "Dataset#select_group" do
1257
+ before do
1258
+ @d = Sequel::Dataset.new(nil).from(:test)
1259
+ end
1260
+
1261
+ specify "should set both SELECT and GROUP" do
1262
+ @d.select_group(:name).sql.should == 'SELECT name FROM test GROUP BY name'
1263
+ @d.select_group(:a, :b__c, :d___e).sql.should == 'SELECT a, b.c, d AS e FROM test GROUP BY a, b.c, d'
1264
+ end
1265
+
1266
+ specify "should remove from both SELECT and GROUP if no arguments" do
1267
+ @d.select_group(:name).select_group.sql.should == 'SELECT * FROM test'
1268
+ end
1269
+
1270
+ specify "should accept virtual row blocks" do
1271
+ @d.select_group{name}.sql.should == 'SELECT name FROM test GROUP BY name'
1272
+ @d.select_group{[name, f(v).as(a)]}.sql.should == 'SELECT name, f(v) AS a FROM test GROUP BY name, f(v)'
1273
+ @d.select_group(:name){f(v).as(a)}.sql.should == 'SELECT name, f(v) AS a FROM test GROUP BY name, f(v)'
1274
+ end
1275
+ end
1276
+
1222
1277
  describe "Dataset#select_all" do
1223
1278
  before do
1224
1279
  @d = Sequel::Dataset.new(nil).from(:test)
@@ -1231,6 +1286,14 @@ describe "Dataset#select_all" do
1231
1286
  specify "should overrun the previous select option" do
1232
1287
  @d.select!(:a, :b, :c).select_all.sql.should == 'SELECT * FROM test'
1233
1288
  end
1289
+
1290
+ specify "should select all columns in a table if given an argument" do
1291
+ @d.select_all(:test).sql.should == 'SELECT test.* FROM test'
1292
+ end
1293
+
1294
+ specify "should select all columns all tables if given a multiple arguments" do
1295
+ @d.select_all(:test, :foo).sql.should == 'SELECT test.*, foo.* FROM test'
1296
+ end
1234
1297
  end
1235
1298
 
1236
1299
  describe "Dataset#select_more" do
@@ -1774,6 +1837,12 @@ describe "Dataset#group_and_count" do
1774
1837
  @ds.group_and_count(:name.identifier.as(:n)).sql.should ==
1775
1838
  "SELECT name AS n, count(*) AS count FROM test GROUP BY name"
1776
1839
  end
1840
+
1841
+ specify "should take a virtual row block" do
1842
+ @ds.group_and_count{(type_id > 1).as(t)}.sql.should == "SELECT (type_id > 1) AS t, count(*) AS count FROM test GROUP BY (type_id > 1)"
1843
+ @ds.group_and_count{[(type_id > 1).as(t), type_id < 2]}.sql.should == "SELECT (type_id > 1) AS t, (type_id < 2), count(*) AS count FROM test GROUP BY (type_id > 1), (type_id < 2)"
1844
+ @ds.group_and_count(:foo){type_id > 1}.sql.should == "SELECT foo, (type_id > 1), count(*) AS count FROM test GROUP BY foo, (type_id > 1)"
1845
+ end
1777
1846
  end
1778
1847
 
1779
1848
  describe "Dataset#empty?" do
@@ -452,6 +452,45 @@ describe "Blockless Ruby Filters" do
452
452
  e2 = ~:comment.like('%:hidden:%')
453
453
  e1.should == e2
454
454
  end
455
+
456
+ it "should support expression filter methods on Datasets" do
457
+ d = @d.select(:a)
458
+
459
+ @d.lit(d + 1).should == '((SELECT a FROM items) + 1)'
460
+ @d.lit(d - 1).should == '((SELECT a FROM items) - 1)'
461
+ @d.lit(d * 1).should == '((SELECT a FROM items) * 1)'
462
+ @d.lit(d / 1).should == '((SELECT a FROM items) / 1)'
463
+
464
+ @d.lit(d => 1).should == '((SELECT a FROM items) = 1)'
465
+ @d.lit(~{d => 1}).should == '((SELECT a FROM items) != 1)'
466
+ @d.lit(d > 1).should == '((SELECT a FROM items) > 1)'
467
+ @d.lit(d < 1).should == '((SELECT a FROM items) < 1)'
468
+ @d.lit(d >= 1).should == '((SELECT a FROM items) >= 1)'
469
+ @d.lit(d <= 1).should == '((SELECT a FROM items) <= 1)'
470
+
471
+ @d.lit(d.as(:b)).should == '(SELECT a FROM items) AS b'
472
+
473
+ @d.lit(d & :b).should == '((SELECT a FROM items) AND b)'
474
+ @d.lit(d | :b).should == '((SELECT a FROM items) OR b)'
475
+ @d.lit(~d).should == 'NOT (SELECT a FROM items)'
476
+
477
+ @d.lit(d.cast(Integer)).should == 'CAST((SELECT a FROM items) AS integer)'
478
+ @d.lit(d.cast_numeric).should == 'CAST((SELECT a FROM items) AS integer)'
479
+ @d.lit(d.cast_string).should == 'CAST((SELECT a FROM items) AS varchar(255))'
480
+ @d.lit(d.cast_numeric << :b).should == '(CAST((SELECT a FROM items) AS integer) << b)'
481
+ @d.lit(d.cast_string + :b).should == '(CAST((SELECT a FROM items) AS varchar(255)) || b)'
482
+
483
+ @d.lit(d.extract(:year)).should == 'extract(year FROM (SELECT a FROM items))'
484
+ @d.lit(d.sql_boolean & :b).should == '((SELECT a FROM items) AND b)'
485
+ @d.lit(d.sql_number << :b).should == '((SELECT a FROM items) << b)'
486
+ @d.lit(d.sql_string + :b).should == '((SELECT a FROM items) || b)'
487
+
488
+ @d.lit(d.asc).should == '(SELECT a FROM items) ASC'
489
+ @d.lit(d.desc).should == '(SELECT a FROM items) DESC'
490
+
491
+ @d.lit(d.like(:b)).should == '((SELECT a FROM items) LIKE b)'
492
+ @d.lit(d.ilike(:b)).should == '((SELECT a FROM items) ILIKE b)'
493
+ end
455
494
 
456
495
  if RUBY_VERSION < '1.9.0'
457
496
  it "should not allow inequality operations on true, false, or nil" do
@@ -594,6 +594,16 @@ describe "DB#drop_table" do
594
594
  @db.drop_table :cats
595
595
  @db.sqls.should == ['DROP TABLE cats']
596
596
  end
597
+
598
+ specify "should drop multiple tables at once" do
599
+ @db.drop_table :cats, :dogs
600
+ @db.sqls.should == ['DROP TABLE cats', 'DROP TABLE dogs']
601
+ end
602
+
603
+ specify "should take an options hash and support the :cascade option" do
604
+ @db.drop_table :cats, :dogs, :cascade=>true
605
+ @db.sqls.should == ['DROP TABLE cats CASCADE', 'DROP TABLE dogs CASCADE']
606
+ end
597
607
  end
598
608
 
599
609
  describe "DB#alter_table" do
@@ -722,6 +732,13 @@ describe "DB#alter_table" do
722
732
  @db.sqls.should == ["ALTER TABLE cats DROP COLUMN score"]
723
733
  end
724
734
 
735
+ specify "should support drop_column with :cascade=>true option" do
736
+ @db.alter_table(:cats) do
737
+ drop_column :score, :cascade=>true
738
+ end
739
+ @db.sqls.should == ["ALTER TABLE cats DROP COLUMN score CASCADE"]
740
+ end
741
+
725
742
  specify "should support drop_constraint" do
726
743
  @db.alter_table(:cats) do
727
744
  drop_constraint :valid_score
@@ -729,6 +746,13 @@ describe "DB#alter_table" do
729
746
  @db.sqls.should == ["ALTER TABLE cats DROP CONSTRAINT valid_score"]
730
747
  end
731
748
 
749
+ specify "should support drop_constraint with :cascade=>true option" do
750
+ @db.alter_table(:cats) do
751
+ drop_constraint :valid_score, :cascade=>true
752
+ end
753
+ @db.sqls.should == ["ALTER TABLE cats DROP CONSTRAINT valid_score CASCADE"]
754
+ end
755
+
732
756
  specify "should support drop_index" do
733
757
  @db.alter_table(:cats) do
734
758
  drop_index :name
@@ -776,6 +800,286 @@ describe "DB#alter_table" do
776
800
  end
777
801
  end
778
802
 
803
+ describe "Database#create_table" do
804
+ before do
805
+ @db = DummyDatabase.new
806
+ end
807
+
808
+ specify "should construct proper SQL" do
809
+ @db.create_table :test do
810
+ primary_key :id, :integer, :null => false
811
+ column :name, :text
812
+ index :name, :unique => true
813
+ end
814
+ @db.sqls.should == [
815
+ 'CREATE TABLE test (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
816
+ 'CREATE UNIQUE INDEX test_name_index ON test (name)'
817
+ ]
818
+ end
819
+
820
+ specify "should create a temporary table" do
821
+ @db.create_table :test_tmp, :temp => true do
822
+ primary_key :id, :integer, :null => false
823
+ column :name, :text
824
+ index :name, :unique => true
825
+ end
826
+
827
+ @db.sqls.should == [
828
+ 'CREATE TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
829
+ 'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
830
+ ]
831
+ end
832
+
833
+ specify "should not use default schema when creating a temporary table" do
834
+ @db.default_schema = :foo
835
+ @db.create_table :test_tmp, :temp => true do
836
+ column :name, :text
837
+ end
838
+ @db.sqls.should == ['CREATE TEMPORARY TABLE test_tmp (name text)']
839
+ end
840
+ end
841
+
842
+ describe "Database#alter_table" do
843
+ before do
844
+ @db = DummyDatabase.new
845
+ end
846
+
847
+ specify "should construct proper SQL" do
848
+ @db.alter_table :xyz do
849
+ add_column :aaa, :text, :null => false, :unique => true
850
+ drop_column :bbb
851
+ rename_column :ccc, :ddd
852
+ set_column_type :eee, :integer
853
+ set_column_default :hhh, 'abcd'
854
+
855
+ add_index :fff, :unique => true
856
+ drop_index :ggg
857
+ end
858
+
859
+ @db.sqls.should == [
860
+ 'ALTER TABLE xyz ADD COLUMN aaa text NOT NULL UNIQUE',
861
+ 'ALTER TABLE xyz DROP COLUMN bbb',
862
+ 'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
863
+ 'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
864
+ "ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
865
+
866
+ 'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
867
+ 'DROP INDEX xyz_ggg_index'
868
+ ]
869
+ end
870
+ end
871
+
872
+ describe "Database#add_column" do
873
+ before do
874
+ @db = DummyDatabase.new
875
+ end
876
+
877
+ specify "should construct proper SQL" do
878
+ @db.add_column :test, :name, :text, :unique => true
879
+ @db.sqls.should == [
880
+ 'ALTER TABLE test ADD COLUMN name text UNIQUE'
881
+ ]
882
+ end
883
+ end
884
+
885
+ describe "Database#drop_column" do
886
+ before do
887
+ @db = DummyDatabase.new
888
+ end
889
+
890
+ specify "should construct proper SQL" do
891
+ @db.drop_column :test, :name
892
+ @db.sqls.should == ['ALTER TABLE test DROP COLUMN name']
893
+ end
894
+
895
+ specify "should use CASCADE for :cascade=>true option" do
896
+ @db.drop_column :test, :name, :cascade=>true
897
+ @db.sqls.should == ['ALTER TABLE test DROP COLUMN name CASCADE']
898
+ end
899
+ end
900
+
901
+ describe "Database#rename_column" do
902
+ before do
903
+ @db = DummyDatabase.new
904
+ end
905
+
906
+ specify "should construct proper SQL" do
907
+ @db.rename_column :test, :abc, :def
908
+ @db.sqls.should == [
909
+ 'ALTER TABLE test RENAME COLUMN abc TO def'
910
+ ]
911
+ end
912
+ end
913
+
914
+ describe "Database#set_column_type" do
915
+ before do
916
+ @db = DummyDatabase.new
917
+ end
918
+
919
+ specify "should construct proper SQL" do
920
+ @db.set_column_type :test, :name, :integer
921
+ @db.sqls.should == [
922
+ 'ALTER TABLE test ALTER COLUMN name TYPE integer'
923
+ ]
924
+ end
925
+ end
926
+
927
+ describe "Database#set_column_default" do
928
+ before do
929
+ @db = DummyDatabase.new
930
+ end
931
+
932
+ specify "should construct proper SQL" do
933
+ @db.set_column_default :test, :name, 'zyx'
934
+ @db.sqls.should == [
935
+ "ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
936
+ ]
937
+ end
938
+ end
939
+
940
+ describe "Database#add_index" do
941
+ before do
942
+ @db = DummyDatabase.new
943
+ end
944
+
945
+ specify "should construct proper SQL" do
946
+ @db.add_index :test, :name, :unique => true
947
+ @db.sqls.should == [
948
+ 'CREATE UNIQUE INDEX test_name_index ON test (name)'
949
+ ]
950
+ end
951
+
952
+ specify "should accept multiple columns" do
953
+ @db.add_index :test, [:one, :two]
954
+ @db.sqls.should == [
955
+ 'CREATE INDEX test_one_two_index ON test (one, two)'
956
+ ]
957
+ end
958
+ end
959
+
960
+ describe "Database#drop_index" do
961
+ before do
962
+ @db = DummyDatabase.new
963
+ end
964
+
965
+ specify "should construct proper SQL" do
966
+ @db.drop_index :test, :name
967
+ @db.sqls.should == [
968
+ 'DROP INDEX test_name_index'
969
+ ]
970
+ end
971
+
972
+ end
973
+
974
+ describe "Database#drop_table" do
975
+ before do
976
+ @db = DummyDatabase.new
977
+ end
978
+
979
+ specify "should construct proper SQL" do
980
+ @db.drop_table :test
981
+ @db.sqls.should == ['DROP TABLE test']
982
+ end
983
+
984
+ specify "should accept multiple table names" do
985
+ @db.drop_table :a, :bb, :ccc
986
+ @db.sqls.should == [
987
+ 'DROP TABLE a',
988
+ 'DROP TABLE bb',
989
+ 'DROP TABLE ccc'
990
+ ]
991
+ end
992
+ end
993
+
994
+ describe "Database#rename_table" do
995
+ before do
996
+ @db = DummyDatabase.new
997
+ end
998
+
999
+ specify "should construct proper SQL" do
1000
+ @db.rename_table :abc, :xyz
1001
+ @db.sqls.should == ['ALTER TABLE abc RENAME TO xyz']
1002
+ end
1003
+ end
1004
+
1005
+ describe "Database#create_view" do
1006
+ before do
1007
+ @db = DummyDatabase.new
1008
+ end
1009
+
1010
+ specify "should construct proper SQL with raw SQL" do
1011
+ @db.create_view :test, "SELECT * FROM xyz"
1012
+ @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1013
+ @db.sqls.clear
1014
+ @db.create_view :test.identifier, "SELECT * FROM xyz"
1015
+ @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1016
+ end
1017
+
1018
+ specify "should construct proper SQL with dataset" do
1019
+ @db.create_view :test, @db[:items].select(:a, :b).order(:c)
1020
+ @db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
1021
+ @db.sqls.clear
1022
+ @db.create_view :test.qualify(:sch), @db[:items].select(:a, :b).order(:c)
1023
+ @db.sqls.should == ['CREATE VIEW sch.test AS SELECT a, b FROM items ORDER BY c']
1024
+ end
1025
+ end
1026
+
1027
+ describe "Database#create_or_replace_view" do
1028
+ before do
1029
+ @db = DummyDatabase.new
1030
+ end
1031
+
1032
+ specify "should construct proper SQL with raw SQL" do
1033
+ @db.create_or_replace_view :test, "SELECT * FROM xyz"
1034
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT * FROM xyz']
1035
+ @db.sqls.clear
1036
+ @db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
1037
+ @db.sqls.should == ['CREATE OR REPLACE VIEW sch.test AS SELECT * FROM xyz']
1038
+ end
1039
+
1040
+ specify "should construct proper SQL with dataset" do
1041
+ @db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
1042
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1043
+ @db.sqls.clear
1044
+ @db.create_or_replace_view :test.identifier, @db[:items].select(:a, :b).order(:c)
1045
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1046
+ end
1047
+ end
1048
+
1049
+ describe "Database#drop_view" do
1050
+ before do
1051
+ @db = DummyDatabase.new
1052
+ end
1053
+
1054
+ specify "should construct proper SQL" do
1055
+ @db.drop_view :test
1056
+ @db.drop_view :test.identifier
1057
+ @db.drop_view :sch__test
1058
+ @db.drop_view :test.qualify(:sch)
1059
+ @db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
1060
+ end
1061
+
1062
+ specify "should drop multiple views at once" do
1063
+ @db.drop_view :cats, :dogs
1064
+ @db.sqls.should == ['DROP VIEW cats', 'DROP VIEW dogs']
1065
+ end
1066
+
1067
+ specify "should take an options hash and support the :cascade option" do
1068
+ @db.drop_view :cats, :dogs, :cascade=>true
1069
+ @db.sqls.should == ['DROP VIEW cats CASCADE', 'DROP VIEW dogs CASCADE']
1070
+ end
1071
+ end
1072
+
1073
+ describe "Database#alter_table_sql" do
1074
+ before do
1075
+ @db = DummyDatabase.new
1076
+ end
1077
+
1078
+ specify "should raise error for an invalid op" do
1079
+ proc {@db.send(:alter_table_sql, :mau, :op => :blah)}.should raise_error(Sequel::Error)
1080
+ end
1081
+ end
1082
+
779
1083
  describe "Schema Parser" do
780
1084
  before do
781
1085
  @sqls = []