File: pg_enum_spec.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (154 lines) | stat: -rw-r--r-- 7,092 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
require_relative "spec_helper"

Sequel.extension :migration

describe "pg_enum extension" do
  mod = Module.new do
    private
    def schema_parse_table(*)
      [[:a, {:oid=>1}], [:b, {:oid=>1234}]]
    end
    def _metadata_dataset
      super.with_fetch([[{:v=>1, :enumlabel=>'a'}, {:v=>1, :enumlabel=>'b'}, {:v=>1, :enumlabel=>'c'}], [{:typname=>'enum1', :v=>212389}]])
    end
  end
  before do
    @db = Sequel.connect('mock://postgres')
    @db.extend_datasets{def quote_identifiers?; false end}
    @db.extend(mod)
    @db.extension(:pg_array, :pg_enum)
    @db.sqls
  end

  it "should parse enum labels respecting the sort order" do
    @db.send(:parse_enum_labels)
    @db.sqls.must_equal ["SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
  end

  it "should parse enum labels without the sort order on PostgreSQL < 9.1" do
    def @db.server_version(_=nil); 90000; end
    @db.send(:parse_enum_labels)
    @db.sqls.must_equal ["SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid",
    "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
  end

  it "should add enum values to parsed schema columns" do
    @db.schema(:foo).must_equal [[:a, {:oid=>1, :ruby_default=>nil, :type=>:enum, :enum_values=>["a", "b", "c"]}], [:b, {:oid=>1234, :ruby_default=>nil}]]
  end

  it "should typecast objects to string" do
    @db.typecast_value(:enum, :a).must_equal 'a'
  end

  it "should add array parsers for enum values" do
    @db.conversion_procs[212389].call('{a,b,c}').must_equal %w'a b c'
  end

  it "should not add array parser if there is already a conversion proc" do
    @db = Sequel.connect('mock://postgres')
    @db.extend_datasets{def quote_identifiers?; false end}
    @db.extend(mod)
    pr = proc{}
    @db.conversion_procs[212389] = pr
    @db.extension(:pg_array, :pg_enum)
    @db.conversion_procs[212389].must_equal pr
    @db.sqls.must_equal ["SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((oid IN (1)) AND (typarray != 0))"]
  end

  it "should not add array parsers for enum values if pg_array extension is not used" do
    @db = Sequel.connect('mock://postgres')
    @db.extend_datasets{def quote_identifiers?; false end}
    @db.extend(mod)
    @db.extension(:pg_enum)
    @db.conversion_procs[212389].must_be_nil
    @db.sqls.must_equal ["SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder"]
  end

  it "should support #create_enum method for adding a new enum" do
    @db.create_enum(:foo, [:a, :b, :c])
    @db.sqls.first.must_equal "CREATE TYPE foo AS ENUM ('a', 'b', 'c')"
    @db.create_enum(Sequel[:sch][:foo], %w'a b c')
    @db.sqls.first.must_equal "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
  end

  with_symbol_splitting "should support #create_enum method for adding a new enum with qualified symbol" do
    @db.create_enum(:sch__foo, %w'a b c')
    @db.sqls.first.must_equal "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
  end

  it "should support #rename_enum method for renameing an enum" do
    @db.rename_enum(:foo, :bar)
    @db.sqls.first.must_equal "ALTER TYPE foo RENAME TO bar"
    @db.rename_enum(Sequel[:sch][:foo], Sequel[:sch][:bar])
    @db.sqls.first.must_equal "ALTER TYPE sch.foo RENAME TO sch.bar"
  end

  it "should support #rename_enum_value method for renameing an enum value" do
    @db.rename_enum_value(:foo, :b, :x)
    @db.sqls.first.must_equal "ALTER TYPE foo RENAME VALUE 'b' TO 'x'"
  end

  it "should support #drop_enum method for dropping an enum" do
    @db.drop_enum(:foo)
    @db.sqls.first.must_equal "DROP TYPE foo"
    @db.drop_enum(Sequel[:sch][:foo], :if_exists=>true)
    @db.sqls.first.must_equal "DROP TYPE IF EXISTS sch.foo"
    @db.drop_enum('foo', :cascade=>true)
    @db.sqls.first.must_equal "DROP TYPE foo CASCADE"
  end

  with_symbol_splitting "should support #drop_enum method for dropping an enum with a splittable symbol" do
    @db.drop_enum(:sch__foo, :if_exists=>true)
    @db.sqls.first.must_equal "DROP TYPE IF EXISTS sch.foo"
  end

  it "should support #add_enum_value method for adding value to an existing enum" do
    @db.add_enum_value(:foo, :a)
    @db.sqls.first.must_equal "ALTER TYPE foo ADD VALUE 'a'"
  end

  it "should support :before option for #add_enum_value method for adding value before an existing enum value" do
    @db.add_enum_value('foo', :a, :before=>:b)
    @db.sqls.first.must_equal "ALTER TYPE foo ADD VALUE 'a' BEFORE 'b'"
  end

  it "should support :after option for #add_enum_value method for adding value after an existing enum value" do
    @db.add_enum_value(Sequel[:sch][:foo], :a, :after=>:b)
    @db.sqls.first.must_equal "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
  end

  with_symbol_splitting "should support :after option for #add_enum_value method for adding value after an existing enum value with splittable symbol" do
    @db.add_enum_value(:sch__foo, :a, :after=>:b)
    @db.sqls.first.must_equal "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
  end

  it "should support :if_not_exists option for #add_enum_value method for not adding the value if it exists" do
    @db.add_enum_value(:foo, :a, :if_not_exists=>true)
    @db.sqls.first.must_equal "ALTER TYPE foo ADD VALUE IF NOT EXISTS 'a'"
  end

  it "should reverse a create_enum directive in a migration" do
    m = Sequel.migration{change{create_enum(:type_name, %w'value1 value2 value3')}}
    m.apply(@db, :up)
    @db.sqls.must_equal ["CREATE TYPE type_name AS ENUM ('value1', 'value2', 'value3')",
      "SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
    m.apply(@db, :down)
    @db.sqls.must_equal ["DROP TYPE type_name", "SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
  end

  it "should reverse a rename_enum directive in a migration" do
    m = Sequel.migration{change{rename_enum(:old_type_name, :new_type_name)}}
    m.apply(@db, :up)
    @db.sqls.must_equal ["ALTER TYPE old_type_name RENAME TO new_type_name",
      "SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
    m.apply(@db, :down)
    @db.sqls.must_equal ["ALTER TYPE new_type_name RENAME TO old_type_name",
      "SELECT CAST(enumtypid AS integer) AS v, enumlabel FROM pg_enum ORDER BY enumtypid, enumsortorder",
      "SELECT typname, CAST(typarray AS integer) AS v FROM pg_type WHERE ((1 = 0) AND (typarray != 0))"]
  end
end