miguel 0.1.0.pre4 → 0.1.0.pre5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dbf13dd299009fb0beefd95d64b4a1b3bfba5be5
4
- data.tar.gz: 0f4558c6faa5826150e998fb900706ea84bb65a1
3
+ metadata.gz: a0ecd54548a6934b77b3f075d8b1fc74db7c555b
4
+ data.tar.gz: 87c76a4d8e883f01be334d3d07fd3be0598d5097
5
5
  SHA512:
6
- metadata.gz: 30b5da0b99408f21db2c16658c1451f19c0e76dc3398c8edce4881d9339eb07a2ee113a4fcb8cd0aca1e16cd23d03432842169f780399c94580a0a92cf7ecee1
7
- data.tar.gz: c6bf941afb95fa42763aa62c0d49376aacca8b32fe6d044d753fffbad2184f7a811edafc107ae46eb7572f44ba2b677cf901e5635572e848db0650c3ba23a2e1
6
+ metadata.gz: 1d8c0640ab68fe0d19b45a4f6ab05b34acba429d21dd3de9d30341eb64aab8127e2535ce416eb29ecdfb741d8d1f07fe624ba249ba45fce35a1d1689faaf0ad5
7
+ data.tar.gz: e3598249193c4e2edd85800f9b48c584526ab56045516c3910969a82ccf8ae11e79ca7dc27675e734727907303bcdf09bf43b4fe95368cbb3c43db1f4c208dc9
data/.travis.yml CHANGED
@@ -20,5 +20,8 @@ matrix:
20
20
  - rvm: ruby-head
21
21
  - rvm: jruby-19mode
22
22
  - rvm: jruby-head
23
+ before_script:
24
+ - mysql -e 'create database miguel_test;'
25
+ - psql -c 'create database miguel_test;' -U postgres
23
26
 
24
27
  # EOF #
data/README.md CHANGED
@@ -102,7 +102,7 @@ end
102
102
  ```
103
103
 
104
104
  One enhancement is that it allows you to define `NULL` columns simply by adding `?` to the type name.
105
- Anything else is implicitly `NOT NULL`, which is a really wise default.
105
+ Anything else is implicitly `NOT NULL`, which is a really wise default for many reasons.
106
106
 
107
107
  Another enhancement is that it allows you to set defaults and
108
108
  define custom shortcuts for types which you use frequently.
@@ -118,24 +118,26 @@ set_defaults :False, :TrueClass, default: false
118
118
  set_defaults :Signed, :integer, unsigned: false
119
119
  set_defaults :Unsigned, :integer, unsigned: true
120
120
  set_defaults :Text, :String, text: true
121
- set_defaults :Time, :timestamp, default: '0000-00-00 00:00:00'
121
+ set_defaults :Time, :timestamp, default: '2000-01-01 00:00:00'
122
122
  set_defaults :Time?, :timestamp, default: nil
123
123
 
124
124
  set_defaults :unique, :index, unique: true
125
125
 
126
+ set_defaults :Key, :integer, unsigned: false
126
127
  set_defaults :primary_key, type: :integer, unsigned: false
127
128
  set_defaults :foreign_key, key: :id, type: :integer, unsigned: false
128
129
  ```
129
130
 
130
131
  If you prefer unsigned keys instead and your database engine supports it,
131
- you can pass the `unsigned_keys: true` option to `define` to make it happen.
132
+ you can pass the `unsigned_keys: true` option to `Schema.define` to make it happen.
132
133
  If you don't want any of these defaults set up for you,
133
- pass the `use_defaults: false` option to define instead.
134
+ pass the `use_defaults: false` option to `define` instead.
134
135
 
135
136
  Finally, the `timestamps` helper can be used to create the
136
137
  `create_time` and `update_time` timestamps for you.
137
138
  If you pass the `mysql_timestamps: true` option to `define`,
138
- the `update_time` timestamp will have the MySQL auto-update feature enabled.
139
+ the `update_time` timestamp will have the MySQL auto-update feature enabled,
140
+ and timestamps will use the `'0000-00-00 00:00:00'` default by default.
139
141
 
140
142
  ## Using the command
141
143
 
@@ -105,27 +105,24 @@ module Miguel
105
105
 
106
106
  # Convert given database default of given type to default used by our schema definitions.
107
107
  def revert_default( type, default, ruby_default )
108
- default = ruby_default unless ruby_default.nil?
109
- return if default.nil?
110
-
111
- case default
112
- when String, Numeric, TrueClass, FalseClass
113
- when DateTime
114
- default = default.strftime( '%F %T' )
115
- else
116
- default = default.to_s
117
- end
118
-
119
108
  if type.to_s =~ /date|time/
