miguel 0.1.0.pre4 → 0.1.0.pre5

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.
@@ -0,0 +1,18 @@
1
+ # Migration test.
2
+
3
+ Miguel::Schema.define do
4
+
5
+ table :a do
6
+ Integer :a
7
+ end
8
+
9
+ table :b do
10
+ primary_key :id
11
+ String :t
12
+ Unsigned? :u
13
+ Signed :s
14
+ end
15
+
16
+ end
17
+
18
+ # EOF #
@@ -0,0 +1,17 @@
1
+ Sequel.migration do
2
+ up do
3
+ create_table :a do
4
+ Integer :a, :null => false
5
+ end
6
+ create_table :b do
7
+ primary_key :id, :null => false, :unsigned => false
8
+ String :t, :null => false
9
+ integer :u, :null => true, :unsigned => true
10
+ integer :s, :null => false, :unsigned => false
11
+ end
12
+ end
13
+ down do
14
+ drop_table :a
15
+ drop_table :b
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ # Migration test.
2
+
3
+ Miguel::Schema.define do
4
+
5
+ table :a do
6
+ primary_key :id
7
+ Float :a
8
+ foreign_key :fk, :c
9
+ end
10
+
11
+ table :b do
12
+ primary_key :id
13
+ Text :t
14
+ Unsigned :u, default: 123
15
+ Signed? :s
16
+ timestamps
17
+ foreign_key :fk, :a
18
+ unique :u
19
+ end
20
+
21
+ table :c do
22
+ primary_key :id
23
+ String? :s
24
+ end
25
+
26
+ table :d do
27
+ Integer :a
28
+ Integer :b
29
+ end
30
+
31
+ end
32
+
33
+ # EOF #
@@ -0,0 +1,60 @@
1
+ Sequel.migration do
2
+ up do
3
+ alter_table :a do
4
+ set_column_type :a, Float, :null => false
5
+ add_primary_key :id, :null => false, :unsigned => false
6
+ add_column :fk, :integer, :default => 0, :null => false, :key => [:id], :unsigned => false
7
+ end
8
+ alter_table :b do
9
+ set_column_type :t, String, :null => false, :text => true
10
+ set_column_default :u, 123
11
+ set_column_not_null :u
12
+ set_column_allow_null :s
13
+ set_column_default :s, nil
14
+ add_column :create_time, :timestamp, :default => "2000-01-01 00:00:00", :null => false
15
+ add_column :update_time, :timestamp, :default => "2000-01-01 00:00:00", :null => false
16
+ add_column :fk, :integer, :default => 0, :null => false, :key => [:id], :unsigned => false
17
+ add_index [:u], :unique => true
18
+ end
19
+ create_table :c do
20
+ primary_key :id, :null => false, :unsigned => false
21
+ String :s, :null => true
22
+ end
23
+ create_table :d do
24
+ Integer :a, :null => false
25
+ Integer :b, :null => false
26
+ end
27
+ alter_table :a do
28
+ add_foreign_key [:fk], :c, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
29
+ end
30
+ alter_table :b do
31
+ add_foreign_key [:fk], :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
32
+ end
33
+ end
34
+ down do
35
+ alter_table :a do
36
+ drop_foreign_key [:fk] # :c, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
37
+ end
38
+ alter_table :b do
39
+ drop_foreign_key [:fk] # :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
40
+ end
41
+ drop_table :c
42
+ drop_table :d
43
+ alter_table :a do
44
+ drop_column :id # :primary_key, :null => false, :unsigned => false
45
+ drop_column :fk # :integer, :null => false, :key => [:id], :unsigned => false
46
+ set_column_type :a, Integer, :null => false
47
+ end
48
+ alter_table :b do
49
+ drop_index [:u] # :unique => true
50
+ drop_column :create_time # :timestamp, :null => false, :default => "2000-01-01 00:00:00"
51
+ drop_column :update_time # :timestamp, :null => false, :default => "2000-01-01 00:00:00"
52
+ drop_column :fk # :integer, :null => false, :key => [:id], :unsigned => false
53
+ set_column_type :t, String, :null => false
54
+ set_column_allow_null :u
55
+ set_column_default :u, nil
56
+ set_column_default :s, 0
57
+ set_column_not_null :s
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,38 @@
1
+ # Migration test.
2
+
3
+ Miguel::Schema.define do
4
+
5
+ table :a do
6
+ primary_key :id
7
+ Float :a
8
+ foreign_key :fk, :c
9
+ end
10
+
11
+ table :b do
12
+ primary_key :id
13
+ Text :t
14
+ Unsigned :u, default: 123
15
+ Signed? :s
16
+ timestamps
17
+ foreign_key :fk, :c
18
+ unique :u
19
+ index :create_time
20
+ end
21
+
22
+ table :c do
23
+ primary_key :id
24
+ String? :s
25
+ Text :t
26
+ end
27
+
28
+ table :d do
29
+ Integer :a
30
+ Integer :b
31
+ primary_key [:a,:b]
32
+ end
33
+
34
+ join_table :left_id, :a, :right_id, :b
35
+
36
+ end
37
+
38
+ # EOF #
@@ -0,0 +1,51 @@
1
+ Sequel.migration do
2
+ up do
3
+ alter_table :b do
4
+ drop_foreign_key [:fk] # :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
5
+ end
6
+ alter_table :b do
7
+ add_index [:create_time], :unique => false
8
+ end
9
+ alter_table :c do
10
+ add_column :t, String, :default => "", :null => false, :text => true
11
+ end
12
+ alter_table :d do
13
+ add_primary_key [:a, :b], :null => false, :unsigned => false
14
+ end
15
+ create_table :a_b do
16
+ integer :left_id, :null => false, :key => [:id], :unsigned => false
17
+ integer :right_id, :null => false, :key => [:id], :unsigned => false
18
+ primary_key [:left_id, :right_id], :null => false, :unsigned => false
19
+ index [:right_id, :left_id], :null => false, :unique => true
20
+ end
21
+ alter_table :b do
22
+ add_foreign_key [:fk], :c, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
23
+ end
24
+ alter_table :a_b do
25
+ add_foreign_key [:left_id], :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
26
+ add_foreign_key [:right_id], :b, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
27
+ end
28
+ end
29
+ down do
30
+ alter_table :b do
31
+ drop_foreign_key [:fk] # :c, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
32
+ end
33
+ alter_table :a_b do
34
+ drop_foreign_key [:left_id] # :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
35
+ drop_foreign_key [:right_id] # :b, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
36
+ end
37
+ drop_table :a_b
38
+ alter_table :b do
39
+ drop_index [:create_time] # :unique => false
40
+ end
41
+ alter_table :c do
42
+ drop_column :t # String, :null => false, :text => true
43
+ end
44
+ alter_table :d do
45
+ drop_constraint [:a, :b], :type => :primary_key # :null => false, :unsigned => false
46
+ end
47
+ alter_table :b do
48
+ add_foreign_key [:fk], :a, :on_update => :no_action, :on_delete => :no_action, :key => [:id]
49
+ end
50
+ end
51
+ end
data/test/data/simple.txt CHANGED
@@ -1,10 +1,10 @@
1
1
  table :items do
