sequel 3.24.1 → 3.25.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.
@@ -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 = []