120
109
  case default
121
- when /\A'([-: \d]+)'\z/
122
- default = $1
123
110
  when 'CURRENT_TIMESTAMP'
124
111
  # This matches our use of MySQL timestamps in schema definitions.
125
- default = Sequel.lit('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')
112
+ return Sequel.lit('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')
126
113
  end
127
114
  end
128
- default
115
+
116
+ default = ruby_default unless ruby_default.nil?
117
+
118
+ case default
119
+ when nil, String, Numeric, TrueClass, FalseClass
120
+ return default
121
+ when DateTime
122
+ return default.strftime( '%F %T' )
123
+ else
124
+ return default.to_s
125
+ end
129
126
  end
130
127
 
131
128
  # Import indexes of given table.
@@ -156,46 +153,55 @@ module Miguel
156
153
  # These are usually just schema hints which the user normally doesn't specify.
157
154
  IGNORED_OPTS = [ :max_length ]
158
155
 
159
- # Import columns of given table.
160
- def import_columns( table )
161
- schema = db.schema( table.name )
156
+ # Import column type and options.
157
+ def import_column_type_and_options( opts )
158
+ opts = opts.dup
162
159
 
163
- # Get info about primary key columns.
160
+ # Discard anything we don't need.
164
161
 
165
- primary_key_columns = schema.select{ |name, opts| opts[ :primary_key ] }
162
+ opts.delete_if{ |key, value| IGNORED_OPTS.include? key }
166
163
 
167
- multi_primary_key = ( primary_key_columns.count > 1 )
164
+ # Import type.
168
165
 
169
- # Import each column in sequence.
166
+ type = opts.delete( :type )
167
+ db_type = opts.delete( :db_type )
170
168
 
171
- for name, opts in schema
169
+ type, type_opts = revert_type_literal( db_type, type )
170
+ opts.merge!( type_opts ) if type_opts
172
171
 
173
- opts = opts.dup
172
+ # Import NULL option.
174
173
 
175
- # Discard anything we don't need.
174
+ opts[ :null ] = opts.delete( :allow_null )
176
175
 
177
- opts.delete_if{ |key, value| IGNORED_OPTS.include? key }
176
+ # Import default value.
178
177
 
179
- # Import type.
178
+ default = opts.delete( :default )
179
+ ruby_default = opts.delete( :ruby_default )
180
+
181
+ default = revert_default( type, default, ruby_default )
182
+
183
+ opts[ :default ] = default unless default.nil?
184
+
185
+ [ type, opts ]
186
+ end
180
187
 
181
- type = opts.delete( :type )
182
- db_type = opts.delete( :db_type )
188
+ # Import columns of given table.
189
+ def import_columns( table )
190
+ schema = db.schema( table.name )
183
191
 
184
- type, type_opts = revert_type_literal( db_type, type )
185
- opts.merge!( type_opts ) if type_opts
192
+ # Get info about primary key columns.
186
193
 
187
- # Import NULL option.
194
+ primary_key_columns = schema.select{ |name, opts| opts[ :primary_key ] }
188
195
 
189
- opts[ :null ] = opts.delete( :allow_null )
196
+ multi_primary_key = ( primary_key_columns.count > 1 )
190
197
 
191
- # Import default value.
198
+ # Import each column in sequence.
192
199
 
193
- default = opts.delete( :default )
194
- ruby_default = opts.delete( :ruby_default )
200
+ for name, opts in schema
195
201
 
196
- default = revert_default( type, default, ruby_default )
202
+ # Import column type and options.
197
203
 
198
- opts[ :default ] = default unless default.nil?
204
+ type, opts = import_column_type_and_options( opts )
199
205
 
200
206
  # Deal with primary keys, which is a bit obscure because of the auto-increment handling.
201
207
 
@@ -111,7 +111,7 @@ module Miguel
111
111
  # Generate code for dropping given columns.
112
112
  def dump_drop_columns( out, columns )
113
113
  for column in columns
114
- if column.type == :primary_key
114
+ if column.primary_key_constraint?
115
115
  out << "drop_constraint #{column.out_name}, :type => :primary_key#{column.out_opts(' # ')}"
116
116
  else
117
117
  out << "drop_column #{column.out_name} # #{column.out_type}#{column.out_opts}"
@@ -125,7 +125,7 @@ module Miguel
125
125
  if column.type == :primary_key
126
126
  out << "add_primary_key #{column.out_name}#{column.out_opts}"