2
- primary_key :id, :null => false, :unsigned => false, :type => :integer
2
+ primary_key :id, :null => false, :unsigned => false
3
3
  String :name, :null => false
4
- integer :parent_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
5
- timestamp :create_time, :null => false, :default => "0000-00-00 00:00:00"
6
- timestamp :update_time, :null => false, :default => "0000-00-00 00:00:00"
4
+ integer :parent_id, :null => false, :key => [:id], :unsigned => false
5
+ timestamp :create_time, :null => false, :default => "2000-01-01 00:00:00"
6
+ timestamp :update_time, :null => false, :default => "2000-01-01 00:00:00"
7
7
  index [:name], :null => false, :unique => true
8
8
  index [:parent_id], :null => false
9
- foreign_key [:parent_id], :items, :null => false, :key => [:id], :unsigned => false, :type => :integer
9
+ foreign_key [:parent_id], :items, :null => false, :key => [:id], :unsigned => false
10
10
  end
data/test/helper.rb CHANGED
@@ -8,4 +8,28 @@ begin
8
8
  rescue LoadError
9
9
  end
10
10
 
11
+ # Setup helpers.
12
+
13
+ DATA_DIR = File.expand_path( "#{__FILE__}/../data" )
14
+
15
+ SEQ_COUNT = Dir[ "#{DATA_DIR}/seq_*.rb" ].count
16
+
17
+ class Bacon::Context
18
+
19
+ def data( name )
20
+ "#{DATA_DIR}/#{name}"
21
+ end
22
+
23
+ def lines( s )
24
+ s.to_s.lines.map.with_index{ |l, i| "#{i}:#{l.strip}" }
25
+ end
26
+
27
+ def match( a, b )
28
+ for a, b in lines( a ).zip( lines( b ) )
29
+ a.should == b
30
+ end
31
+ end
32
+
33
+ end
34
+
11
35
  # EOF #
