File: schema_generator_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 (257 lines) | stat: -rw-r--r-- 9,694 bytes parent folder | download | duplicates (2)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
require_relative "spec_helper"

describe Sequel::Schema::CreateTableGenerator do
  before do
    @generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
      string(:title).must_be_nil
      column(:body, :text).must_be_nil
      foreign_key(:parent_id).must_be_nil
      primary_key(:id).must_be_nil
      check('price > 100').must_be_nil
      constraint(:xxx){{:yyy => :zzz}}.must_be_nil
      index(:title).must_be_nil
      index([:title, :body], :unique => true).must_be_nil
      foreign_key(:node_id, :nodes).must_be_nil
      foreign_key(:deferrable_node_id, :nodes, :deferrable => true).must_be_nil
      primary_key([:title, :parent_id], :name => :cpk).must_be_nil
      foreign_key([:node_id, :prop_id], :nodes_props, :name => :cfk).must_be_nil
    end
    @columns, @indexes, @constraints = @generator.columns, @generator.indexes, @generator.constraints
  end
  
  it "should respond to everything" do
    @generator.respond_to?(:foo).must_equal true
  end

  it "should respond adding types" do
    c = Class.new(Sequel::Schema::CreateTableGenerator)
    c2 = Class.new
    def c2.to_s; 'Foo' end
    c.add_type_method(c2)
    gen = c.new(Sequel.mock) do
      Foo :bar
    end

    gen.columns.first.values_at(:name, :type).must_equal [:bar, c2]
  end

  it "should primary key column first" do
    @columns.first[:name].must_equal :id
    @columns.first[:primary_key].must_equal true
    @columns[3][:name].must_equal :parent_id
    @columns[3][:primary_key].must_be_nil
  end
  
  it "should respect existing column order if primary_key :keep_order is used" do
    generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
      string :title
      primary_key :id, :keep_order=>true
    end

    columns = generator.columns
    columns.last[:name].must_equal :id
    columns.last[:primary_key].must_equal true
    columns.first[:name].must_equal :title
    columns.first[:primary_key].must_be_nil
  end
  
  it "should handle SQL::Identifier and SQL::QualifiedIdentifier as foreign_key arguments" do
    generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
      foreign_key :a_id, Sequel.identifier(:as)
      foreign_key :b_id, Sequel.qualify(:c, :b)
    end

    columns = generator.columns
    columns.first.values_at(:name, :table).must_equal [:a_id, Sequel.identifier(:as)]
    columns.last.values_at(:name, :table).must_equal [:b_id, Sequel.qualify(:c, :b)]
  end
  
  it "counts definitions correctly" do
    @columns.size.must_equal 6
    @indexes.size.must_equal 2
    @constraints.size.must_equal 4
  end
  
  it "retrieves primary key name" do
    @generator.primary_key_name.must_equal :id
  end

  it "keeps columns in order" do
    @columns[1][:name].must_equal :title
    @columns[1][:type].must_equal :string
    @columns[2][:name].must_equal :body
    @columns[2][:type].must_equal :text
  end
  
  it "creates foreign key column" do
    @columns[3][:name].must_equal :parent_id
    @columns[3][:type].must_equal Integer
    @columns[4][:name].must_equal :node_id
    @columns[4][:type].must_equal Integer
  end

  it "creates deferrable altered foreign key column" do
    @columns[5][:name].must_equal :deferrable_node_id
    @columns[5][:type].must_equal Integer
    @columns[5][:deferrable].must_equal true
  end
  
  it "uses table for foreign key columns, if specified" do
    @columns[3][:table].must_be_nil
    @columns[4][:table].must_equal :nodes
    @constraints[3][:table].must_equal :nodes_props
  end
  
  it "finds columns" do
    [:title, :body, :parent_id, :id].each do |col|
      @generator.has_column?(col).must_equal true
    end
    @generator.has_column?(:foo).wont_equal true
  end
  
  it "creates constraints" do
    @constraints[0][:name].must_be_nil
    @constraints[0][:type].must_equal :check
    @constraints[0][:check].must_equal ['price > 100']

    @constraints[1][:name].must_equal :xxx
    @constraints[1][:type].must_equal :check
    @constraints[1][:check].must_be_kind_of Proc

    @constraints[2][:name].must_equal :cpk
    @constraints[2][:type].must_equal :primary_key
    @constraints[2][:columns].must_equal [ :title, :parent_id ]

    @constraints[3][:name].must_equal :cfk
    @constraints[3][:type].must_equal :foreign_key
    @constraints[3][:columns].must_equal [ :node_id, :prop_id ]
    @constraints[3][:table].must_equal :nodes_props
  end
  
  it "creates indexes" do
    @indexes[0][:columns].must_equal [:title]
    @indexes[1][:columns].must_equal [:title, :body]
  end
end