127
127
  else
128
- out << "add_column #{column.out_name}, #{column.out_type}#{column.out_opts}"
128
+ out << "add_column #{column.out_name}, #{column.out_type}#{column.out_default_opts}"
129
129
  end
130
130
  end
131
131
  end
data/lib/miguel/schema.rb CHANGED
@@ -9,9 +9,12 @@ module Miguel
9
9
  # Class for defining database schema.
10
10
  class Schema
11
11
 
12
- # String denoting zero time.
12
+ # String denoting zero time in MySQL.
13
13
  ZERO_TIME = '0000-00-00 00:00:00'.freeze
14
14
 
15
+ # String denoting default time.
16
+ DEFAULT_TIME = '2000-01-01 00:00:00'.freeze
17
+
15
18
  # Module for pretty printing of names, types, and especially options.
16
19
  module Output
17
20
 
@@ -45,6 +48,10 @@ module Miguel
45
48
  out_hash( canonic_opts, prefix )
46
49
  end
47
50
 
51
+ def out_default_opts( prefix = ', ' )
52
+ out_hash( default_opts, prefix )
53
+ end
54
+
48
55
  def out_name
49
56
  name.inspect
50
57
  end
@@ -81,6 +88,11 @@ module Miguel
81
88
  @opts = opts
82
89
  end
83
90
 
91
+ # Test if the column is in fact just a primary key constraint.
92
+ def primary_key_constraint?
93
+ type == :primary_key && name.is_a?( Array )
94
+ end
95
+
84
96
  # Get the column default.
85
97
  def default
86
98
  d = opts[ :default ]
@@ -159,7 +171,7 @@ module Miguel
159
171
 
160
172
  # Get the column options in a canonic way.
161
173
  def canonic_opts
162
- return {} if type == :primary_key && name.is_a?( Array )
174
+ return {} if primary_key_constraint?
163
175
  o = { :type => canonic_type, :default => default, :null => true }
164
176
  o.merge!( DEFAULT_OPTS[ canonic_type ] || {} )
165
177
  o.merge!( opts )
@@ -167,6 +179,11 @@ module Miguel
167
179
  o.delete_if{ |key, value| IGNORED_OPTS.include? key }
168
180
  end
169
181
 
182
+ # Get options with default value included.
183
+ def default_opts
184
+ { :default => default }.merge( opts )
185
+ end
186
+
170
187
  # Compare one column with another one.
171
188
  def == other
172
189
  other.is_a?( Column ) &&
@@ -240,7 +257,7 @@ module Miguel
240
257
 
241
258
  # Options we ignore when comparing.
242
259
  # These are usually tied to the underlying column, not constraint.
243
- IGNORED_OPTS = [ :null, :unsigned, :type ]
260
+ IGNORED_OPTS = [ :null, :unsigned, :type, :default ]
244
261
 
245
262
  # Get the foreign key options, in a canonic way.
246
263
  def canonic_opts
@@ -475,6 +492,7 @@ module Miguel
475
492
  # Also note that the defaults are applied in the instant the +table+ block is evaluated,
476
493
  # so it is eventually possible (though not necessarily recommended) to change them in between.
477
494
  def set_defaults( name, *args, &block )
495
+ clear_defaults( name )
478
496
  @aliases[ name ] = args.shift if args.first.is_a? Symbol
479
497
  @defaults[ name ] = args.pop if args.last.is_a? Hash
480
498
  @callbacks[ name ] = block
@@ -512,6 +530,7 @@ module Miguel
512
530
  #
513
531
  # :unique, :index, :unique => true
514
532
  #
533
+ # :Key, :integer, :unsigned => false
515
534
  # :primary_key, :type => :integer, :unsigned => false
516
535
  # :foreign_key, :key => :id, :type => :integer, :unsigned => false
517
536
  #
@@ -528,14 +547,17 @@ module Miguel
528
547
  # Unfortunately, :unsigned currently works only with :integer,
529
548
  # not the default :Integer, and :integer can't be specified for compound keys,
530
549
  # so we have to use the callback to set the type only at correct times.
550
+ # Furthermore, Postgres's autoincrementing serials only work with Integer,
551
+ # so we set the type only as long as the unsigned keys are not requested.
531
552
 
532
553
  unsigned_keys = !! opts[ :unsigned_keys ]
533
554
 
555
+ set_defaults :Key, :integer, :unsigned => unsigned_keys
534
556
  set_defaults :primary_key, :unsigned => unsigned_keys do |opts,args,table|