@@ -0,0 +1,66 @@
1
+ # Test Importer.
2
+
3
+ require_relative 'helper'
4
+ require 'miguel/importer'
5
+ require 'miguel/migrator'
6
+
7
+ require 'yaml'
8
+
9
+ describe Miguel::Importer do
10
+
11
+ def database_options( db )
12
+ case db.database_type
13
+ when :mysql
14
+ [
15
+ {},
16
+ { unsigned_keys: true },
17
+ { mysql_timestamps: true },
18
+ ]
19
+ when :postgres
20
+ [ signed_unsigned: true ]
21
+ else
22
+ [ {} ]
23
+ end
24
+ end
25
+
26
+ def load( name, opts = {} )
27
+ Miguel::Schema.load( data( name ), opts )
28
+ end
29
+
30
+ def get_changes( db, schema )
31
+ importer = Miguel::Importer.new( db )
32
+ Miguel::Migrator.new.changes( importer.schema, schema ).to_s
33
+ end
34
+
35
+ def apply_schema( db, schema )
36
+ changes = get_changes( db, schema )
37
+ db.instance_eval( changes )
38
+ end
39
+
40
+ def databases
41
+ YAML.load_file( data( 'db.yml' ) ).map do |env, config|
42
+ Sequel.connect( config )
43
+ end
44
+ end
45
+
46
+ should 'correctly import schema from each supported database' do
47
+ empty = Miguel::Schema.new
48
+ for db in databases
49
+ for opts in database_options( db )
50
+ schema = load( 'schema.rb', opts )
51
+ apply_schema( db, empty )
52
+ get_changes( db, empty ).should.be.empty
53
+ get_changes( db, schema ).should.not.be.empty
54
+ apply_schema( db, schema )
55
+ get_changes( db, schema ).should.be.empty
56
+ get_changes( db, empty ).should.not.be.empty
57
+ apply_schema( db, empty )
58
+ get_changes( db, empty ).should.be.empty
59
+ get_changes( db, schema ).should.not.be.empty
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ # EOF #
@@ -0,0 +1,53 @@
1
+ # Test Migrator.
2
+
3
+ require_relative 'helper'
4
+ require 'miguel/migrator'
5
+
6
+ describe Miguel::Migrator do
7
+
8
+ def load( name )
9
+ Miguel::Schema.load( data( name ) )
10
+ end
11
+
12
+ def match_file( data, name )
13
+ match( data, File.read( data( name ) ) )
14
+ end
15
+
16
+ should 'create changes needed to create schema' do
17
+ schema = load( 'schema.rb' )
18
+ changes = Miguel::Migrator.new.changes( Miguel::Schema.new, schema )
19
+ match_file( changes, 'schema_bare.txt' )
20
+ end
21
+
22
+ should 'create changes needed to destroy schema' do
23
+ schema = load( 'schema.rb' )
24
+ changes = Miguel::Migrator.new.changes( schema, Miguel::Schema.new )
25
+ match_file( changes, 'schema_down.txt' )
26
+ end
27
+
28
+ should 'create Sequel change migration' do
29
+ schema = load( 'schema.rb' )
30
+ migration = Miguel::Migrator.new.change_migration( Miguel::Schema.new, schema )
31
+ match_file( migration, 'schema_change.txt' )
32
+ end
33
+
34
+ should 'create Sequel up/down migration' do
35
+ schema = load( 'schema.rb' )
36
+ migration = Miguel::Migrator.new.full_migration( Miguel::Schema.new, schema )
37
+ match_file( migration, 'schema_full.txt' )
38
+ end
39
+
40
+ should 'create migrations to migrate from one schema to another' do
41
+ m = Miguel::Migrator.new
42
+ schema = Miguel::Schema.new
43
+ SEQ_COUNT.times do |i|
44
+ new_schema = load( "seq_#{i}.rb" )
45
+ migration = m.full_migration( schema, new_schema )
46
+ match_file( migration, "seq_#{i}.txt" )
47
+ schema = new_schema
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ # EOF #
data/test/test_schema.rb CHANGED
@@ -5,24 +5,31 @@ require 'miguel/schema'
5
5
 