describe Sequel::Schema::AlterTableGenerator do
  before do
    @generator = Sequel::Schema::AlterTableGenerator.new(Sequel.mock) do
      add_column(:aaa, :text).must_be_nil
      drop_column(:bbb).must_be_nil
      rename_column(:ccc, :ho).must_be_nil
      set_column_type(:ddd, :float).must_be_nil
      set_column_default(:eee, 1).must_be_nil
      add_index([:fff, :ggg]).must_be_nil
      drop_index(:hhh).must_be_nil
      drop_index(:hhh, :name=>:blah_blah).must_be_nil
      add_full_text_index(:blah).must_be_nil
      add_spatial_index(:geom).must_be_nil
      add_index(:blah, :type => :hash).must_be_nil
      add_index(:blah, :where => {:something => true}).must_be_nil
      add_constraint(:con1, 'fred > 100').must_be_nil
      drop_constraint(:con2).must_be_nil
      add_unique_constraint([:aaa, :bbb, :ccc], :name => :con3).must_be_nil
      add_primary_key(:id).must_be_nil
      add_foreign_key(:node_id, :nodes).must_be_nil
      add_primary_key([:aaa, :bbb]).must_be_nil
      add_foreign_key([:node_id, :prop_id], :nodes_props).must_be_nil
      add_foreign_key([:node_id, :prop_id], :nodes_props, :name => :fkey).must_be_nil
      drop_foreign_key(:node_id).must_be_nil
      drop_foreign_key([:node_id, :prop_id]).must_be_nil
      drop_foreign_key([:node_id, :prop_id], :name => :fkey).must_be_nil
      add_column(:iii, :text, :index=>true).must_be_nil
      add_column(:jjj, :text, :index=>{:name=>:jjj_index}).must_be_nil
    end
  end
  
  it "should generate operation records" do
    @generator.operations.must_equal [
      {:op => :add_column, :name => :aaa, :type => :text},
      {:op => :drop_column, :name => :bbb},
      {:op => :rename_column, :name => :ccc, :new_name => :ho},
      {:op => :set_column_type, :name => :ddd, :type => :float},
      {:op => :set_column_default, :name => :eee, :default => 1},
      {:op => :add_index, :columns => [:fff, :ggg]},
      {:op => :drop_index, :columns => [:hhh]},
      {:op => :drop_index, :columns => [:hhh], :name=>:blah_blah},
      {:op => :add_index, :columns => [:blah], :type => :full_text},
      {:op => :add_index, :columns => [:geom], :type => :spatial},
      {:op => :add_index, :columns => [:blah], :type => :hash},
      {:op => :add_index, :columns => [:blah], :where => {:something => true}},
      {:op => :add_constraint, :type => :check, :name => :con1, :check => ['fred > 100']},
      {:op => :drop_constraint, :name => :con2},
      {:op => :add_constraint, :type => :unique, :name => :con3, :columns => [:aaa, :bbb, :ccc]},
      {:op => :add_column, :name => :id, :type => Integer, :primary_key=>true, :auto_increment=>true},
      {:op => :add_column, :name => :node_id, :type => Integer, :table=>:nodes},
      {:op => :add_constraint, :type => :primary_key, :columns => [:aaa, :bbb]},
      {:op => :add_constraint, :type => :foreign_key, :columns => [:node_id, :prop_id], :table => :nodes_props},
      {:op => :add_constraint, :type => :foreign_key, :columns => [:node_id, :prop_id], :table => :nodes_props, :name => :fkey},
      {:op => :drop_constraint, :type => :foreign_key, :columns => [:node_id]},
      {:op => :drop_column, :name => :node_id},
      {:op => :drop_constraint, :type => :foreign_key, :columns => [:node_id, :prop_id]},
      {:op => :drop_constraint, :type => :foreign_key, :columns => [:node_id, :prop_id], :name => :fkey},
      {:op => :add_column, :name => :iii, :type => :text},
      {:op => :add_index, :columns => [:iii]},
      {:op => :add_column, :name => :jjj, :type => :text},
      {:op => :add_index, :columns => [:jjj], :name => :jjj_index},
    ]
  end
end

describe "Sequel::Schema::CreateTableGenerator generic type methods" do
  it "should store the type class in :type for each column" do
    Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
      String :a
      Integer :b
      Fixnum :c
      Bignum :d
      Float :e
      BigDecimal :f
      Date :g
      DateTime :h
      Time :i
      Numeric :j
      File :k
      TrueClass :l
      FalseClass :m
    end.columns.map{|c| c[:type]}.must_equal [String, Integer, Integer, :Bignum, Float, BigDecimal, Date, DateTime, Time, Numeric, File, TrueClass, FalseClass]
  end
end

describe Sequel::Schema::CreateTableGenerator do
  before do
    @generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock)
  end

  it "should support usage without a block" do
    @generator.columns.must_be_empty
    @generator.indexes.must_be_empty
    @generator.constraints.must_be_empty

    @generator.column :a, String
    @generator.columns.wont_be_empty
  end

  it "should not handle method calls without name" do
    proc{@generator.foo123}.must_raise NoMethodError
  end

  it "should return name of the primary key" do
    @generator.primary_key_name.must_be_nil
    @generator.primary_key :id
    @generator.primary_key_name.must_equal :id
  end
end

describe Sequel::Schema::AlterTableGenerator do
  before do
    @generator = Sequel::Schema::AlterTableGenerator.new(Sequel.mock)
  end

  it "should support usage without a block" do
    @generator.operations.must_be_empty
    @generator.add_column :a, String
    @generator.operations.wont_be_empty
  end
end