535
- opts[ :type ] ||= :integer unless args.first.is_a? Array
557
+ opts[ :type ] ||= :integer unless args.first.is_a? Array or not opts[ :unsigned ]
536
558
  end
537
559
  set_defaults :foreign_key, :key => :id, :unsigned => unsigned_keys do |opts,args,table|
538
- opts[ :type ] ||= :integer unless args.first.is_a? Array
560
+ opts[ :type ] ||= :integer unless args.first.is_a? Array or not opts[ :unsigned ]
539
561
  end
540
562
 
541
563
  # Save some typing for unique indexes.
@@ -557,7 +579,8 @@ module Miguel
557
579
  # we have to be careful to turn off the MySQL autoupdate behavior.
558
580
  # That's why we have to set defaults explicitly.
559
581
 
560
- set_defaults :Time, :timestamp, :default => ZERO_TIME
582
+ default_time = opts[ :mysql_timestamps ] ? ZERO_TIME : DEFAULT_TIME
583
+ set_defaults :Time, :timestamp, :default => default_time
561
584
  set_defaults :Time?, :timestamp, :default => nil
562
585
 
563
586
  self
data/miguel.gemspec CHANGED
@@ -4,7 +4,7 @@ require File.expand_path( '../lib/miguel/version', __FILE__ )
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'miguel'
7
- s.version = Miguel::VERSION + '.pre4'
7
+ s.version = Miguel::VERSION + '.pre5'
8
8
  s.summary = 'Database migrator and migration generator for Sequel.'
9
9
  s.description = <<EOT
10
10
  This gem makes it easy to create and maintain an up-to-date database schema
@@ -22,6 +22,9 @@ EOT
22
22
  s.required_ruby_version = '>= 1.9.3'
23
23
  s.add_runtime_dependency 'sequel', '~> 4.0'
24
24
  s.add_development_dependency 'bacon', '~> 1.2'
25
+ s.add_development_dependency 'sqlite3'
26
+ s.add_development_dependency 'mysql2'
27
+ s.add_development_dependency 'pg'
25
28
  end
26
29
 
27
30
  # EOF #
data/test/data/db.yml ADDED
@@ -0,0 +1,17 @@
1
+ # Database configuration.
2
+
3
+ development:
4
+ adapter: sqlite
5
+
6
+ mysql:
7
+ adapter: mysql2
8
+ user: travis
9
+ password: ''
10
+ host: localhost
11
+ database: miguel_test
12
+ encoding: utf8
13
+
14
+ postgres:
15
+ adapter: sqlite
16
+
17
+ # EOF #
data/test/data/schema.rb CHANGED
@@ -29,6 +29,7 @@ Miguel::Schema.define( use_defaults: false ) do
29
29
  set_defaults :Custom, :String, fixed: true, size: 3
30
30
 
31
31
  table :miguel_types do
32
+ Key :key
32
33
  String :string
33
34
  Text :text
34
35
  File :blob
@@ -74,8 +75,8 @@ Miguel::Schema.define( use_defaults: false ) do
74
75
  end
75
76
 
76
77
  table :compound do
77
- Unsigned :a
78
- Unsigned :b
78
+ Integer :a
79
+ Integer :b
79
80
  primary_key [:a, :b]
80
81
  foreign_key [:b, :a], :compound, key: [:a, :b]
81
82
  String :c
data/test/data/schema.txt CHANGED
@@ -19,6 +19,7 @@ table :sequel_types do
19
19
  FalseClass :l
20
20
  end
21
21
  table :miguel_types do
22
+ integer :key, :null => false, :unsigned => false
22
23
  String :string, :null => false
23
24
  String :text, :null => false, :text => true
24
25
  File :blob, :null => false
@@ -29,7 +30,7 @@ table :miguel_types do
29
30
  TrueClass :bool, :null => false
30
31
  TrueClass :true, :null => false, :default => true
31
32
  TrueClass :false, :null => false, :default => false
32
- timestamp :time, :null => false, :default => "0000-00-00 00:00:00"
33
+ timestamp :time, :null => false, :default => "2000-01-01 00:00:00"
33
34
  String :custom, :null => false, :fixed => true, :size => 3
34
35
  end
35
36
  table :native_types do
@@ -39,29 +40,29 @@ table :native_types do
39
40
  timestamp :timestamp, :null => false, :default => "1970-01-02 00:00:00"
40
41
  end
41
42
  table :timestamps do
42
- timestamp :t1, :null => false, :default => "0000-00-00 00:00:00"
43
+ timestamp :t1, :null => false, :default => "2000-01-01 00:00:00"
43
44
  timestamp :t2, :null => true, :default => nil