6
6
  describe Miguel::Schema do
7
7
 
8
- DATA_DIR = File.expand_path( "#{__FILE__}/../data" )
8
+ after do
9
+ Miguel::Schema.default_options = nil
10
+ end
11
+
12
+ def match_file( schema, name )
13
+ match( schema.dump, File.read( data( name ) ) )
14
+ end
9
15
 
10
- def data( name )
11
- "#{DATA_DIR}/#{name}"
16
+ def match_schema( text, opts = {}, &block )
17
+ schema = Miguel::Schema.new( opts ).define( &block )
18
+ match( schema.dump, text )
12
19
  end
13
20
 
14
21
  should 'load and dump schema properly' do
15
22
  schema = Miguel::Schema.load( data( 'schema.rb' ) )
16
- schema.dump.to_s.should == File.read( data( 'schema.txt' ) )
23
+ match_file( schema, 'schema.txt' )
17
24
  end
18
25
 
19
26
  should 'allow changing default schema options temporarily' do
20
27
  schema = Miguel::Schema.load( data( 'simple.rb' ), unsigned_keys: true, mysql_timestamps: true )
21
- schema.dump.to_s.should == File.read( data( 'simple_mysql.txt' ) )
28
+ match_file( schema, 'simple_mysql.txt' )
22
29
  Miguel::Schema.new.opts.should.be.empty
23
30
 
24
31
  schema = Miguel::Schema.load( data( 'simple.rb' ) )
25
- schema.dump.to_s.should == File.read( data( 'simple.txt' ) )
32
+ match_file( schema, 'simple.txt' )
26
33
  end
27
34
 
28
35
  should 'allow changing default schema options permanently' do
@@ -33,14 +40,472 @@ describe Miguel::Schema do
33
40
  Miguel::Schema.default_options.should == { unsigned_keys: true, mysql_timestamps: true }
34
41
 
35
42
  schema = Miguel::Schema.load( data( 'simple.rb' ) )
36
- schema.dump.to_s.should == File.read( data( 'simple_mysql.txt' ) )
43
+ match_file( schema, 'simple_mysql.txt' )
37
44
 
38
45
  Miguel::Schema.default_options = nil
39
46
  Miguel::Schema.default_options.should == {}
40
47
  Miguel::Schema.new.opts.should.be.empty
41
48
 
42
49
  schema = Miguel::Schema.load( data( 'simple.rb' ) )