44
- timestamp :create_time, :null => false, :default => "0000-00-00 00:00:00"
45
- timestamp :update_time, :null => false, :default => "0000-00-00 00:00:00"
45
+ timestamp :create_time, :null => false, :default => "2000-01-01 00:00:00"
46
+ timestamp :update_time, :null => false, :default => "2000-01-01 00:00:00"
46
47
  end
47
48
  table :users do
48
- primary_key :id, :null => false, :unsigned => false, :type => :integer
49
+ primary_key :id, :null => false, :unsigned => false
49
50
  String :name, :null => false
50
51
  index [:name], :null => false, :unique => true
51
52
  end
52
53
  table :simple do
53
- primary_key :id, :null => false, :unsigned => false, :type => :integer
54
- integer :user_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
54
+ primary_key :id, :null => false, :unsigned => false
55
+ integer :user_id, :null => false, :key => [:id], :unsigned => false
55
56
  index [:user_id], :null => false
56
- foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false, :type => :integer
57
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false
57
58
  end
58
59
  table :reuse do
59
- primary_key :user_id, :null => false, :unsigned => false, :type => :integer
60
+ primary_key :user_id, :null => false, :unsigned => false
60
61
  foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false
61
62
  end
62
63
  table :compound do
63
- integer :a, :null => false, :unsigned => true
64
- integer :b, :null => false, :unsigned => true
64
+ Integer :a, :null => false
65
+ Integer :b, :null => false
65
66
  primary_key [:a, :b], :null => false, :unsigned => false
66
67
  String :c, :null => false
67
68
  integer :d, :null => false, :unsigned => false
@@ -82,8 +83,8 @@ table :null do
82
83
  TrueClass :true, :null => true, :default => true
83
84
  TrueClass :false, :null => true, :default => false
84
85
  timestamp :t, :null => true, :default => nil
85
- integer :user_id, :null => true, :key => [:id], :unsigned => false, :type => :integer
86
- foreign_key [:user_id], :users, :null => true, :key => [:id], :unsigned => false, :type => :integer
86
+ integer :user_id, :null => true, :key => [:id], :unsigned => false
87
+ foreign_key [:user_id], :users, :null => true, :key => [:id], :unsigned => false
87
88
  end
88
89
  table :defaults do
89
90
  String :string, :null => false, :default => "abc"
@@ -95,21 +96,21 @@ table :defaults do
95
96
  timestamp :time, :null => false, :default => "2037-12-31 23:59:59"
96
97
  end
97
98
  table :simple_users do
98
- integer :user_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
99
- integer :simple_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
99
+ integer :user_id, :null => false, :key => [:id], :unsigned => false
100
+ integer :simple_id, :null => false, :key => [:id], :unsigned => false
100
101
  primary_key [:user_id, :simple_id], :null => false, :unsigned => false
101
102
  index [:simple_id, :user_id], :null => false, :unique => true
102
- foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false, :type => :integer
103
- foreign_key [:simple_id], :simple, :null => false, :key => [:id], :unsigned => false, :type => :integer
103
+ foreign_key [:user_id], :users, :null => false, :key => [:id], :unsigned => false
104
+ foreign_key [:simple_id], :simple, :null => false, :key => [:id], :unsigned => false
104
105
  end
105
106
  table :self_join do
106
- integer :left_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
107
- integer :right_id, :null => false, :key => [:id], :unsigned => false, :type => :integer
107
+ integer :left_id, :null => false, :key => [:id], :unsigned => false
108
+ integer :right_id, :null => false, :key => [:id], :unsigned => false
108
109
  primary_key [:left_id, :right_id], :null => false, :unsigned => false
109
- timestamp :create_time, :null => false, :default => "0000-00-00 00:00:00"
110
- timestamp :update_time, :null => false, :default => "0000-00-00 00:00:00"
110
+ timestamp :create_time, :null => false, :default => "2000-01-01 00:00:00"
111
+ timestamp :update_time, :null => false, :default => "2000-01-01 00:00:00"
111
112
  index [:right_id, :left_id], :null => false, :unique => true
112
113
  index [:create_time], :null => false
113
- foreign_key [:left_id], :users, :null => false, :key => [:id], :unsigned => false, :type => :integer
114
- foreign_key [:right_id], :users, :null => false, :key => [:id], :unsigned => false, :type => :integer
114
+ foreign_key [:left_id], :users, :null => false, :key => [:id], :unsigned => false
115
+ foreign_key [:right_id], :users, :null => false, :key => [:id], :unsigned => false
115
116
  end