43
- schema.dump.to_s.should == File.read( data( 'simple.txt' ) )
50
+ match_file( schema, 'simple.txt' )
51
+ end
52
+
53
+ should 'support plain sequel types' do
54
+ match_schema <<-EOT, use_defaults: false do
55
+ table :sequel_types do
56
+ Integer :a0
57
+ String :a1
58
+ String :a2, :size => 50
59
+ String :a3, :fixed => true
60
+ String :a4, :fixed => true, :size => 50
61
+ String :a5, :text => true
62
+ File :b
63
+ Fixnum :c
64
+ Bignum :d
65
+ Float :e
66
+ BigDecimal :f
67
+ BigDecimal :f2, :size => 10
68
+ BigDecimal :f3, :size => [10, 2]
69
+ Date :g
70
+ DateTime :h
71
+ Time :i
72
+ Time :i2, :only_time => true
73
+ Numeric :j
74
+ TrueClass :k
75
+ FalseClass :l
76
+ end
77
+ EOT
78
+ table :sequel_types do
79
+ Integer :a0 # integer
80
+ String :a1 # varchar(255)
81
+ String :a2, :size=>50 # varchar(50)
82
+ String :a3, :fixed=>true # char(255)
83
+ String :a4, :fixed=>true, :size=>50 # char(50)
84
+ String :a5, :text=>true # text
85
+ File :b # blob
86
+ Fixnum :c # integer
87
+ Bignum :d # bigint
88
+ Float :e # double precision
89
+ BigDecimal :f # numeric
90
+ BigDecimal :f2, :size=>10 # numeric(10)
91
+ BigDecimal :f3, :size=>[10, 2] # numeric(10, 2)
92
+ Date :g # date
93
+ DateTime :h # timestamp or datetime
94
+ Time :i # timestamp or datetime
95
+ Time :i2, :only_time=>true # time
96
+ Numeric :j # numeric
97
+ TrueClass :k # boolean
98
+ FalseClass :l # boolean
99
+ end
100
+ end
101
+ end
102
+
103
+ should 'support default miguel types' do
104
+ match_schema <<-EOT do
105
+ table :miguel_types do
106
+ integer :key, :null => false, :unsigned => false
107
+ String :string, :null => false
108
+ String :text, :null => false, :text => true
109
+ File :blob, :null => false
110
+ Integer :int, :null => false
111
+ integer :signed, :null => false, :unsigned => false
112
+ integer :unsigned, :null => false, :unsigned => true
113
+ Float :float, :null => false
114
+ TrueClass :bool, :null => false
115
+ TrueClass :true, :null => false, :default => true
116
+ TrueClass :false, :null => false, :default => false
117
+ timestamp :time, :null => false, :default => "2000-01-01 00:00:00"
118
+ end
119
+ EOT
120
+ table :miguel_types do
121
+ Key :key
122
+ String :string
123
+ Text :text
124
+ File :blob
125
+ Integer :int
126
+ Signed :signed
127
+ Unsigned :unsigned
128
+ Float :float
129
+ Bool :bool
130
+ True :true
131
+ False :false
132
+ Time :time
133
+ end
134
+ end
135
+ end
136
+
137
+ should 'support custom types' do
138
+ match_schema <<-EOT do
139
+ table :custom_types do
140
+ String :custom, :null => false, :fixed => true, :size => 3
141
+ datetime :time, :null => false
142
+ datetime :time2, :null => true, :default => nil
143
+ end
144
+ EOT
145
+ set_defaults :Custom, :String, fixed: true, size: 3
146
+ set_defaults :Time, :datetime
147
+ set_defaults :Time?, :datetime, default: nil
148
+ table :custom_types do
149
+ Custom :custom
150
+ Time :time
151
+ Time? :time2
152
+ end
153
+ end
154
+ end
155
+
156
+ should 'support native types' do
157
+ match_schema <<-EOT do
158
+ table :native_types do
159
+ date :date, :null => false, :default => "2000-12-31"
160
+ time :time, :null => false, :default => "23:59:59"
161
+ datetime :datetime, :null => false, :default => "2037-12-31 23:59:59"
162
+ timestamp :timestamp, :null => false, :default => "1970-01-02 00:00:00"
163
+ end
164
+ EOT
165
+ table :native_types do
166
+ date :date, default: '2000-12-31'
167
+ time :time, default: '23:59:59'
168
+ datetime :datetime, default: '2037-12-31 23:59:59'
169
+ timestamp :timestamp, default: '1970-01-02 00:00:00'
170
+ end
171
+ end
172
+ end
173
+
174
+ should 'support enums' do
175
+ match_schema <<-EOT do
176
+ table :enum do
177
+ enum :error, :null => false, :elements => ["none", "invalid", "expired", "declined", "other"], :default => "none"
178
+ end
179
+ EOT
180
+ table :enum do
181
+ enum :error, elements: %w[ none invalid expired declined other ], default: 'none'
182
+ end
183
+ end
184
+ end
185
+
186
+ should 'support sets' do
187
+ match_schema <<-EOT do
188
+ table :set do
189
+ set :permissions, :null => false, :elements => ["read", "write", "create", "delete"], :default => "read"
190
+ end
191
+ EOT
192
+ table :set do
193
+ set :permissions, elements: %w[ read write create delete ], default: 'read'
194
+ end
195
+ end
196
+ end
197
+
198
+ should 'support generic timestamps' do
199
+ match_schema <<-EOT do
200
+ table :timestamps do
201
+ timestamp :t1, :null => false, :default => "2000-01-01 00:00:00"
202
+ timestamp :t2, :null => true, :default => nil
203
+ timestamp :create_time, :null => false, :default => "2000-01-01 00:00:00"
204
+ timestamp :update_time, :null => false, :default => "2000-01-01 00:00:00"
205
+ end
206
+ EOT
207
+ table :timestamps do
208
+ Time :t1
209
+ Time? :t2
210
+ timestamps
211
+ end
212
+ end
213
+ end
214
+
215
+ should 'support MySQL timestamps' do
216
+ match_schema <<-EOT, mysql_timestamps: true do
217
+ table :timestamps do
218
+ timestamp :t1, :null => false, :default => "0000-00-00 00:00:00"
219
+ timestamp :t2, :null => true, :default => nil
220
+ timestamp :create_time, :null => false, :default => "0000-00-00 00:00:00"
221
+ timestamp :update_time, :null => false, :default => Sequel.lit("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
222
+ end
223
+ EOT
224
+ table :timestamps do
225
+ Time :t1
226
+ Time? :t2
227
+ timestamps
228
+ end
229
+ end
230
+ end
231
+
232
+ should 'support auto-incrementing primary keys' do
233
+ match_schema <<-EOT do
234
+ table :pk do
235
+ primary_key :id, :null => false, :unsigned => false
236
+ end
237
+ EOT
238
+ table :pk do
239
+ primary_key :id
240
+ end
241
+ end
242
+ end
243
+
244
+ should 'support non-incrementing primary keys' do
245
+ match_schema <<-EOT do
246
+ table :pk do
247
+ integer :id, :null => false, :unsigned => false, :primary_key => true
248
+ end
249
+ EOT
250
+ table :pk do
251
+ Key :id, primary_key: true
252
+ end
253
+ end
254
+ end
255
+
256
+ should 'support compound primary keys' do
257
+ match_schema <<-EOT do
258
+ table :pk do
259
+ Integer :a, :null => false
260
+ Integer :b, :null => false
261
+ primary_key [:a, :b], :null => false, :unsigned => false
262
+ end
263
+ EOT
264
+ table :pk do
265
+ Integer :a
266
+ Integer :b
267
+ primary_key [:a, :b]
268
+ end
269
+ end
270
+ end
271
+
272
+ should 'support foreign keys' do
273
+ match_schema <<-EOT do
274
+ table :fk do
275
+ integer :user_id, :null => false, :key => [:id], :unsigned => false
276
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false
277
+ end
278
+ EOT
279
+ table :fk do
280
+ foreign_key :user_id, :users
281
+ end
282
+ end
283
+ end
284
+
285
+ should 'support reused foreign keys' do
286
+ match_schema <<-EOT do
287
+ table :fk do
288
+ primary_key :user_id, :null => false, :unsigned => false
289
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false
290
+ end
291
+ EOT
292
+ table :fk do
293
+ primary_key :user_id
294
+ foreign_key [:user_id], :users
295
+ end
296
+ end
297
+ end
298
+
299
+ should 'support compound foreign keys' do
300
+ match_schema <<-EOT do
301
+ table :fk do
302
+ Integer :x, :null => false
303
+ Integer :y, :null => false
304
+ foreign_key [:x, :y], :pk, :null => false, :key => [:a, :b], :unsigned => false
305
+ end
306
+ EOT
307
+ table :fk do
308
+ Integer :x
309
+ Integer :y
310
+ foreign_key [:x, :y], :pk, key: [:a, :b]
311
+ end
312
+ end
313
+ end
314
+
315
+ should 'support unsigned keys' do
316
+ match_schema <<-EOT, unsigned_keys: true do
317
+ table :pk do
318
+ primary_key :id, :null => false, :unsigned => true, :type => :integer
319
+ end
320
+ table :pk2 do
321
+ integer :id, :null => false, :unsigned => true, :primary_key => true
322
+ end
323
+ table :pk3 do
324
+ Integer :a, :null => false
325
+ Integer :b, :null => false
326
+ primary_key [:a, :b], :null => false, :unsigned => true
327
+ end
328
+ table :fk do
329
+ integer :user_id, :null => false, :key => [:id], :unsigned => true, :type => :integer
330
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => true, :type => :integer
331
+ end
332
+ table :fk2 do
333
+ primary_key :user_id, :null => false, :unsigned => true, :type => :integer
334
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => true
335
+ end
336
+ table :fk3 do
337
+ Integer :x, :null => false
338
+ Integer :y, :null => false
339
+ foreign_key [:x, :y], :pk, :null => false, :key => [:a, :b], :unsigned => true
340
+ end
341
+ EOT
342
+ table :pk do
343
+ primary_key :id
344
+ end
345
+ table :pk2 do
346
+ Key :id, primary_key: true
347
+ end
348
+ table :pk3 do
349
+ Integer :a
350
+ Integer :b
351
+ primary_key [:a, :b]
352
+ end
353
+ table :fk do
354
+ foreign_key :user_id, :users
355
+ end
356
+ table :fk2 do
357
+ primary_key :user_id
358
+ foreign_key [:user_id], :users
359
+ end
360
+ table :fk3 do
361
+ Integer :x
362
+ Integer :y
363
+ foreign_key [:x, :y], :pk, key: [:a, :b]
364
+ end
365
+ end
366
+ end
367
+
368
+ should 'support indexes' do
369
+ match_schema <<-EOT do
370
+ table :index do
371
+ Integer :a, :null => false
372
+ Integer :b, :null => false
373
+ String :s, :null => false
374
+ index [:a], :null => false
375
+ index [:b], :null => false, :unique => true
376
+ index [:a, :b], :null => false
377
+ index [:a, :b, :c], :null => false, :unique => true
378
+ end
379
+ EOT
380
+ table :index do
381
+ Integer :a
382
+ Integer :b
383
+ String :s
384
+ index :a
385
+ unique :b
386
+ index [:a, :b]
387
+ unique [:a, :b, :c]
388
+ end
389
+ end
390
+ end
391
+
392
+ should 'support null columns' do
393
+ match_schema <<-EOT do
394
+ table :null do
395
+ String :string, :null => true
396
+ String :text, :null => true, :text => true
397
+ File :blob, :null => true
398
+ Integer :int, :null => true
399
+ integer :signed, :null => true, :unsigned => false
400
+ integer :unsigned, :null => true, :unsigned => true
401
+ Float :float, :null => true
402
+ TrueClass :bool, :null => true
403
+ TrueClass :true, :null => true, :default => true
404
+ TrueClass :false, :null => true, :default => false
405
+ timestamp :time, :null => true, :default => nil
406
+ integer :user_id, :null => true, :key => [:id], :unsigned => false
407
+ foreign_key [:user_id], :users, :null => true, :key => [:id], :unsigned => false
408
+ end
409
+ EOT
410
+ table :null do
411
+ String? :string
412
+ Text? :text
413
+ File? :blob
414
+ Integer? :int
415
+ Signed? :signed
416
+ Unsigned? :unsigned
417
+ Float? :float
418
+ Bool? :bool
419
+ True? :true
420
+ False? :false
421
+ Time? :time
422
+ foreign_key? :user_id, :users
423
+ end
424
+ end
425
+ end
426
+
427
+ should 'support default values' do
428
+ match_schema <<-EOT do
429
+ table :defaults do
430
+ String :string, :null => false, :default => "abc"
431
+ Integer :int, :null => false, :default => 10
432
+ integer :signed, :null => false, :unsigned => false, :default => -1
433
+ integer :unsigned, :null => false, :unsigned => true, :default => 1000
434
+ Float :float, :null => false, :default => 3.14
435
+ TrueClass :bool, :null => false, :default => true
436
+ timestamp :time, :null => false, :default => "2037-12-31 23:59:59"
437
+ end
438
+ EOT
439
+ table :defaults do
440
+ String :string, default: 'abc'
441
+ Integer :int, default: 10
442
+ Signed :signed, default: -1
443
+ Unsigned :unsigned, default: 1000
444
+ Float :float, default: 3.14
445
+ Bool :bool, default: true
446
+ Time :time, default: '2037-12-31 23:59:59'
447
+ end
448
+ end
449
+ end
450
+
451
+ should 'support arbitrary types and options' do
452
+ match_schema <<-EOT do
453
+ table :whatever do
454
+ Foo :foo, :null => false, :abc => :xyz, :data => ["x", 2, 3.5, :bar], :opts => {:none => true}
455
+ end
456
+ EOT
457
+ table :whatever do
458
+ Foo :foo, abc: :xyz, data: ["x", 2, 3.5, :bar], opts: { none: true }
459
+ end
460
+ end
461
+ end
462
+
463
+ should 'create join tables' do
464
+ match_schema <<-EOT do
465
+ table :left_right do
466
+ integer :left_id, :null => false, :key => [:id], :unsigned => false
467
+ integer :right_id, :null => false, :key => [:id], :unsigned => false
468
+ primary_key [:left_id, :right_id], :null => false, :unsigned => false
469
+ index [:right_id, :left_id], :null => false, :unique => true
470
+ foreign_key [:left_id], :left, :null => false, :key => [:id], :unsigned => false
471
+ foreign_key [:right_id], :right, :null => false, :key => [:id], :unsigned => false
472
+ end
473
+ EOT
474
+ join_table :left_id, :left, :right_id, :right
475
+ end
476
+ end
477
+
478
+ should 'create join tables with custom name' do
479
+ match_schema <<-EOT do
480
+ table :custom_name do
481
+ integer :left_id, :null => false, :key => [:id], :unsigned => false
482
+ integer :right_id, :null => false, :key => [:id], :unsigned => false
483
+ primary_key [:left_id, :right_id], :null => false, :unsigned => false
484
+ index [:right_id, :left_id], :null => false, :unique => true
485
+ foreign_key [:left_id], :left, :null => false, :key => [:id], :unsigned => false
486
+ foreign_key [:right_id], :right, :null => false, :key => [:id], :unsigned => false
487
+ end
488
+ EOT
489
+ join_table :left_id, :left, :right_id, :right, :custom_name
490
+ end
491
+ end
492
+
493
+ should 'create join tables with additional columns' do
494
+ match_schema <<-EOT do
495
+ table :left_right do
496
+ integer :left_id, :null => false, :key => [:id], :unsigned => false
497
+ integer :right_id, :null => false, :key => [:id], :unsigned => false
498
+ primary_key [:left_id, :right_id], :null => false, :unsigned => false
499
+ String :name, :null => false
500
+ index [:right_id, :left_id], :null => false, :unique => true
501
+ foreign_key [:left_id], :left, :null => false, :key => [:id], :unsigned => false
502
+ foreign_key [:right_id], :right, :null => false, :key => [:id], :unsigned => false
503
+ end
504
+ EOT
505
+ join_table :left_id, :left, :right_id, :right do
506
+ String :name
507
+ end
508
+ end
44
509
  end
45
510
 
46
511
  end